|
3 | 3 | * Confidential Computing Platform Capability checks
|
4 | 4 | *
|
5 | 5 | * Copyright (C) 2021 Advanced Micro Devices, Inc.
|
| 6 | + * Copyright (C) 2024 Jason A. Donenfeld <[email protected]>. All Rights Reserved. |
6 | 7 | *
|
7 | 8 | * Author: Tom Lendacky <[email protected]>
|
8 | 9 | */
|
9 | 10 |
|
10 | 11 | #include <linux/export.h>
|
11 | 12 | #include <linux/cc_platform.h>
|
| 13 | +#include <linux/string.h> |
| 14 | +#include <linux/random.h> |
12 | 15 |
|
| 16 | +#include <asm/archrandom.h> |
13 | 17 | #include <asm/coco.h>
|
14 | 18 | #include <asm/processor.h>
|
15 | 19 |
|
16 | 20 | enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE;
|
17 | 21 | u64 cc_mask __ro_after_init;
|
18 | 22 |
|
| 23 | +static struct cc_attr_flags { |
| 24 | + __u64 host_sev_snp : 1, |
| 25 | + __resv : 63; |
| 26 | +} cc_flags; |
| 27 | + |
19 | 28 | static bool noinstr intel_cc_platform_has(enum cc_attr attr)
|
20 | 29 | {
|
21 | 30 | switch (attr) {
|
@@ -89,6 +98,9 @@ static bool noinstr amd_cc_platform_has(enum cc_attr attr)
|
89 | 98 | case CC_ATTR_GUEST_SEV_SNP:
|
90 | 99 | return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
|
91 | 100 |
|
| 101 | + case CC_ATTR_HOST_SEV_SNP: |
| 102 | + return cc_flags.host_sev_snp; |
| 103 | + |
92 | 104 | default:
|
93 | 105 | return false;
|
94 | 106 | }
|
@@ -148,3 +160,84 @@ u64 cc_mkdec(u64 val)
|
148 | 160 | }
|
149 | 161 | }
|
150 | 162 | EXPORT_SYMBOL_GPL(cc_mkdec);
|
| 163 | + |
| 164 | +static void amd_cc_platform_clear(enum cc_attr attr) |
| 165 | +{ |
| 166 | + switch (attr) { |
| 167 | + case CC_ATTR_HOST_SEV_SNP: |
| 168 | + cc_flags.host_sev_snp = 0; |
| 169 | + break; |
| 170 | + default: |
| 171 | + break; |
| 172 | + } |
| 173 | +} |
| 174 | + |
| 175 | +void cc_platform_clear(enum cc_attr attr) |
| 176 | +{ |
| 177 | + switch (cc_vendor) { |
| 178 | + case CC_VENDOR_AMD: |
| 179 | + amd_cc_platform_clear(attr); |
| 180 | + break; |
| 181 | + default: |
| 182 | + break; |
| 183 | + } |
| 184 | +} |
| 185 | + |
| 186 | +static void amd_cc_platform_set(enum cc_attr attr) |
| 187 | +{ |
| 188 | + switch (attr) { |
| 189 | + case CC_ATTR_HOST_SEV_SNP: |
| 190 | + cc_flags.host_sev_snp = 1; |
| 191 | + break; |
| 192 | + default: |
| 193 | + break; |
| 194 | + } |
| 195 | +} |
| 196 | + |
| 197 | +void cc_platform_set(enum cc_attr attr) |
| 198 | +{ |
| 199 | + switch (cc_vendor) { |
| 200 | + case CC_VENDOR_AMD: |
| 201 | + amd_cc_platform_set(attr); |
| 202 | + break; |
| 203 | + default: |
| 204 | + break; |
| 205 | + } |
| 206 | +} |
| 207 | + |
| 208 | +__init void cc_random_init(void) |
| 209 | +{ |
| 210 | + /* |
| 211 | + * The seed is 32 bytes (in units of longs), which is 256 bits, which |
| 212 | + * is the security level that the RNG is targeting. |
| 213 | + */ |
| 214 | + unsigned long rng_seed[32 / sizeof(long)]; |
| 215 | + size_t i, longs; |
| 216 | + |
| 217 | + if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) |
| 218 | + return; |
| 219 | + |
| 220 | + /* |
| 221 | + * Since the CoCo threat model includes the host, the only reliable |
| 222 | + * source of entropy that can be neither observed nor manipulated is |
| 223 | + * RDRAND. Usually, RDRAND failure is considered tolerable, but since |
| 224 | + * CoCo guests have no other unobservable source of entropy, it's |
| 225 | + * important to at least ensure the RNG gets some initial random seeds. |
| 226 | + */ |
| 227 | + for (i = 0; i < ARRAY_SIZE(rng_seed); i += longs) { |
| 228 | + longs = arch_get_random_longs(&rng_seed[i], ARRAY_SIZE(rng_seed) - i); |
| 229 | + |
| 230 | + /* |
| 231 | + * A zero return value means that the guest doesn't have RDRAND |
| 232 | + * or the CPU is physically broken, and in both cases that |
| 233 | + * means most crypto inside of the CoCo instance will be |
| 234 | + * broken, defeating the purpose of CoCo in the first place. So |
| 235 | + * just panic here because it's absolutely unsafe to continue |
| 236 | + * executing. |
| 237 | + */ |
| 238 | + if (longs == 0) |
| 239 | + panic("RDRAND is defective."); |
| 240 | + } |
| 241 | + add_device_randomness(rng_seed, sizeof(rng_seed)); |
| 242 | + memzero_explicit(rng_seed, sizeof(rng_seed)); |
| 243 | +} |
0 commit comments