diff --git a/share/man/man4/rktemp.4 b/share/man/man4/rktemp.4 index 55e3e4b74..79c7d104d 100644 --- a/share/man/man4/rktemp.4 +++ b/share/man/man4/rktemp.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: rktemp.4,v 1.4 2020/06/20 21:16:14 jmc Exp $ +.\" $OpenBSD: rktemp.4,v 1.5 2024/06/12 09:08:43 kettenis Exp $ .\" .\" Copyright (c) 2016 Mark Kettenis .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 20 2020 $ +.Dd $Mdocdate: June 12 2024 $ .Dt RKTEMP 4 .Os .Sh NAME @@ -26,7 +26,7 @@ The .Nm driver provides support for the temperature sensor found on the -Rockchip RK3288, RK3328 and RK3399 SoCs. +Rockchip RK3288, RK3308, RK3328, RK3399 RK356x and RK3588 SoCs. It configures the SoC to reset itself if the temperature raises above a certain temperature to protect it from damage caused by overheating. .Pp diff --git a/sys/arch/amd64/amd64/cacheinfo.c b/sys/arch/amd64/amd64/cacheinfo.c index df94f039e..331c6c7eb 100644 --- a/sys/arch/amd64/amd64/cacheinfo.c +++ b/sys/arch/amd64/amd64/cacheinfo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cacheinfo.c,v 1.14 2024/05/08 18:00:55 guenther Exp $ */ +/* $OpenBSD: cacheinfo.c,v 1.15 2024/06/13 02:19:20 guenther Exp $ */ /* * Copyright (c) 2022 Jonathan Gray @@ -246,8 +246,8 @@ intel_print_cacheinfo(struct cpu_info *ci, u_int fn) } /* print lower levels that were the same */ for (i = 0; i < leaf; i++) - intel_print_one_cache(ci, i, prev_cache[leaf][0], - prev_cache[leaf][1], prev_cache[leaf][2]); + intel_print_one_cache(ci, i, prev_cache[i][0], + prev_cache[i][1], prev_cache[i][2]); /* print this (differing) level and higher levels */ goto printit; } diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c index 8acf196ce..ddcb29aac 100644 --- a/sys/arch/amd64/amd64/conf.c +++ b/sys/arch/amd64/amd64/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.80 2024/06/11 09:21:32 jsg Exp $ */ +/* $OpenBSD: conf.c,v 1.81 2024/06/12 12:54:54 bluhm Exp $ */ /* * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. @@ -98,6 +98,15 @@ int nblkdev = nitems(bdevsw); (dev_type_stop((*))) enodev, 0, \ (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } +/* open, close, ioctl */ +#define cdev_psp_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), \ + (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, \ + dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, \ + (dev_type_mmap((*))) enodev, 0, 0, seltrue_kqfilter } + #define mmread mmrw #define mmwrite mmrw cdev_decl(mm); @@ -143,6 +152,8 @@ cdev_decl(nvram); #include "drm.h" #include "viocon.h" cdev_decl(viocon); +#include "ccp.h" +cdev_decl(psp); #include "wsdisplay.h" #include "wskbd.h" @@ -281,6 +292,7 @@ struct cdevsw cdevsw[] = cdev_fido_init(NFIDO,fido), /* 98: FIDO/U2F security keys */ cdev_pppx_init(NPPPX,pppac), /* 99: PPP Access Concentrator */ cdev_ujoy_init(NUJOY,ujoy), /* 100: USB joystick/gamecontroller */ + cdev_psp_init(NCCP,psp), /* 101: PSP */ }; int nchrdev = nitems(cdevsw); diff --git a/sys/conf/files b/sys/conf/files index dc2ecc291..1be0a066e 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.732 2024/05/29 13:56:49 mglocker Exp $ +# $OpenBSD: files,v 1.733 2024/06/12 12:54:54 bluhm Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -467,7 +467,7 @@ file dev/usb/xhci.c xhci needs-flag # AMD Cryptographic Co-processor device ccp -file dev/ic/ccp.c ccp +file dev/ic/ccp.c ccp needs-flag # SDHC SD/MMC controller define sdhc diff --git a/sys/dev/fdt/rktemp.c b/sys/dev/fdt/rktemp.c index fb8cd2a57..ce11c36cb 100644 --- a/sys/dev/fdt/rktemp.c +++ b/sys/dev/fdt/rktemp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rktemp.c,v 1.12 2023/03/05 09:57:32 kettenis Exp $ */ +/* $OpenBSD: rktemp.c,v 1.13 2024/06/12 09:06:15 kettenis Exp $ */ /* * Copyright (c) 2017 Mark Kettenis * @@ -36,43 +36,38 @@ #define TSADC_USER_CON_INTER_PD_SOC_SHIFT 6 #define TSADC_AUTO_CON 0x0004 #define TSADC_AUTO_CON_TSHUT_POLARITY (1 << 8) -#define TSADC_AUTO_CON_SRC3_EN (1 << 7) -#define TSADC_AUTO_CON_SRC2_EN (1 << 6) -#define TSADC_AUTO_CON_SRC1_EN (1 << 5) -#define TSADC_AUTO_CON_SRC0_EN (1 << 4) +#define TSADC_AUTO_CON_SRC_EN(ch) (1 << ((ch) + 4)) #define TSADC_AUTO_CON_TSADC_Q_SEL (1 << 1) #define TSADC_AUTO_CON_AUTO_EN (1 << 0) #define TSADC_INT_EN 0x0008 -#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC3 (1 << 11) -#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC2 (1 << 10) -#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 (1 << 9) -#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 (1 << 8) -#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC3 (1 << 7) -#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC2 (1 << 6) -#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 (1 << 5) -#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 (1 << 4) +#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC(ch) (1 << ((ch) + 8)) +#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(ch) (1 << ((ch) + 4)) #define TSADC_INT_PD 0x000c -#define TSADC_INT_PD_TSHUT_O_SRC0 (1 << 4) -#define TSADC_INT_PD_TSHUT_O_SRC1 (1 << 5) -#define TSADC_INT_PD_TSHUT_O_SRC2 (1 << 6) -#define TSADC_INT_PD_TSHUT_O_SRC3 (1 << 7) -#define TSADC_DATA0 0x0020 -#define TSADC_DATA1 0x0024 -#define TSADC_DATA2 0x0028 -#define TSADC_DATA3 0x002c -#define TSADC_COMP0_INT 0x0030 -#define TSADC_COMP1_INT 0x0034 -#define TSADC_COMP2_INT 0x0038 -#define TSADC_COMP3_INT 0x003c -#define TSADC_COMP0_SHUT 0x0040 -#define TSADC_COMP1_SHUT 0x0044 -#define TSADC_COMP2_SHUT 0x0048 -#define TSADC_COMP3_SHUT 0x004c +#define TSADC_INT_PD_TSHUT_O_SRC(ch) (1 << ((ch) + 4)) +#define TSADC_DATA(ch) (0x0020 + (ch) * 4) +#define TSADC_COMP_INT(ch) (0x0030 + (ch) * 4) +#define TSADC_COMP_SHUT(ch) (0x0040 + (ch) * 4) #define TSADC_HIGHT_INT_DEBOUNCE 0x0060 #define TSADC_HIGHT_TSHUT_DEBOUNCE 0x0064 #define TSADC_AUTO_PERIOD 0x0068 #define TSADC_AUTO_PERIOD_HT 0x006c +/* RK3588 */ +#define TSADC_V3_AUTO_SRC 0x000c +#define TSADC_V3_AUTO_SRC_CH(ch) (1 << (ch)) +#define TSADC_V3_GPIO_EN 0x0018 +#define TSADC_V3_GPIO_EN_CH(ch) (1 << (ch)) +#define TSADC_V3_CRU_EN 0x001c +#define TSADC_V3_CRU_EN_CH(ch) (1 << (ch)) +#define TSADC_V3_HLT_INT_PD 0x0024 +#define TSADC_V3_HT_INT_STATUS(ch) (1 << (ch)) +#define TSADC_V3_DATA(ch) (0x002c + (ch) * 4) +#define TSADC_V3_COMP_SHUT(ch) (0x010c + (ch) * 4) +#define TSADC_V3_HIGHT_INT_DEBOUNCE 0x014c +#define TSADC_V3_HIGHT_TSHUT_DEBOUNCE 0x0150 +#define TSADC_V3_AUTO_PERIOD 0x0154 +#define TSADC_V3_AUTO_PERIOD_HT 0x0158 + /* RK3568 */ #define RK3568_GRF_TSADC_CON 0x0600 #define RK3568_GRF_TSADC_EN (1 << 8) @@ -248,16 +243,36 @@ const struct rktemp_entry rk3568_temps[] = { const char *const rk3568_names[] = { "CPU", "GPU" }; +/* RK3588 conversion table. */ +const struct rktemp_entry rk3588_temps[] = { + { -40000, 215 }, + { 25000, 285 }, + { 85000, 350 }, + { 125000, 395 }, +}; + +const char *const rk3588_names[] = { + "Top", + "CPU (big0)", + "CPU (big1)", + "CPU (little)", + "Center", + "GPU", + "NPU" +}; + struct rktemp_softc { struct device sc_dev; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; int sc_node; + bus_size_t sc_data0; + const struct rktemp_entry *sc_temps; int sc_ntemps; - struct ksensor sc_sensors[3]; + struct ksensor sc_sensors[7]; int sc_nsensors; struct ksensordev sc_sensordev; @@ -291,7 +306,8 @@ rktemp_match(struct device *parent, void *match, void *aux) OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") || OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") || OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc") || - OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc")); + OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc") || + OF_is_compatible(faa->fa_node, "rockchip,rk3588-tsadc")); } void @@ -301,8 +317,7 @@ rktemp_attach(struct device *parent, struct device *self, void *aux) struct fdt_attach_args *faa = aux; const char *const *names; uint32_t mode, polarity, temp; - uint32_t auto_con, int_en; - uint32_t inter_pd_soc; + uint32_t auto_con, inter_pd_soc; int auto_period, auto_period_ht; int i; @@ -354,7 +369,7 @@ rktemp_attach(struct device *parent, struct device *self, void *aux) inter_pd_soc = 13; auto_period = 1875; /* 2.5 ms */ auto_period_ht = 1875; /* 2.5 ms */ - } else { + } else if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) { sc->sc_temps = rk3568_temps; sc->sc_ntemps = nitems(rk3568_temps); sc->sc_nsensors = 2; @@ -362,6 +377,14 @@ rktemp_attach(struct device *parent, struct device *self, void *aux) inter_pd_soc = 63; /* 97 us */ auto_period = 1622; /* 2.5 ms */ auto_period_ht = 1622; /* 2.5 ms */ + } else { + sc->sc_temps = rk3588_temps; + sc->sc_ntemps = nitems(rk3588_temps); + sc->sc_nsensors = 7; + names = rk3588_names; + inter_pd_soc = 0; + auto_period = 5000; /* 2.5 ms */ + auto_period_ht = 5000; /* 2.5 ms */ } pinctrl_byname(sc->sc_node, "init"); @@ -371,57 +394,110 @@ rktemp_attach(struct device *parent, struct device *self, void *aux) clock_enable(sc->sc_node, "apb_pclk"); /* Reset the TS-ADC controller block. */ - reset_assert(sc->sc_node, "tsadc-apb"); + reset_assert_all(sc->sc_node); delay(10); - reset_deassert(sc->sc_node, "tsadc-apb"); + reset_deassert_all(sc->sc_node); mode = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-mode", 1); polarity = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-polarity", 0); temp = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-temp", 95000); - HWRITE4(sc, TSADC_USER_CON, - inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT); - HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period); - HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht); - HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4); - HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4); + if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) { + uint32_t gpio_en, cru_en; - if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) - rktemp_rk3568_init(sc); + sc->sc_data0 = TSADC_V3_DATA(0); + + HWRITE4(sc, TSADC_V3_AUTO_PERIOD, auto_period); + HWRITE4(sc, TSADC_V3_AUTO_PERIOD_HT, auto_period_ht); + HWRITE4(sc, TSADC_V3_HIGHT_INT_DEBOUNCE, 4); + HWRITE4(sc, TSADC_V3_HIGHT_TSHUT_DEBOUNCE, 4); - auto_con = HREAD4(sc, TSADC_AUTO_CON); - auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL; - if (polarity) - auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY; - HWRITE4(sc, TSADC_AUTO_CON, auto_con); + auto_con = TSADC_AUTO_CON_TSHUT_POLARITY << 16; + if (polarity) + auto_con = TSADC_AUTO_CON_TSHUT_POLARITY; + HWRITE4(sc, TSADC_AUTO_CON, auto_con); - /* Set shutdown limit. */ - for (i = 0; i < sc->sc_nsensors; i++) { - HWRITE4(sc, TSADC_COMP0_SHUT + i * 4, - rktemp_calc_code(sc, temp)); - auto_con |= (TSADC_AUTO_CON_SRC0_EN << i); + /* Set shutdown limit. */ + for (i = 0; i < sc->sc_nsensors; i++) { + HWRITE4(sc, TSADC_V3_COMP_SHUT(i), + rktemp_calc_code(sc, temp)); + HWRITE4(sc, TSADC_V3_AUTO_SRC, + TSADC_V3_AUTO_SRC_CH(i) << 16 | + TSADC_V3_AUTO_SRC_CH(i)); + } + + /* Clear shutdown output status. */ + for (i = 0; i < sc->sc_nsensors; i++) { + HWRITE4(sc, TSADC_V3_HLT_INT_PD, + TSADC_V3_HT_INT_STATUS(i)); + } + + /* Configure mode. */ + gpio_en = cru_en = 0; + for (i = 0; i < sc->sc_nsensors; i++) { + gpio_en |= TSADC_V3_GPIO_EN_CH(i) << 16; + cru_en |= TSADC_V3_CRU_EN_CH(i) << 16; + if (mode) + gpio_en |= TSADC_V3_GPIO_EN_CH(i); + else + cru_en |= TSADC_V3_CRU_EN_CH(i); + } + HWRITE4(sc, TSADC_V3_GPIO_EN, gpio_en); + HWRITE4(sc, TSADC_V3_CRU_EN, cru_en); + } else { + uint32_t int_en; + + sc->sc_data0 = TSADC_DATA(0); + + HWRITE4(sc, TSADC_USER_CON, + inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT); + HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period); + HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht); + HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4); + HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4); + + if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) + rktemp_rk3568_init(sc); + + auto_con = HREAD4(sc, TSADC_AUTO_CON); + auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL; + if (polarity) + auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY; + HWRITE4(sc, TSADC_AUTO_CON, auto_con); + + /* Set shutdown limit. */ + for (i = 0; i < sc->sc_nsensors; i++) { + HWRITE4(sc, TSADC_COMP_SHUT(i), + rktemp_calc_code(sc, temp)); + auto_con |= (TSADC_AUTO_CON_SRC_EN(i)); + } + HWRITE4(sc, TSADC_AUTO_CON, auto_con); + + /* Clear shutdown output status. */ + for (i = 0; i < sc->sc_nsensors; i++) + HWRITE4(sc, TSADC_INT_PD, TSADC_INT_PD_TSHUT_O_SRC(i)); + + /* Configure mode. */ + int_en = HREAD4(sc, TSADC_INT_EN); + for (i = 0; i < sc->sc_nsensors; i++) { + if (mode) + int_en |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(i); + else + int_en |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC(i); + } + HWRITE4(sc, TSADC_INT_EN, int_en); } - HWRITE4(sc, TSADC_AUTO_CON, auto_con); - - /* Clear shutdown output status. */ - for (i = 0; i < sc->sc_nsensors; i++) - HWRITE4(sc, TSADC_INT_PD, (TSADC_INT_PD_TSHUT_O_SRC0 << i)); - - /* Configure mode. */ - int_en = HREAD4(sc, TSADC_INT_EN); - for (i = 0; i < sc->sc_nsensors; i++) { - if (mode) - int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i); - else - int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i); - } - HWRITE4(sc, TSADC_INT_EN, int_en); pinctrl_byname(sc->sc_node, "default"); /* Finally turn on the ADC. */ - auto_con |= TSADC_AUTO_CON_AUTO_EN; - HWRITE4(sc, TSADC_AUTO_CON, auto_con); + if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) { + HWRITE4(sc, TSADC_AUTO_CON, + TSADC_AUTO_CON_AUTO_EN << 16 | TSADC_AUTO_CON_AUTO_EN); + } else { + auto_con |= TSADC_AUTO_CON_AUTO_EN; + HWRITE4(sc, TSADC_AUTO_CON, auto_con); + } /* Register sensors. */ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, @@ -557,7 +633,7 @@ rktemp_refresh_sensors(void *arg) int i; for (i = 0; i < sc->sc_nsensors; i++) { - code = HREAD4(sc, TSADC_DATA0 + i * 4); + code = HREAD4(sc, sc->sc_data0 + (i * 4)); temp = rktemp_calc_temp(sc, code); sc->sc_sensors[i].value = 273150000 + 1000 * temp; if (rktemp_valid(sc, code)) @@ -577,7 +653,7 @@ rktemp_get_temperature(void *cookie, uint32_t *cells) if (idx >= sc->sc_nsensors) return THERMAL_SENSOR_MAX; - code = HREAD4(sc, TSADC_DATA0 + idx * 4); + code = HREAD4(sc, sc->sc_data0 + (idx * 4)); if (rktemp_valid(sc, code)) return rktemp_calc_temp(sc, code); else diff --git a/sys/dev/ic/ccp.c b/sys/dev/ic/ccp.c index 5a04b7393..5e8a9392c 100644 --- a/sys/dev/ic/ccp.c +++ b/sys/dev/ic/ccp.c @@ -1,7 +1,8 @@ -/* $OpenBSD: ccp.c,v 1.3 2020/05/29 04:42:25 deraadt Exp $ */ +/* $OpenBSD: ccp.c,v 1.4 2024/06/12 12:54:54 bluhm Exp $ */ /* * Copyright (c) 2018 David Gwynne + * Copyright (c) 2023, 2024 Hans-Joerg Hoexer * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,6 +27,12 @@ #include +#ifdef __amd64__ +#include +#include +#include +#endif + #include #define CCP_REG_TRNG 0xc @@ -38,13 +45,23 @@ struct cfdriver ccp_cd = { DV_DULL }; +#ifdef __amd64__ +struct ccp_softc *ccp_softc; + +int psp_get_pstatus(struct psp_platform_status *); +int psp_init(struct psp_init *); +#endif + void ccp_attach(struct ccp_softc *sc) { timeout_set(&sc->sc_tick, ccp_rng, sc); ccp_rng(sc); - printf("\n"); + if (sc->sc_psp_attached) + printf(", RNG\n"); + else + printf(": RNG\n"); } static void @@ -59,3 +76,585 @@ ccp_rng(void *arg) timeout_add_msec(&sc->sc_tick, 100); } + +#ifdef __amd64__ +int +psp_sev_intr(struct ccp_softc *sc, uint32_t status) +{ + if (!(status & PSP_CMDRESP_COMPLETE)) + return (0); + + wakeup(sc); + + return (1); +} + +int +psp_attach(struct ccp_softc *sc) +{ + struct psp_platform_status pst; + struct psp_init init; + size_t size; + int nsegs; + + if (!(sc->sc_capabilities & PSP_CAP_SEV)) + return (0); + + rw_init(&sc->sc_lock, "ccp_lock"); + + /* create and map SEV command buffer */ + sc->sc_cmd_size = size = PAGE_SIZE; + if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, + BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, + &sc->sc_cmd_map) != 0) + return (0); + + if (bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_cmd_seg, 1, + &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) + goto fail_0; + + if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_seg, nsegs, size, + &sc->sc_cmd_kva, BUS_DMA_WAITOK) != 0) + goto fail_1; + + if (bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_map, sc->sc_cmd_kva, + size, NULL, BUS_DMA_WAITOK) != 0) + goto fail_2; + + sc->sc_sev_intr = psp_sev_intr; + ccp_softc = sc; + + if (psp_get_pstatus(&pst) || pst.state != 0) + goto fail_3; + + printf(", SEV"); + + /* + * create and map Trusted Memory Region (TMR); size 1 Mbyte, + * needs to be aligend to 1 Mbyte. + */ + sc->sc_tmr_size = size = PSP_TMR_SIZE; + if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, + BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, + &sc->sc_tmr_map) != 0) + goto fail_3; + + if (bus_dmamem_alloc(sc->sc_dmat, size, size, 0, &sc->sc_tmr_seg, 1, + &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) + goto fail_4; + + if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size, + &sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0) + goto fail_5; + + if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva, + size, NULL, BUS_DMA_WAITOK) != 0) + goto fail_6; + + memset(&init, 0, sizeof(init)); + init.enable_es = 1; + init.tmr_length = PSP_TMR_SIZE; + init.tmr_paddr = sc->sc_tmr_map->dm_segs[0].ds_addr; + if (psp_init(&init)) + goto fail_7; + + psp_get_pstatus(&pst); + if ((pst.state == 1) && (pst.cfges_build & 0x1)) + printf(", SEV-ES"); + + sc->sc_psp_attached = 1; + + return (1); + +fail_7: + bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map); +fail_6: + bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size); +fail_5: + bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1); +fail_4: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map); +fail_3: + bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_map); +fail_2: + bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_kva, size); +fail_1: + bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_seg, 1); +fail_0: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map); + + ccp_softc = NULL; + + return (0); +} + +static int +ccp_wait(struct ccp_softc *sc, uint32_t *status, int poll) +{ + uint32_t cmdword; + int count; + + if (poll) { + count = 0; + while (count++ < 10) { + cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PSP_REG_CMDRESP); + if (cmdword & PSP_CMDRESP_RESPONSE) + goto done; + delay(5000); + } + + /* timeout */ + return (1); + } + + if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(1)) == EWOULDBLOCK) + return (1); + +done: + if (status) { + *status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PSP_REG_CMDRESP); + } + + return (0); +} + +static int +ccp_docmd(struct ccp_softc *sc, int cmd, uint64_t paddr) +{ + uint32_t plo, phi, cmdword, status; + + plo = ((paddr >> 0) & 0xffffffff); + phi = ((paddr >> 32) & 0xffffffff); + cmdword = (cmd & 0x3f) << 16; + if (!cold) + cmdword |= PSP_CMDRESP_IOC; + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRLO, plo); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRHI, phi); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_CMDRESP, cmdword); + + if (ccp_wait(sc, &status, cold)) + return (1); + + /* Did PSP sent a response code? */ + if (status & PSP_CMDRESP_RESPONSE) { + if ((status & PSP_STATUS_MASK) != PSP_STATUS_SUCCESS) { + printf("%s: command failed: 0x%x\n", __func__, + (status & PSP_STATUS_MASK)); + return (1); + } + } + + return (0); +} + +int +psp_init(struct psp_init *uinit) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_init *init; + int ret; + + init = (struct psp_init *)sc->sc_cmd_kva; + bzero(init, sizeof(*init)); + + init->enable_es = uinit->enable_es; + init->tmr_paddr = uinit->tmr_paddr; + init->tmr_length = uinit->tmr_length; + + ret = ccp_docmd(sc, PSP_CMD_INIT, sc->sc_cmd_map->dm_segs[0].ds_addr); + + wbinvd_on_all_cpus(); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_get_pstatus(struct psp_platform_status *ustatus) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_platform_status *status; + int ret; + + status = (struct psp_platform_status *)sc->sc_cmd_kva; + bzero(status, sizeof(*status)); + + ret = ccp_docmd(sc, PSP_CMD_PLATFORMSTATUS, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + bcopy(status, ustatus, sizeof(*ustatus)); + + return (0); +} + +int +psp_df_flush(void) +{ + struct ccp_softc *sc = ccp_softc; + int ret; + + wbinvd_on_all_cpus(); + + ret = ccp_docmd(sc, PSP_CMD_DF_FLUSH, 0x0); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_decommission(struct psp_decommission *udecom) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_decommission *decom; + int ret; + + decom = (struct psp_decommission *)sc->sc_cmd_kva; + bzero(decom, sizeof(*decom)); + + decom->handle = udecom->handle; + + ret = ccp_docmd(sc, PSP_CMD_DECOMMISSION, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_get_gstatus(struct psp_guest_status *ustatus) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_guest_status *status; + int ret; + + status = (struct psp_guest_status *)sc->sc_cmd_kva; + bzero(status, sizeof(*status)); + + status->handle = ustatus->handle; + + ret = ccp_docmd(sc, PSP_CMD_GUESTSTATUS, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + ustatus->policy = status->policy; + ustatus->asid = status->asid; + ustatus->state = status->state; + + return (0); +} + +int +psp_launch_start(struct psp_launch_start *ustart) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_launch_start *start; + int ret; + + start = (struct psp_launch_start *)sc->sc_cmd_kva; + bzero(start, sizeof(*start)); + + start->handle = ustart->handle; + start->policy = ustart->policy; + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_START, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + /* If requested, return new handle. */ + if (ustart->handle == 0) + ustart->handle = start->handle; + + return (0); +} + +int +psp_launch_update_data(struct psp_launch_update_data *ulud, struct proc *p) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_launch_update_data *ludata; + pmap_t pmap; + vaddr_t v, next, end; + size_t size, len, off; + int ret; + + /* Ensure AES_XTS_BLOCKSIZE alignment and multiplicity. */ + if ((ulud->paddr & (AES_XTS_BLOCKSIZE - 1)) != 0 || + (ulud->length % AES_XTS_BLOCKSIZE) != 0) + return (EINVAL); + + ludata = (struct psp_launch_update_data *)sc->sc_cmd_kva; + bzero(ludata, sizeof(*ludata)); + + ludata->handle = ulud->handle; + + /* Drain caches before we encrypt memory. */ + wbinvd_on_all_cpus(); + + /* + * Launch update one physical page at a time. We could + * optimise this for contiguous pages of physical memory. + * + * vmd(8) provides the guest physical address, thus convert + * to system physical address. + */ + pmap = vm_map_pmap(&p->p_vmspace->vm_map); + size = ulud->length; + end = ulud->paddr + ulud->length; + for (v = ulud->paddr; v < end; v = next) { + off = v & PAGE_MASK; + + len = MIN(PAGE_SIZE - off, size); + + /* Wire mapping. */ + if (uvm_map_pageable(&p->p_vmspace->vm_map, v, v+len, FALSE, 0)) + return (EINVAL); + if (!pmap_extract(pmap, v, (paddr_t *)&ludata->paddr)) + return (EINVAL); + ludata->length = len; + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_DATA, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + size -= len; + next = v + len; + } + + return (0); +} + +int +psp_launch_measure(struct psp_launch_measure *ulm) +{ + struct psp_launch_measure *lm; + struct ccp_softc *sc = ccp_softc; + int ret; + uint64_t paddr; + + if (ulm->measure_len != sizeof(ulm->psp_measure)) + return (EINVAL); + + lm = (struct psp_launch_measure *)sc->sc_cmd_kva; + bzero(lm, sizeof(*lm)); + + lm->handle = ulm->handle; + paddr = sc->sc_cmd_map->dm_segs[0].ds_addr; + lm->measure_paddr = + paddr + offsetof(struct psp_launch_measure, psp_measure); + lm->measure_len = sizeof(lm->psp_measure); + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_MEASURE, paddr); + + if (ret != 0 || lm->measure_len != ulm->measure_len) + return (EIO); + + bcopy(&lm->psp_measure, &ulm->psp_measure, ulm->measure_len); + + return (0); +} + +int +psp_launch_finish(struct psp_launch_finish *ulf) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_launch_finish *lf; + int ret; + + lf = (struct psp_launch_finish *)sc->sc_cmd_kva; + bzero(lf, sizeof(*lf)); + + lf->handle = ulf->handle; + + ret = ccp_docmd(sc, PSP_CMD_LAUNCH_FINISH, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_attestation(struct psp_attestation *uat) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_attestation *at; + int ret; + uint64_t paddr; + + if (uat->attest_len != sizeof(uat->psp_report)) + return (EINVAL); + + at = (struct psp_attestation *)sc->sc_cmd_kva; + bzero(at, sizeof(*at)); + + at->handle = uat->handle; + paddr = sc->sc_cmd_map->dm_segs[0].ds_addr; + at->attest_paddr = + paddr + offsetof(struct psp_attestation, psp_report); + bcopy(uat->attest_nonce, at->attest_nonce, sizeof(at->attest_nonce)); + at->attest_len = sizeof(at->psp_report); + + ret = ccp_docmd(sc, PSP_CMD_ATTESTATION, paddr); + + if (ret != 0 || at->attest_len != uat->attest_len) + return (EIO); + + bcopy(&at->psp_report, &uat->psp_report, uat->attest_len); + + return (0); +} + +int +psp_activate(struct psp_activate *uact) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_activate *act; + int ret; + + act = (struct psp_activate *)sc->sc_cmd_kva; + bzero(act, sizeof(*act)); + + act->handle = uact->handle; + act->asid = uact->asid; + + ret = ccp_docmd(sc, PSP_CMD_ACTIVATE, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_deactivate(struct psp_deactivate *udeact) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_deactivate *deact; + int ret; + + deact = (struct psp_deactivate *)sc->sc_cmd_kva; + bzero(deact, sizeof(*deact)); + + deact->handle = udeact->handle; + + ret = ccp_docmd(sc, PSP_CMD_DEACTIVATE, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + return (0); +} + +int +psp_snp_get_pstatus(struct psp_snp_platform_status *ustatus) +{ + struct ccp_softc *sc = ccp_softc; + struct psp_snp_platform_status *status; + int ret; + + status = (struct psp_snp_platform_status *)sc->sc_cmd_kva; + bzero(status, sizeof(*status)); + + ret = ccp_docmd(sc, PSP_CMD_SNP_PLATFORMSTATUS, + sc->sc_cmd_map->dm_segs[0].ds_addr); + + if (ret != 0) + return (EIO); + + bcopy(status, ustatus, sizeof(*ustatus)); + + return (0); +} + +int +pspopen(dev_t dev, int flag, int mode, struct proc *p) +{ + if (ccp_softc == NULL) + return (ENODEV); + + return (0); +} + +int +pspclose(dev_t dev, int flag, int mode, struct proc *p) +{ + return (0); +} + +int +pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + int ret; + + rw_enter_write(&ccp_softc->sc_lock); + + switch (cmd) { + case PSP_IOC_GET_PSTATUS: + ret = psp_get_pstatus((struct psp_platform_status *)data); + break; + case PSP_IOC_DF_FLUSH: + ret = psp_df_flush(); + break; + case PSP_IOC_DECOMMISSION: + ret = psp_decommission((struct psp_decommission *)data); + break; + case PSP_IOC_GET_GSTATUS: + ret = psp_get_gstatus((struct psp_guest_status *)data); + break; + case PSP_IOC_LAUNCH_START: + ret = psp_launch_start((struct psp_launch_start *)data); + break; + case PSP_IOC_LAUNCH_UPDATE_DATA: + ret = psp_launch_update_data( + (struct psp_launch_update_data *)data, p); + break; + case PSP_IOC_LAUNCH_MEASURE: + ret = psp_launch_measure((struct psp_launch_measure *)data); + break; + case PSP_IOC_LAUNCH_FINISH: + ret = psp_launch_finish((struct psp_launch_finish *)data); + break; + case PSP_IOC_ATTESTATION: + ret = psp_attestation((struct psp_attestation *)data); + break; + case PSP_IOC_ACTIVATE: + ret = psp_activate((struct psp_activate *)data); + break; + case PSP_IOC_DEACTIVATE: + ret = psp_deactivate((struct psp_deactivate *)data); + break; + case PSP_IOC_SNP_GET_PSTATUS: + ret = + psp_snp_get_pstatus((struct psp_snp_platform_status *)data); + break; + default: + printf("%s: unkown ioctl code 0x%lx\n", __func__, cmd); + ret = ENOTTY; + } + + rw_exit_write(&ccp_softc->sc_lock); + + return (ret); +} +#endif /* __amd64__ */ diff --git a/sys/dev/ic/ccpvar.h b/sys/dev/ic/ccpvar.h index 237a5d45f..6b4675ff6 100644 --- a/sys/dev/ic/ccpvar.h +++ b/sys/dev/ic/ccpvar.h @@ -1,7 +1,8 @@ -/* $OpenBSD: ccpvar.h,v 1.1 2018/04/20 04:37:21 dlg Exp $ */ +/* $OpenBSD: ccpvar.h,v 1.2 2024/06/12 12:54:54 bluhm Exp $ */ /* * Copyright (c) 2018 David Gwynne + * Copyright (c) 2023, 2024 Hans-Joerg Hoexer * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,6 +25,266 @@ struct ccp_softc { bus_space_handle_t sc_ioh; struct timeout sc_tick; + + bus_size_t sc_size; + int sc_psp_attached; + +#ifdef __amd64__ + bus_dma_tag_t sc_dmat; + uint32_t sc_capabilities; + int (*sc_sev_intr)(struct ccp_softc *, uint32_t); + void * sc_ih; + + bus_dmamap_t sc_cmd_map; + bus_dma_segment_t sc_cmd_seg; + size_t sc_cmd_size; + caddr_t sc_cmd_kva; + + bus_dmamap_t sc_tmr_map; + bus_dma_segment_t sc_tmr_seg; + size_t sc_tmr_size; + caddr_t sc_tmr_kva; + + struct rwlock sc_lock; +#endif }; +#ifdef __amd64__ + +#include +#include + +/* AMD 17h */ +#define PSP_REG_INTEN 0x10690 +#define PSP_REG_INTSTS 0x10694 +#define PSP_REG_CMDRESP 0x10980 +#define PSP_REG_ADDRLO 0x109e0 +#define PSP_REG_ADDRHI 0x109e4 +#define PSP_REG_CAPABILITIES 0x109fc + +#define PSP_PSTATE_UNINIT 0x0 +#define PSP_PSTATE_INIT 0x1 +#define PSP_PSTATE_WORKING 0x2 + +#define PSP_GSTATE_UNINIT 0x0 +#define PSP_GSTATE_LUPDATE 0x1 +#define PSP_GSTATE_LSECRET 0x2 +#define PSP_GSTATE_RUNNING 0x3 +#define PSP_GSTATE_SUPDATE 0x4 +#define PSP_GSTATE_RUPDATE 0x5 +#define PSP_GSTATE_SENT 0x6 + +#define PSP_CAP_SEV (1 << 0) +#define PSP_CAP_TEE (1 << 1) +#define PSP_CAP_DBC_THRU_EXT (1 << 2) +#define PSP_CAP_SECURITY_REPORTING (1 << 7) +#define PSP_CAP_SECURITY_FUSED_PART (1 << 8) +#define PSP_CAP_SECURITY_DEBUG_LOCK_ON (1 << 10) +#define PSP_CAP_SECURITY_TSME_STATUS (1 << 13) +#define PSP_CAP_SECURITY_ANTI_ROLLBACK_STATUS (1 << 15) +#define PSP_CAP_SECURITY_RPMC_PRODUCTION_ENABLED (1 << 16) +#define PSP_CAP_SECURITY_RPMC_SPIROM_AVAILABLE (1 << 17) +#define PSP_CAP_SECURITY_HSP_TPM_AVAILABLE (1 << 18) +#define PSP_CAP_SECURITY_ROM_ARMOR_ENFORCED (1 << 19) + +#define PSP_CAP_BITS "\20\001SEV\002TEE\003DBC_THRU_EXT\010REPORTING\011FUSED_PART\013DEBUG_LOCK_ON\016TSME_STATUS\020ANTI_ROLLBACK_STATUS\021RPMC_PRODUCTION_ENABLED\022RPMC_SPIROM_AVAILABLE\023HSP_TPM_AVAILABLE\024ROM_ARMOR_ENFORCED" + +#define PSP_CMDRESP_IOC (1 << 0) +#define PSP_CMDRESP_COMPLETE (1 << 1) +#define PSP_CMDRESP_RESPONSE (1 << 31) + +#define PSP_STATUS_MASK 0xffff +#define PSP_STATUS_SUCCESS 0x0000 +#define PSP_STATUS_INVALID_PLATFORM_STATE 0x0001 + +#define PSP_TMR_SIZE (1024*1024) /* 1 Mb */ + +#define PSP_SUCCESS 0x0000 +#define PSP_INVALID_ADDRESS 0x0009 + +/* Selection of PSP commands of the SEV API Version 0.24 */ + +#define PSP_CMD_INIT 0x1 +#define PSP_CMD_PLATFORMSTATUS 0x4 +#define PSP_CMD_DF_FLUSH 0xa +#define PSP_CMD_DECOMMISSION 0x20 +#define PSP_CMD_ACTIVATE 0x21 +#define PSP_CMD_DEACTIVATE 0x22 +#define PSP_CMD_GUESTSTATUS 0x23 +#define PSP_CMD_LAUNCH_START 0x30 +#define PSP_CMD_LAUNCH_UPDATE_DATA 0x31 +#define PSP_CMD_LAUNCH_MEASURE 0x33 +#define PSP_CMD_LAUNCH_FINISH 0x35 +#define PSP_CMD_ATTESTATION 0x36 + +struct psp_platform_status { + /* Output parameters from PSP_CMD_PLATFORMSTATUS */ + uint8_t api_major; + uint8_t api_minor; + uint8_t state; + uint8_t owner; + uint32_t cfges_build; + uint32_t guest_count; +} __packed; + +struct psp_guest_status { + /* Input parameter for PSP_CMD_GUESTSTATUS */ + uint32_t handle; + + /* Output parameters from PSP_CMD_GUESTSTATUS */ + uint32_t policy; + uint32_t asid; + uint8_t state; +} __packed; + +struct psp_launch_start { + /* Input/Output parameter for PSP_CMD_LAUNCH_START */ + uint32_t handle; + + /* Input parameters for PSP_CMD_LAUNCH_START */ + uint32_t policy; + + /* The following input parameters are not used yet */ + uint64_t dh_cert_paddr; + uint32_t dh_cert_len; + uint32_t reserved; + uint64_t session_paddr; + uint32_t session_len; +} __packed; + +struct psp_launch_update_data { + /* Input parameters for PSP_CMD_LAUNCH_UPDATE_DATA */ + uint32_t handle; + uint32_t reserved; + uint64_t paddr; + uint32_t length; +} __packed; + +struct psp_measure { + /* Output buffer for PSP_CMD_LAUNCH_MEASURE */ + uint8_t measure[32]; + uint8_t measure_nonce[16]; +} __packed; + +struct psp_launch_measure { + /* Input parameters for PSP_CMD_LAUNCH_MEASURE */ + uint32_t handle; + uint32_t reserved; + uint64_t measure_paddr; + + /* Input/output parameter for PSP_CMD_LAUNCH_MEASURE */ + uint32_t measure_len; + uint32_t padding; + + /* Output buffer from PSP_CMD_LAUNCH_MEASURE */ + struct psp_measure psp_measure; /* 64bit aligned */ +#define measure psp_measure.measure +#define measure_nonce psp_measure.measure_nonce +} __packed; + +struct psp_launch_finish { + /* Input parameter for PSP_CMD_LAUNCH_FINISH */ + uint32_t handle; +} __packed; + +struct psp_report { + /* Output buffer for PSP_CMD_ATTESTATION */ + uint8_t report_nonce[16]; + uint8_t report_launch_digest[32]; + uint32_t report_policy; + uint32_t report_sig_usage; + uint32_t report_sig_algo; + uint32_t reserved2; + uint8_t report_sig1[144]; +} __packed; + +struct psp_attestation { + /* Input parameters for PSP_CMD_ATTESTATION */ + uint32_t handle; + uint32_t reserved; + uint64_t attest_paddr; + uint8_t attest_nonce[16]; + + /* Input/output parameter from PSP_CMD_ATTESTATION */ + uint32_t attest_len; + uint32_t padding; + + /* Output parameter from PSP_CMD_ATTESTATION */ + struct psp_report psp_report; /* 64bit aligned */ +#define report_nonce psp_report.report_nonce +#define report_launch_digest psp_report.report_launch_digest +#define report_policy psp_report.report_policy +#define report_sig_usage psp_report.report_sig_usage; +#define report_report_sig_alg psp_report.report_sig_algo; +#define report_report_sig1 psp_report.report_sig1; +} __packed; + +struct psp_activate { + /* Input parameters for PSP_CMD_ACTIVATE */ + uint32_t handle; + uint32_t asid; +} __packed; + +struct psp_deactivate { + /* Input parameter for PSP_CMD_DEACTIVATE */ + uint32_t handle; +} __packed; + +struct psp_decommission { + /* Input parameter for PSP_CMD_DECOMMISSION */ + uint32_t handle; +} __packed; + +struct psp_init { + /* Output parameters from PSP_CMD_INIT */ + uint32_t enable_es; + uint32_t reserved; + uint64_t tmr_paddr; + uint32_t tmr_length; +} __packed; + + +/* Selection of PSP commands of the SEV-SNP ABI Version 1.55 */ + +#define PSP_CMD_SNP_PLATFORMSTATUS 0x81 + +struct psp_snp_platform_status { + uint8_t api_major; + uint8_t api_minor; + uint8_t state; + uint8_t is_rmp_init; + uint32_t build; + uint32_t features; + uint32_t guest_count; + uint64_t current_tcb; + uint64_t reported_tcb; +} __packed; + +#define PSP_IOC_GET_PSTATUS _IOR('P', 0, struct psp_platform_status) +#define PSP_IOC_DF_FLUSH _IO('P', 1) +#define PSP_IOC_DECOMMISSION _IOW('P', 2, struct psp_decommission) +#define PSP_IOC_GET_GSTATUS _IOWR('P', 3, struct psp_guest_status) +#define PSP_IOC_LAUNCH_START _IOWR('P', 4, struct psp_launch_start) +#define PSP_IOC_LAUNCH_UPDATE_DATA \ + _IOW('P', 5, struct psp_launch_update_data) +#define PSP_IOC_LAUNCH_MEASURE _IOWR('P', 6, struct psp_launch_measure) +#define PSP_IOC_LAUNCH_FINISH _IOW('P', 7, struct psp_launch_finish) +#define PSP_IOC_ATTESTATION _IOWR('P', 8, struct psp_attestation) +#define PSP_IOC_ACTIVATE _IOW('P', 9, struct psp_activate) +#define PSP_IOC_DEACTIVATE _IOW('P', 10, struct psp_deactivate) +#define PSP_IOC_SNP_GET_PSTATUS _IOR('P', 11, struct psp_snp_platform_status) +#endif /* __amd64__ */ + +#ifdef _KERNEL + void ccp_attach(struct ccp_softc *); + +#ifdef __amd64__ +int psp_attach(struct ccp_softc *); + +int pspclose(dev_t, int, int, struct proc *); +int pspopen(dev_t, int, int, struct proc *); +int pspioctl(dev_t, u_long, caddr_t, int, struct proc *); +#endif + +#endif /* _KERNEL */ diff --git a/sys/dev/pci/ccp_pci.c b/sys/dev/pci/ccp_pci.c index 9ad536e0a..3f6df5384 100644 --- a/sys/dev/pci/ccp_pci.c +++ b/sys/dev/pci/ccp_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ccp_pci.c,v 1.9 2024/05/24 06:02:53 jsg Exp $ */ +/* $OpenBSD: ccp_pci.c,v 1.10 2024/06/12 12:54:54 bluhm Exp $ */ /* * Copyright (c) 2018 David Gwynne @@ -33,6 +33,11 @@ int ccp_pci_match(struct device *, void *, void *); void ccp_pci_attach(struct device *, struct device *, void *); +#ifdef __amd64__ +void psp_pci_attach(struct device *, struct device *, void *); +int psp_pci_intr(void *); +#endif + const struct cfattach ccp_pci_ca = { sizeof(struct ccp_softc), ccp_pci_match, @@ -69,10 +74,67 @@ ccp_pci_attach(struct device *parent, struct device *self, void *aux) } if (pci_mapreg_map(pa, CCP_PCI_BAR, memtype, 0, - &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0) != 0) { + &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size, 0) != 0) { printf(": cannot map registers\n"); return; } +#ifdef __amd64__ + psp_pci_attach(parent, self, aux); +#endif + ccp_attach(sc); } + +#ifdef __amd64__ +void +psp_pci_attach(struct device *parent, struct device *self, void *aux) +{ + struct ccp_softc *sc = (struct ccp_softc *)self; + struct pci_attach_args *pa = aux; + pci_intr_handle_t ih; + const char *intrstr = NULL; + + sc->sc_dmat = pa->pa_dmat; + + sc->sc_capabilities = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + PSP_REG_CAPABILITIES); + + /* clear and disable interrupts */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, -1); + + if (pci_intr_map_msix(pa, 0, &ih) != 0 && + pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) { + printf(": couldn't map interrupt\n"); + bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size); + return; + } + + intrstr = pci_intr_string(pa->pa_pc, ih); + sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, psp_pci_intr, + sc, sc->sc_dev.dv_xname); + if (sc->sc_ih != NULL) + printf(": %s", intrstr); + + if (psp_attach(sc)) { + /* enable interrupts */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, -1); + } +} + +int +psp_pci_intr(void *arg) +{ + struct ccp_softc *sc = arg; + uint32_t status; + + status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, status); + + if (sc->sc_sev_intr) + return (sc->sc_sev_intr(sc, status)); + + return (1); +} +#endif /* __amd64__ */ diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c index 2caa16039..2926e69fc 100644 --- a/usr.bin/ssh/servconf.c +++ b/usr.bin/ssh/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.410 2024/06/11 00:36:20 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.411 2024/06/12 22:36:00 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -147,8 +147,10 @@ initialize_server_options(ServerOptions *options) options->per_source_masklen_ipv6 = -1; options->per_source_penalty_exempt = NULL; options->per_source_penalty.enabled = -1; - options->per_source_penalty.max_sources = -1; + options->per_source_penalty.max_sources4 = -1; + options->per_source_penalty.max_sources6 = -1; options->per_source_penalty.overflow_mode = -1; + options->per_source_penalty.overflow_mode6 = -1; options->per_source_penalty.penalty_crash = -1; options->per_source_penalty.penalty_authfail = -1; options->per_source_penalty.penalty_noauth = -1; @@ -389,10 +391,14 @@ fill_default_server_options(ServerOptions *options) options->per_source_masklen_ipv6 = 128; if (options->per_source_penalty.enabled == -1) options->per_source_penalty.enabled = 1; - if (options->per_source_penalty.max_sources == -1) - options->per_source_penalty.max_sources = 65536; + if (options->per_source_penalty.max_sources4 == -1) + options->per_source_penalty.max_sources4 = 65536; + if (options->per_source_penalty.max_sources6 == -1) + options->per_source_penalty.max_sources6 = 65536; if (options->per_source_penalty.overflow_mode == -1) options->per_source_penalty.overflow_mode = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; + if (options->per_source_penalty.overflow_mode6 == -1) + options->per_source_penalty.overflow_mode6 = options->per_source_penalty.overflow_mode; if (options->per_source_penalty.penalty_crash == -1) options->per_source_penalty.penalty_crash = 90; if (options->per_source_penalty.penalty_grace == -1) @@ -1971,9 +1977,14 @@ process_server_config_line_depth(ServerOptions *options, char *line, } else if (strncmp(arg, "min:", 4) == 0) { p = arg + 4; intptr = &options->per_source_penalty.penalty_min; - } else if (strncmp(arg, "max-sources:", 12) == 0) { - intptr = &options->per_source_penalty.max_sources; - if ((errstr = atoi_err(arg+12, &value)) != NULL) + } else if (strncmp(arg, "max-sources4:", 13) == 0) { + intptr = &options->per_source_penalty.max_sources4; + if ((errstr = atoi_err(arg+13, &value)) != NULL) + fatal("%s line %d: %s value %s.", + filename, linenum, keyword, errstr); + } else if (strncmp(arg, "max-sources6:", 13) == 0) { + intptr = &options->per_source_penalty.max_sources6; + if ((errstr = atoi_err(arg+13, &value)) != NULL) fatal("%s line %d: %s value %s.", filename, linenum, keyword, errstr); } else if (strcmp(arg, "overflow:deny-all") == 0) { @@ -1982,6 +1993,12 @@ process_server_config_line_depth(ServerOptions *options, char *line, } else if (strcmp(arg, "overflow:permissive") == 0) { intptr = &options->per_source_penalty.overflow_mode; value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; + } else if (strcmp(arg, "overflow6:deny-all") == 0) { + intptr = &options->per_source_penalty.overflow_mode6; + value = PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL; + } else if (strcmp(arg, "overflow6:permissive") == 0) { + intptr = &options->per_source_penalty.overflow_mode6; + value = PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE; } else { fatal("%s line %d: unsupported %s keyword %s", filename, linenum, keyword, arg); @@ -3218,16 +3235,21 @@ dump_config(ServerOptions *o) if (o->per_source_penalty.enabled) { printf("persourcepenalties crash:%d authfail:%d noauth:%d " - "grace-exceeded:%d max:%d min:%d max-sources:%d " - "overflow:%s\n", o->per_source_penalty.penalty_crash, + "grace-exceeded:%d max:%d min:%d max-sources4:%d " + "max-sources6:%d overflow:%s overflow6:%s\n", + o->per_source_penalty.penalty_crash, o->per_source_penalty.penalty_authfail, o->per_source_penalty.penalty_noauth, o->per_source_penalty.penalty_grace, o->per_source_penalty.penalty_max, o->per_source_penalty.penalty_min, - o->per_source_penalty.max_sources, + o->per_source_penalty.max_sources4, + o->per_source_penalty.max_sources6, o->per_source_penalty.overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ? + "deny-all" : "permissive", + o->per_source_penalty.overflow_mode6 == + PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL ? "deny-all" : "permissive"); } else printf("persourcepenalties no\n"); diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h index 4a4ac1cdb..442dacdcd 100644 --- a/usr.bin/ssh/servconf.h +++ b/usr.bin/ssh/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.164 2024/06/06 17:15:25 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.165 2024/06/12 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen @@ -69,8 +69,10 @@ struct listenaddr { #define PER_SOURCE_PENALTY_OVERFLOW_PERMISSIVE 2 struct per_source_penalty { int enabled; - int max_sources; + int max_sources4; + int max_sources6; int overflow_mode; + int overflow_mode6; int penalty_crash; int penalty_grace; int penalty_authfail; diff --git a/usr.bin/ssh/srclimit.c b/usr.bin/ssh/srclimit.c index c4bc5fee2..430952678 100644 --- a/usr.bin/ssh/srclimit.c +++ b/usr.bin/ssh/srclimit.c @@ -59,11 +59,11 @@ struct penalty { }; static int penalty_addr_cmp(struct penalty *a, struct penalty *b); static int penalty_expiry_cmp(struct penalty *a, struct penalty *b); -RB_HEAD(penalties_by_addr, penalty) penalties_by_addr; -RB_HEAD(penalties_by_expiry, penalty) penalties_by_expiry; +RB_HEAD(penalties_by_addr, penalty) penalties_by_addr4, penalties_by_addr6; +RB_HEAD(penalties_by_expiry, penalty) penalties_by_expiry4, penalties_by_expiry6; RB_GENERATE_STATIC(penalties_by_addr, penalty, by_addr, penalty_addr_cmp) RB_GENERATE_STATIC(penalties_by_expiry, penalty, by_expiry, penalty_expiry_cmp) -static size_t npenalties; +static size_t npenalties4, npenalties6; static int srclimit_mask_addr(const struct xaddr *addr, int bits, struct xaddr *masked) @@ -104,10 +104,14 @@ srclimit_init(int max, int persource, int ipv4len, int ipv6len, ipv6_masklen = ipv6len; max_persource = persource; penalty_cfg = *penalty_conf; + if (penalty_cfg.max_sources4 < 0 || penalty_cfg.max_sources6 < 0) + fatal_f("invalid max_sources"); /* shouldn't happen */ penalty_exempt = penalty_exempt_conf == NULL ? NULL : xstrdup(penalty_exempt_conf); - RB_INIT(&penalties_by_addr); - RB_INIT(&penalties_by_expiry); + RB_INIT(&penalties_by_addr4); + RB_INIT(&penalties_by_expiry4); + RB_INIT(&penalties_by_addr6); + RB_INIT(&penalties_by_expiry6); if (max_persource == INT_MAX) /* no limit */ return; debug("%s: max connections %d, per source %d, masks %d,%d", __func__, @@ -206,26 +210,36 @@ penalty_expiry_cmp(struct penalty *a, struct penalty *b) } static void -expire_penalties(time_t now) +expire_penalties_from_tree(time_t now, const char *t, + struct penalties_by_expiry *by_expiry, + struct penalties_by_addr *by_addr, size_t *npenaltiesp) { struct penalty *penalty, *tmp; /* XXX avoid full scan of tree, e.g. min-heap */ - RB_FOREACH_SAFE(penalty, penalties_by_expiry, - &penalties_by_expiry, tmp) { + RB_FOREACH_SAFE(penalty, penalties_by_expiry, by_expiry, tmp) { if (penalty->expiry >= now) break; - if (RB_REMOVE(penalties_by_expiry, &penalties_by_expiry, + if (RB_REMOVE(penalties_by_expiry, by_expiry, penalty) != penalty || - RB_REMOVE(penalties_by_addr, &penalties_by_addr, + RB_REMOVE(penalties_by_addr, by_addr, penalty) != penalty) - fatal_f("internal error: penalty tables corrupt"); + fatal_f("internal error: %s penalty table corrupt", t); free(penalty); - if (npenalties-- == 0) - fatal_f("internal error: npenalties underflow"); + if ((*npenaltiesp)-- == 0) + fatal_f("internal error: %s npenalties underflow", t); } } +static void +expire_penalties(time_t now) +{ + expire_penalties_from_tree(now, "ipv4", + &penalties_by_expiry4, &penalties_by_addr4, &npenalties4); + expire_penalties_from_tree(now, "ipv6", + &penalties_by_expiry6, &penalties_by_addr6, &npenalties6); +} + static void addr_masklen_ntop(struct xaddr *addr, int masklen, char *s, size_t slen) { @@ -245,8 +259,10 @@ srclimit_penalty_check_allow(int sock, const char **reason) struct xaddr addr; struct penalty find, *penalty; time_t now; - int bits; + int bits, max_sources, overflow_mode; char addr_s[NI_MAXHOST]; + struct penalties_by_addr *by_addr; + size_t npenalties; if (!penalty_cfg.enabled) return 1; @@ -259,8 +275,17 @@ srclimit_penalty_check_allow(int sock, const char **reason) return 1; } } - if (npenalties >= (size_t)penalty_cfg.max_sources && - penalty_cfg.overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) { + now = monotime(); + expire_penalties(now); + by_addr = addr.af == AF_INET ? + &penalties_by_addr4 : &penalties_by_addr6; + max_sources = addr.af == AF_INET ? + penalty_cfg.max_sources4 : penalty_cfg.max_sources6; + overflow_mode = addr.af == AF_INET ? + penalty_cfg.overflow_mode : penalty_cfg.overflow_mode6; + npenalties = addr.af == AF_INET ? npenalties4 : npenalties6; + if (npenalties >= (size_t)max_sources && + overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) { *reason = "too many penalised addresses"; return 0; } @@ -268,9 +293,7 @@ srclimit_penalty_check_allow(int sock, const char **reason) memset(&find, 0, sizeof(find)); if (srclimit_mask_addr(&addr, bits, &find.addr) != 0) return 1; - now = monotime(); - if ((penalty = RB_FIND(penalties_by_addr, - &penalties_by_addr, &find)) == NULL) + if ((penalty = RB_FIND(penalties_by_addr, by_addr, &find)) == NULL) return 1; /* no penalty */ if (penalty->expiry < now) { expire_penalties(now); @@ -283,38 +306,52 @@ srclimit_penalty_check_allow(int sock, const char **reason) } static void -srclimit_remove_expired_penalties(void) +srclimit_early_expire_penalties_from_tree(const char *t, + struct penalties_by_expiry *by_expiry, + struct penalties_by_addr *by_addr, size_t *npenaltiesp, size_t max_sources) { struct penalty *p = NULL; int bits; char s[NI_MAXHOST + 4]; /* Delete the soonest-to-expire penalties. */ - while (npenalties > (size_t)penalty_cfg.max_sources) { - if ((p = RB_MIN(penalties_by_expiry, - &penalties_by_expiry)) == NULL) - fatal_f("internal error: penalty tables corrupt (find)"); + while (*npenaltiesp > max_sources) { + if ((p = RB_MIN(penalties_by_expiry, by_expiry)) == NULL) + fatal_f("internal error: %s table corrupt (find)", t); bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen; addr_masklen_ntop(&p->addr, bits, s, sizeof(s)); - debug3_f("overflow, remove %s", s); - if (RB_REMOVE(penalties_by_expiry, - &penalties_by_expiry, p) != p || - RB_REMOVE(penalties_by_addr, &penalties_by_addr, p) != p) - fatal_f("internal error: penalty tables corrupt (remove)"); + debug3_f("%s overflow, remove %s", t, s); + if (RB_REMOVE(penalties_by_expiry, by_expiry, p) != p || + RB_REMOVE(penalties_by_addr, by_addr, p) != p) + fatal_f("internal error: %s table corrupt (remove)", t); free(p); - npenalties--; + (*npenaltiesp)--; } } +static void +srclimit_early_expire_penalties(void) +{ + srclimit_early_expire_penalties_from_tree("ipv4", + &penalties_by_expiry4, &penalties_by_addr4, &npenalties4, + (size_t)penalty_cfg.max_sources4); + srclimit_early_expire_penalties_from_tree("ipv6", + &penalties_by_expiry6, &penalties_by_addr6, &npenalties6, + (size_t)penalty_cfg.max_sources6); +} + void srclimit_penalise(struct xaddr *addr, int penalty_type) { struct xaddr masked; - struct penalty *penalty, *existing; + struct penalty *penalty = NULL, *existing = NULL; time_t now; - int bits, penalty_secs; + int bits, penalty_secs, max_sources = 0, overflow_mode; char addrnetmask[NI_MAXHOST + 4]; - const char *reason = NULL; + const char *reason = NULL, *t; + size_t *npenaltiesp = NULL; + struct penalties_by_addr *by_addr = NULL; + struct penalties_by_expiry *by_expiry = NULL; if (!penalty_cfg.enabled) return; @@ -356,9 +393,19 @@ srclimit_penalise(struct xaddr *addr, int penalty_type) now = monotime(); expire_penalties(now); - if (npenalties > (size_t)penalty_cfg.max_sources && - penalty_cfg.overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) { - verbose_f("penalty table full, cannot penalise %s for %s", + by_expiry = addr->af == AF_INET ? + &penalties_by_expiry4 : &penalties_by_expiry6; + by_addr = addr->af == AF_INET ? + &penalties_by_addr4 : &penalties_by_addr6; + max_sources = addr->af == AF_INET ? + penalty_cfg.max_sources4 : penalty_cfg.max_sources6; + overflow_mode = addr->af == AF_INET ? + penalty_cfg.overflow_mode : penalty_cfg.overflow_mode6; + npenaltiesp = addr->af == AF_INET ? &npenalties4 : &npenalties6; + t = addr->af == AF_INET ? "ipv4" : "ipv6"; + if (*npenaltiesp > (size_t)max_sources && + overflow_mode == PER_SOURCE_PENALTY_OVERFLOW_DENY_ALL) { + verbose_f("%s penalty table full, cannot penalise %s for %s", t, addrnetmask, reason); return; } @@ -367,48 +414,48 @@ srclimit_penalise(struct xaddr *addr, int penalty_type) penalty->addr = masked; penalty->expiry = now + penalty_secs; penalty->reason = reason; - if ((existing = RB_INSERT(penalties_by_addr, &penalties_by_addr, + if ((existing = RB_INSERT(penalties_by_addr, by_addr, penalty)) == NULL) { /* penalty didn't previously exist */ if (penalty_secs > penalty_cfg.penalty_min) penalty->active = 1; - if (RB_INSERT(penalties_by_expiry, &penalties_by_expiry, - penalty) != NULL) - fatal_f("internal error: penalty tables corrupt"); - verbose_f("%s: new %s penalty of %d seconds for %s", + if (RB_INSERT(penalties_by_expiry, by_expiry, penalty) != NULL) + fatal_f("internal error: %s penalty tables corrupt", t); + verbose_f("%s: new %s %s penalty of %d seconds for %s", t, addrnetmask, penalty->active ? "active" : "deferred", penalty_secs, reason); - if (++npenalties > (size_t)penalty_cfg.max_sources) - srclimit_remove_expired_penalties(); /* permissive */ + if (++(*npenaltiesp) > (size_t)max_sources) + srclimit_early_expire_penalties(); /* permissive */ return; } - debug_f("%s penalty for %s already exists, %lld seconds remaining", - existing->active ? "active" : "inactive", + debug_f("%s penalty for %s %s already exists, %lld seconds remaining", + existing->active ? "active" : "inactive", t, addrnetmask, (long long)(existing->expiry - now)); /* Expiry information is about to change, remove from tree */ - if (RB_REMOVE(penalties_by_expiry, &penalties_by_expiry, - existing) != existing) - fatal_f("internal error: penalty tables corrupt (remove)"); + if (RB_REMOVE(penalties_by_expiry, by_expiry, existing) != existing) + fatal_f("internal error: %s penalty table corrupt (remove)", t); /* An entry already existed. Accumulate penalty up to maximum */ existing->expiry += penalty_secs; if (existing->expiry - now > penalty_cfg.penalty_max) existing->expiry = now + penalty_cfg.penalty_max; if (existing->expiry - now > penalty_cfg.penalty_min && !existing->active) { - verbose_f("%s: activating penalty of %lld seconds for %s", - addrnetmask, (long long)(existing->expiry - now), reason); + verbose_f("%s: activating %s penalty of %lld seconds for %s", + addrnetmask, t, (long long)(existing->expiry - now), + reason); existing->active = 1; } existing->reason = penalty->reason; free(penalty); + penalty = NULL; /* Re-insert into expiry tree */ - if (RB_INSERT(penalties_by_expiry, &penalties_by_expiry, - existing) != NULL) - fatal_f("internal error: penalty tables corrupt (insert)"); + if (RB_INSERT(penalties_by_expiry, by_expiry, existing) != NULL) + fatal_f("internal error: %s penalty table corrupt (insert)", t); } -void -srclimit_penalty_info(void) +static void +srclimit_penalty_info_for_tree(const char *t, + struct penalties_by_expiry *by_expiry, size_t npenalties) { struct penalty *p = NULL; int bits; @@ -416,8 +463,8 @@ srclimit_penalty_info(void) time_t now; now = monotime(); - logit("%zu active penalties", npenalties); - RB_FOREACH(p, penalties_by_expiry, &penalties_by_expiry) { + logit("%zu active %s penalties", npenalties, t); + RB_FOREACH(p, penalties_by_expiry, by_expiry) { bits = p->addr.af == AF_INET ? ipv4_masklen : ipv6_masklen; addr_masklen_ntop(&p->addr, bits, s, sizeof(s)); if (p->expiry < now) @@ -428,3 +475,12 @@ srclimit_penalty_info(void) } } } + +void +srclimit_penalty_info(void) +{ + srclimit_penalty_info_for_tree("ipv4", + &penalties_by_expiry4, npenalties4); + srclimit_penalty_info_for_tree("ipv6", + &penalties_by_expiry6, npenalties6); +} diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5 index 390cf9804..50e5d8f6e 100644 --- a/usr.bin/ssh/sshd_config.5 +++ b/usr.bin/ssh/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.360 2024/06/11 05:24:39 jmc Exp $ -.Dd $Mdocdate: June 11 2024 $ +.\" $OpenBSD: sshd_config.5,v 1.361 2024/06/12 22:36:00 djm Exp $ +.Dd $Mdocdate: June 12 2024 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -1604,12 +1604,14 @@ Repeated penalties will accumulate up to this maximum. .It Cm min:duration Specifies the minimum penalty that must accrue before enforcement begins (default: 15s). -.It Cm max-sources:number -Specifies the maximum number of penalise client address ranges to track -(default: 65536). +.It Cm max-sources4:number max-sources6:number +Specifies the maximum number of client IPv4 and IPv6 address ranges to +track for penalties (default: 65536 for both). .It Cm overflow:mode Controls how the server behaves when -.Cm max-sources +.Cm max-sources4 +or +.Cm max-sources6 is exceeded. There are two operating modes: .Cm deny-all , @@ -1619,6 +1621,14 @@ until a penalty expires, and .Cm permissive , which allows new connections by removing existing penalties early (default: permissive). +Note that client penalties below the +.Cm min +threshold count against the total number of tracked penalties. +IPv4 and IPv6 addresses are tracked separately, so an overflow in one will +not affect the other. +.It Cm overflow6:mode +Allows specifying a different overflow mode for IPv6 addresses. +The default it to use the same overflow mode as was specified for IPv4. .El .It Cm PerSourcePenaltyExemptList Specifies a comma-separated list of addresses to exempt from penalties. diff --git a/usr.sbin/rpki-client/cert.c b/usr.sbin/rpki-client/cert.c index c0c32a925..c6a762fa3 100644 --- a/usr.sbin/rpki-client/cert.c +++ b/usr.sbin/rpki-client/cert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cert.c,v 1.147 2024/06/12 04:01:20 tb Exp $ */ +/* $OpenBSD: cert.c,v 1.148 2024/06/12 10:03:09 tb Exp $ */ /* * Copyright (c) 2022 Theo Buehler * Copyright (c) 2021 Job Snijders @@ -34,7 +34,7 @@ extern ASN1_OBJECT *carepo_oid; /* 1.3.6.1.5.5.7.48.5 (caRepository) */ extern ASN1_OBJECT *manifest_oid; /* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */ extern ASN1_OBJECT *notify_oid; /* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */ -static int certid = TALSZ_MAX; +int certid = TALSZ_MAX; /* * Append an IP address structure to our list of results. @@ -1271,8 +1271,12 @@ auth_insert(const char *fn, struct auth_tree *auths, struct cert *cert, cert->certid = cert->talid; } else { cert->certid = ++certid; - if (certid > CERTID_MAX) - errx(1, "%s: too many certificates in store", fn); + if (certid > CERTID_MAX) { + if (certid == CERTID_MAX + 1) + warnx("%s: too many certificates in store", fn); + free(na); + return NULL; + } na->depth = issuer->depth + 1; } diff --git a/usr.sbin/rpki-client/crl.c b/usr.sbin/rpki-client/crl.c index 5ec57c9b3..0cf97caff 100644 --- a/usr.sbin/rpki-client/crl.c +++ b/usr.sbin/rpki-client/crl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crl.c,v 1.40 2024/06/11 15:33:46 tb Exp $ */ +/* $OpenBSD: crl.c,v 1.41 2024/06/12 10:03:09 tb Exp $ */ /* * Copyright (c) 2024 Theo Buehler * Copyright (c) 2019 Kristaps Dzonsons @@ -296,9 +296,6 @@ crl_get(struct crl_tree *crlt, const struct auth *a) { struct crl find; - if (a == NULL) - return NULL; - find.aki = a->cert->ski; find.mftpath = a->cert->mft; diff --git a/usr.sbin/rpki-client/filemode.c b/usr.sbin/rpki-client/filemode.c index 689817c7c..70c6cf112 100644 --- a/usr.sbin/rpki-client/filemode.c +++ b/usr.sbin/rpki-client/filemode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: filemode.c,v 1.45 2024/06/08 13:34:59 tb Exp $ */ +/* $OpenBSD: filemode.c,v 1.46 2024/06/12 10:03:09 tb Exp $ */ /* * Copyright (c) 2019 Claudio Jeker * Copyright (c) 2019 Kristaps Dzonsons @@ -191,6 +191,10 @@ parse_load_certchain(char *uri) for (i = 0; i < MAX_CERT_DEPTH; i++) { if ((cert = uripath_lookup(uri)) != NULL) { a = auth_find(&auths, cert->certid); + if (a == NULL) { + warnx("failed to find issuer for %s", uri); + goto fail; + } break; } filestack[i] = uri; diff --git a/usr.sbin/rpki-client/parser.c b/usr.sbin/rpki-client/parser.c index b79ac3f4d..c11ec98fd 100644 --- a/usr.sbin/rpki-client/parser.c +++ b/usr.sbin/rpki-client/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.140 2024/06/10 11:49:29 tb Exp $ */ +/* $OpenBSD: parser.c,v 1.141 2024/06/12 10:03:09 tb Exp $ */ /* * Copyright (c) 2019 Claudio Jeker * Copyright (c) 2019 Kristaps Dzonsons @@ -38,6 +38,8 @@ #include "extern.h" +extern int certid; + static X509_STORE_CTX *ctx; static struct auth_tree auths = RB_INITIALIZER(&auths); static struct crl_tree crlt = RB_INITIALIZER(&crlt); @@ -98,7 +100,9 @@ find_issuer(const char *fn, int id, const char *aki, const char *mftaki) a = auth_find(&auths, id); if (a == NULL) { - warnx("%s: RFC 6487: unknown cert with SKI %s", fn, aki); + if (certid <= CERTID_MAX) + warnx("%s: RFC 6487: unknown cert with SKI %s", fn, + aki); return NULL; } @@ -171,6 +175,11 @@ proc_parser_roa(char *file, const unsigned char *der, size_t len, return NULL; a = find_issuer(file, entp->certid, roa->aki, entp->mftaki); + if (a == NULL) { + X509_free(x509); + roa_free(roa); + return NULL; + } crl = crl_get(&crlt, a); if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { @@ -206,6 +215,11 @@ proc_parser_spl(char *file, const unsigned char *der, size_t len, return NULL; a = find_issuer(file, entp->certid, spl->aki, entp->mftaki); + if (a == NULL) { + X509_free(x509); + spl_free(spl); + return NULL; + } crl = crl_get(&crlt, a); if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { @@ -370,6 +384,8 @@ proc_parser_mft_pre(struct entity *entp, char *file, struct crl **crl, *crl = parse_load_crl_from_mft(entp, mft, DIR_VALID, crlfile); a = find_issuer(file, entp->certid, mft->aki, NULL); + if (a == NULL) + goto err; if (!valid_x509(file, ctx, x509, a, *crl, errstr)) goto err; X509_free(x509); @@ -494,7 +510,8 @@ proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile, err2 = err1; if (err2 == NULL) err2 = "no valid manifest available"; - warnx("%s: %s", file2, err2); + if (certid <= CERTID_MAX) + warnx("%s: %s", file2, err2); } mft_free(mft1); @@ -542,6 +559,10 @@ proc_parser_cert(char *file, const unsigned char *der, size_t len, return NULL; a = find_issuer(file, entp->certid, cert->aki, entp->mftaki); + if (a == NULL) { + cert_free(cert); + return NULL; + } crl = crl_get(&crlt, a); if (!valid_x509(file, ctx, cert->x509, a, crl, &errstr) || @@ -684,6 +705,11 @@ proc_parser_gbr(char *file, const unsigned char *der, size_t len, return NULL; a = find_issuer(file, entp->certid, gbr->aki, entp->mftaki); + if (a == NULL) { + X509_free(x509); + gbr_free(gbr); + return NULL; + } crl = crl_get(&crlt, a); if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { @@ -716,6 +742,11 @@ proc_parser_aspa(char *file, const unsigned char *der, size_t len, return NULL; a = find_issuer(file, entp->certid, aspa->aki, entp->mftaki); + if (a == NULL) { + X509_free(x509); + aspa_free(aspa); + return NULL; + } crl = crl_get(&crlt, a); if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { @@ -751,6 +782,8 @@ proc_parser_tak(char *file, const unsigned char *der, size_t len, return NULL; a = find_issuer(file, entp->certid, tak->aki, entp->mftaki); + if (a == NULL) + goto out; crl = crl_get(&crlt, a); if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { @@ -1076,5 +1109,8 @@ proc_parser(int fd) ibuf_free(inbuf); + if (certid > CERTID_MAX) + errx(1, "processing incomplete: too many certificates"); + exit(0); } diff --git a/usr.sbin/rpki-client/validate.c b/usr.sbin/rpki-client/validate.c index f66518a47..f4c6e7c26 100644 --- a/usr.sbin/rpki-client/validate.c +++ b/usr.sbin/rpki-client/validate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: validate.c,v 1.74 2024/05/20 15:51:43 claudio Exp $ */ +/* $OpenBSD: validate.c,v 1.75 2024/06/12 10:03:09 tb Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -304,9 +304,6 @@ build_chain(const struct auth *a, STACK_OF(X509) **intermediates, *intermediates = NULL; *root = NULL; - if (a == NULL) - return; - if ((*intermediates = sk_X509_new_null()) == NULL) err(1, "sk_X509_new_null"); if ((*root = sk_X509_new_null()) == NULL)