diff --git a/sgx.h b/sgx.h index 62c19da..978d988 100644 --- a/sgx.h +++ b/sgx.h @@ -226,7 +226,7 @@ int sgx_encl_create(struct sgx_secs *secs); int sgx_encl_add_page(struct sgx_encl *encl, unsigned long addr, void *data, struct sgx_secinfo *secinfo, unsigned int mrmask); int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct, - struct sgx_einittoken *einittoken); + struct sgx_einittoken *einittoken, bool use_flc); struct sgx_encl_page *sgx_encl_augment(struct vm_area_struct *vma, unsigned long addr, bool write); void sgx_encl_release(struct kref *ref); @@ -282,4 +282,6 @@ long modify_range(struct sgx_range *rg, unsigned long flags); int remove_page(struct sgx_encl *encl, unsigned long address, bool trim); int sgx_get_encl(unsigned long addr, struct sgx_encl **encl); int sgx_vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr, resource_size_t pa); + +void sgx_reset_pubkey_hash(void *failed); #endif /* __ARCH_X86_INTEL_SGX_H__ */ diff --git a/sgx_encl.c b/sgx_encl.c index 04a1b9c..2e3a469 100644 --- a/sgx_encl.c +++ b/sgx_encl.c @@ -916,6 +916,7 @@ static int sgx_einit(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct, * @encl: an enclave * @sigstruct: SIGSTRUCT for the enclave * @token: EINITTOKEN for the enclave + * @use_flc: write LEHASH MSRs prior to calling EINIT, and restore them after * * Retries a few times in order to perform EINIT operation on an enclave * because there could be potentially an interrupt storm. @@ -926,9 +927,10 @@ static int sgx_einit(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct, * SGX error code */ int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct, - struct sgx_einittoken *token) + struct sgx_einittoken *token, bool use_flc) { int ret; + int ret2; int i; int j; @@ -943,8 +945,23 @@ int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct, for (i = 0; i < SGX_EINIT_SLEEP_COUNT; i++) { for (j = 0; j < SGX_EINIT_SPIN_COUNT; j++) { + preempt_disable(); + + if (use_flc) { + wrmsrl_safe(MSR_IA32_SGXLEPUBKEYHASH0, ((u64*)token->payload.mrsigner)[0]); + wrmsrl_safe(MSR_IA32_SGXLEPUBKEYHASH1, ((u64*)token->payload.mrsigner)[1]); + wrmsrl_safe(MSR_IA32_SGXLEPUBKEYHASH2, ((u64*)token->payload.mrsigner)[2]); + wrmsrl_safe(MSR_IA32_SGXLEPUBKEYHASH3, ((u64*)token->payload.mrsigner)[3]); + } + ret = sgx_einit(encl, sigstruct, token); + if (use_flc) { + sgx_reset_pubkey_hash(&ret2); + } + + preempt_enable(); + if (ret == SGX_UNMASKED_EVENT) continue; else diff --git a/sgx_ioctl.c b/sgx_ioctl.c index 56ab1e6..681da4d 100644 --- a/sgx_ioctl.c +++ b/sgx_ioctl.c @@ -72,6 +72,7 @@ #include #include #include +#include int sgx_get_encl(unsigned long addr, struct sgx_encl **encl) { @@ -202,6 +203,31 @@ static long sgx_ioc_enclave_add_page(struct file *filep, unsigned int cmd, return ret; } +static int __sgx_get_key_hash(struct crypto_shash *tfm, const void *modulus, + void *hash) +{ + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm = tfm; + + return crypto_shash_digest(shash, modulus, SGX_MODULUS_SIZE, hash); +} + +static int sgx_get_key_hash(const void *modulus, void *hash) +{ + struct crypto_shash *tfm; + int ret; + + tfm = crypto_alloc_shash("sha256", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + ret = __sgx_get_key_hash(tfm, modulus, hash); + + crypto_free_shash(tfm); + return ret; +} + /** * sgx_ioc_enclave_init - handler for %SGX_IOC_ENCLAVE_INIT * @@ -218,16 +244,28 @@ static long sgx_ioc_enclave_add_page(struct file *filep, unsigned int cmd, static long sgx_ioc_enclave_init(struct file *filep, unsigned int cmd, unsigned long arg) { - struct sgx_enclave_init *initp = (struct sgx_enclave_init *)arg; - unsigned long sigstructp = (unsigned long)initp->sigstruct; - unsigned long einittokenp = (unsigned long)initp->einittoken; - unsigned long encl_id = initp->addr; + unsigned long sigstructp; + unsigned long einittokenp; + unsigned long encl_id; + struct sgx_enclave_init *initp; + struct sgx_enclave_init_no_token *initntp; struct sgx_sigstruct *sigstruct; struct sgx_einittoken *einittoken; struct sgx_encl *encl; struct page *initp_page; int ret; + if (cmd == SGX_IOC_ENCLAVE_INIT_NO_TOKEN) { + initntp = (struct sgx_enclave_init_no_token *)arg; + sigstructp = (unsigned long)initntp->sigstruct; + encl_id = initntp->addr; + } else { + initp = (struct sgx_enclave_init *)arg; + sigstructp = (unsigned long)initp->sigstruct; + einittokenp = (unsigned long)initp->einittoken; + encl_id = initp->addr; + } + initp_page = alloc_page(GFP_HIGHUSER); if (!initp_page) return -ENOMEM; @@ -241,16 +279,22 @@ static long sgx_ioc_enclave_init(struct file *filep, unsigned int cmd, if (ret) goto out; - ret = copy_from_user(einittoken, (void __user *)einittokenp, - sizeof(*einittoken)); - if (ret) - goto out; + if (cmd != SGX_IOC_ENCLAVE_INIT_NO_TOKEN) { + ret = copy_from_user(einittoken, (void __user *)einittokenp, + sizeof(*einittoken)); + if (ret) + goto out; + } else { + ret = sgx_get_key_hash(sigstruct->modulus, einittoken->payload.mrsigner); + if (ret) + goto out; + } ret = sgx_get_encl(encl_id, &encl); if (ret) goto out; - ret = sgx_encl_init(encl, sigstruct, einittoken); + ret = sgx_encl_init(encl, sigstruct, einittoken, cmd == SGX_IOC_ENCLAVE_INIT_NO_TOKEN); kref_put(&encl->refcount, sgx_encl_release); @@ -394,6 +438,7 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) handler = sgx_ioc_enclave_add_page; break; case SGX_IOC_ENCLAVE_INIT: + case SGX_IOC_ENCLAVE_INIT_NO_TOKEN: handler = sgx_ioc_enclave_init; break; case SGX_IOC_ENCLAVE_EMODPR: diff --git a/sgx_main.c b/sgx_main.c index ca52821..2278e8b 100644 --- a/sgx_main.c +++ b/sgx_main.c @@ -105,6 +105,7 @@ u64 sgx_xfrm_mask = 0x3; u32 sgx_misc_reserved; u32 sgx_xsave_size_tbl[64]; bool sgx_has_sgx2; +bool sgx_dev_alt_name; static int sgx_mmap(struct file *file, struct vm_area_struct *vma) { @@ -168,6 +169,13 @@ static struct miscdevice sgx_dev = { .mode = 0666, }; +static struct miscdevice sgx_dev_alt = { + .minor = MISC_DYNAMIC_MINOR, + .name = "sgx", + .fops = &sgx_fops, + .mode = 0666, +}; + static int sgx_pm_suspend(struct device *dev) { struct sgx_tgid_ctx *ctx; @@ -184,7 +192,7 @@ static int sgx_pm_suspend(struct device *dev) return 0; } -static void sgx_reset_pubkey_hash(void *failed) +void sgx_reset_pubkey_hash(void *failed) { if (wrmsrl_safe(MSR_IA32_SGXLEPUBKEYHASH0, 0xa6053e051270b7acULL) || wrmsrl_safe(MSR_IA32_SGXLEPUBKEYHASH1, 0x6cfbe8ba8b3b413dULL) || @@ -275,7 +283,7 @@ static int sgx_dev_init(struct device *parent) } sgx_dev.parent = parent; - ret = misc_register(&sgx_dev); + ret = misc_register(sgx_dev_alt_name ? &sgx_dev_alt : &sgx_dev); if (ret) { pr_err("intel_sgx: misc_register() failed\n"); goto out_workqueue; @@ -408,3 +416,6 @@ module_init(init_sgx_module); module_exit(cleanup_sgx_module); MODULE_LICENSE("Dual BSD/GPL"); + +module_param_named(devsgx, sgx_dev_alt_name, bool, 0444); +MODULE_PARM_DESC(sgx_dev_alt_name, "Device name is sgx instead of isgx"); diff --git a/sgx_user.h b/sgx_user.h index 50f0931..283399e 100644 --- a/sgx_user.h +++ b/sgx_user.h @@ -69,6 +69,8 @@ _IOW(SGX_MAGIC, 0x01, struct sgx_enclave_add_page) #define SGX_IOC_ENCLAVE_INIT \ _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init) +#define SGX_IOC_ENCLAVE_INIT_NO_TOKEN \ + _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init_no_token) #define SGX_IOC_ENCLAVE_EMODPR \ _IOW(SGX_MAGIC, 0x09, struct sgx_modification_param) #define SGX_IOC_ENCLAVE_MKTCS \ @@ -147,6 +149,17 @@ struct sgx_enclave_init { __u64 einittoken; } __attribute__((__packed__)); +/** + * struct sgx_enclave_init - parameter structure for the + * %SGX_IOC_ENCLAVE_INIT ioctl + * @addr: address in the ELRANGE + * @sigstruct: address for the page data + */ +struct sgx_enclave_init_no_token { + __u64 addr; + __u64 sigstruct; +} __attribute__((__packed__)); + /* * SGX2.0 definitions */