diff mbox series

[v39,15/24] x86/sgx: Add SGX_IOC_ENCLAVE_PROVISION

Message ID 20201003045059.665934-16-jarkko.sakkinen@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series Intel SGX foundations | expand

Commit Message

Jarkko Sakkinen Oct. 3, 2020, 4:50 a.m. UTC
Provisioning Certification Enclave (PCE), the root of trust for other
enclaves, generates a signing key from a fused key called Provisioning
Certification Key. PCE can then use this key to certify an attestation key
of a Quoting Enclave (QE), e.g. we get the chain of trust down to the
hardware if the Intel signed PCE is used.

To use the needed keys, ATTRIBUTE.PROVISIONKEY is required but should be
only allowed for those who actually need it so that only the trusted
parties can certify QE's.

Obviously the attestation service should know the public key of the used
PCE and that way detect illegit attestation, but whitelisting the legit
users still adds an additional layer of defence.

Add new device file called /dev/sgx/provision. The sole purpose of this
file is to provide file descriptors that act as privilege tokens to allow
to build enclaves with ATTRIBUTE.PROVISIONKEY set. A new ioctl called
SGX_IOC_ENCLAVE_PROVISION is used to assign this token to an enclave.

Cc: linux-security-module@vger.kernel.org
Acked-by: Jethro Beekman <jethro@fortanix.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 arch/x86/include/uapi/asm/sgx.h  | 11 ++++++++
 arch/x86/kernel/cpu/sgx/driver.c | 18 +++++++++++++
 arch/x86/kernel/cpu/sgx/driver.h |  2 ++
 arch/x86/kernel/cpu/sgx/ioctl.c  | 46 ++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+)

Comments

Dave Hansen Oct. 20, 2020, 3:48 p.m. UTC | #1
>  int __init sgx_drv_init(void)
>  {
>  	unsigned int eax, ebx, ecx, edx;
> @@ -181,5 +192,12 @@ int __init sgx_drv_init(void)
>  		return ret;
>  	}
>  
> +	ret = misc_register(&sgx_dev_provision);
> +	if (ret) {
> +		pr_err("Creating /dev/sgx/provision failed with %d.\n", ret);
> +		misc_deregister(&sgx_dev_enclave);
> +		return ret;
> +	}
> +

Isn't it a *bit* too specific to say that a device file failed to be
created?  Do other misc devices use this kind of message?
Dave Hansen Oct. 20, 2020, 9:19 p.m. UTC | #2
On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> + * Failure to explicitly request access to a restricted attribute will cause
> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> + * is access to the PROVISION_KEY.

Could we also justify why access is restricted, please?  Maybe:

	Access is restricted because PROVISION_KEY is burned uniquely
	into each each processor, making it a perfect unique identifier
	with privacy and fingerprinting implications.

Are there any other reasons for doing it this way?
Jarkko Sakkinen Oct. 23, 2020, 10:14 a.m. UTC | #3
On Tue, Oct 20, 2020 at 08:48:54AM -0700, Dave Hansen wrote:
> >  int __init sgx_drv_init(void)
> >  {
> >  	unsigned int eax, ebx, ecx, edx;
> > @@ -181,5 +192,12 @@ int __init sgx_drv_init(void)
> >  		return ret;
> >  	}
> >  
> > +	ret = misc_register(&sgx_dev_provision);
> > +	if (ret) {
> > +		pr_err("Creating /dev/sgx/provision failed with %d.\n", ret);
> > +		misc_deregister(&sgx_dev_enclave);
> > +		return ret;
> > +	}
> > +
> 
> Isn't it a *bit* too specific to say that a device file failed to be
> created?  Do other misc devices use this kind of message?

Before seeing this I had already removed it. It is incosistent at
least and quite useless error really. We have tracing tools for
this.

/Jarkko
Jarkko Sakkinen Oct. 23, 2020, 10:17 a.m. UTC | #4
On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> > + * Failure to explicitly request access to a restricted attribute will cause
> > + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> > + * is access to the PROVISION_KEY.
> 
> Could we also justify why access is restricted, please?  Maybe:
> 
> 	Access is restricted because PROVISION_KEY is burned uniquely
> 	into each each processor, making it a perfect unique identifier
> 	with privacy and fingerprinting implications.
> 
> Are there any other reasons for doing it this way?

AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
PROVISION_SEALING_KEY also have random salt added, i.e. they change
every boot cycle.

There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
3D :-)

/Jarkko
Dave Hansen Oct. 23, 2020, 2:19 p.m. UTC | #5
On 10/23/20 3:17 AM, Jarkko Sakkinen wrote:
> On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
>> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
>>> + * Failure to explicitly request access to a restricted attribute will cause
>>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
>>> + * is access to the PROVISION_KEY.
>> Could we also justify why access is restricted, please?  Maybe:
>>
>> 	Access is restricted because PROVISION_KEY is burned uniquely
>> 	into each each processor, making it a perfect unique identifier
>> 	with privacy and fingerprinting implications.
>>
>> Are there any other reasons for doing it this way?
> AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> PROVISION_SEALING_KEY also have random salt added, i.e. they change
> every boot cycle.
> 
> There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> 3D :-)

Does that mean there are no privacy implications from access to the
provisioning keys?  If that's true, why do we need a separate permission
framework for creating provisioning enclaves?
Jethro Beekman Oct. 23, 2020, 2:23 p.m. UTC | #6
On 2020-10-23 12:17, Jarkko Sakkinen wrote:
> On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
>> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
>>> + * Failure to explicitly request access to a restricted attribute will cause
>>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
>>> + * is access to the PROVISION_KEY.
>>
>> Could we also justify why access is restricted, please?  Maybe:
>>
>> 	Access is restricted because PROVISION_KEY is burned uniquely
>> 	into each each processor, making it a perfect unique identifier
>> 	with privacy and fingerprinting implications.
>>
>> Are there any other reasons for doing it this way?
> 
> AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> PROVISION_SEALING_KEY also have random salt added, i.e. they change
> every boot cycle.
> 
> There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> 3D :-)
> 

This is nonsense. The whole point of sealing keys is that they don't change every boot. If did they they'd have no value over enclave memory. RAND means that the KEYID field from the KEYREQUEST is included in the derivation (as noted in the source row of the table you looked at).

--
Jethro Beekman | Fortanix
Jarkko Sakkinen Oct. 24, 2020, 11:34 a.m. UTC | #7
On Fri, Oct 23, 2020 at 07:19:05AM -0700, Dave Hansen wrote:
> On 10/23/20 3:17 AM, Jarkko Sakkinen wrote:
> > On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
> >> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> >>> + * Failure to explicitly request access to a restricted attribute will cause
> >>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> >>> + * is access to the PROVISION_KEY.
> >> Could we also justify why access is restricted, please?  Maybe:
> >>
> >> 	Access is restricted because PROVISION_KEY is burned uniquely
> >> 	into each each processor, making it a perfect unique identifier
> >> 	with privacy and fingerprinting implications.
> >>
> >> Are there any other reasons for doing it this way?
> > AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> > PROVISION_SEALING_KEY also have random salt added, i.e. they change
> > every boot cycle.
> > 
> > There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> > 3D :-)
> 
> Does that mean there are no privacy implications from access to the
> provisioning keys?  If that's true, why do we need a separate permission
> framework for creating provisioning enclaves?

As I've understood it, the key material for those keys is not even
required in the current SGX architecture, it was used in the legacy EPID
scheme, but the attribute itself is useful.

Let's assume that we have some sort of quoting enclave Q, which guards a
public key pair, which signs quotes of other enclaves. Let's assume we
have an attestation server A, which will enable some capabilities [*],
if it receives a quote signed with that public key pair.

1. E gets the report key with EGETKEY.
2. E constructs REPORTDATA (37.16) and TARGETINFO (37.17) structures.
   The former describes the enclaves contents and attributes and latter
   the target, i.e. Q in this artitificial example.
3. E calls EREPORT to generate a structure called REPORT MAC'd with the
   *targets* report key. It knows, which key to usue from REPORTDATA.
4. The runtime will then pass this to Q.
5. Q will check if ATTRIBUTE.PROVISION_KEY is set. If it is, Q will
   know that the enclave is allowed to get attested. Then it will
   sign the report with the guarded public key pair and send it to
   the attestation server.

The example is artificial, e.g. there could be something more complex,
but the idea is essentially this.

[*] With TPM and measured boot this could be to open network for a data
    center node. Quote is just the term used for a signed measurement in
    remote attestation schemes generally.

/Jarkko
Jarkko Sakkinen Oct. 24, 2020, 11:40 a.m. UTC | #8
On Fri, Oct 23, 2020 at 04:23:55PM +0200, Jethro Beekman wrote:
> On 2020-10-23 12:17, Jarkko Sakkinen wrote:
> > On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
> >> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> >>> + * Failure to explicitly request access to a restricted attribute will cause
> >>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> >>> + * is access to the PROVISION_KEY.
> >>
> >> Could we also justify why access is restricted, please?  Maybe:
> >>
> >> 	Access is restricted because PROVISION_KEY is burned uniquely
> >> 	into each each processor, making it a perfect unique identifier
> >> 	with privacy and fingerprinting implications.
> >>
> >> Are there any other reasons for doing it this way?
> > 
> > AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> > PROVISION_SEALING_KEY also have random salt added, i.e. they change
> > every boot cycle.
> > 
> > There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> > 3D :-)
> > 
> 
> This is nonsense. The whole point of sealing keys is that they don't
> change every boot. If did they they'd have no value over enclave
> memory. RAND means that the KEYID field from the KEYREQUEST is
> included in the derivation (as noted in the source row of the table
> you looked at).

I just looked that the column name is RAND, the row is called "Provision
key" and the cell has "Yes" in it.

> --
> Jethro Beekman | Fortanix

/Jarkko
Andy Lutomirski Oct. 24, 2020, 3:47 p.m. UTC | #9
On Sat, Oct 24, 2020 at 4:34 AM Jarkko Sakkinen <kernel.org@kernel.org> wrote:
>
> On Fri, Oct 23, 2020 at 07:19:05AM -0700, Dave Hansen wrote:
> > On 10/23/20 3:17 AM, Jarkko Sakkinen wrote:
> > > On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
> > >> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> > >>> + * Failure to explicitly request access to a restricted attribute will cause
> > >>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> > >>> + * is access to the PROVISION_KEY.
> > >> Could we also justify why access is restricted, please?  Maybe:
> > >>
> > >>    Access is restricted because PROVISION_KEY is burned uniquely
> > >>    into each each processor, making it a perfect unique identifier
> > >>    with privacy and fingerprinting implications.
> > >>
> > >> Are there any other reasons for doing it this way?
> > > AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> > > PROVISION_SEALING_KEY also have random salt added, i.e. they change
> > > every boot cycle.
> > >
> > > There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> > > 3D :-)
> >
> > Does that mean there are no privacy implications from access to the
> > provisioning keys?  If that's true, why do we need a separate permission
> > framework for creating provisioning enclaves?
>
> As I've understood it, the key material for those keys is not even
> required in the current SGX architecture, it was used in the legacy EPID
> scheme, but the attribute itself is useful.
>
> Let's assume that we have some sort of quoting enclave Q, which guards a
> public key pair, which signs quotes of other enclaves. Let's assume we
> have an attestation server A, which will enable some capabilities [*],
> if it receives a quote signed with that public key pair.
>
> 1. E gets the report key with EGETKEY.
> 2. E constructs REPORTDATA (37.16) and TARGETINFO (37.17) structures.
>    The former describes the enclaves contents and attributes and latter
>    the target, i.e. Q in this artitificial example.
> 3. E calls EREPORT to generate a structure called REPORT MAC'd with the
>    *targets* report key. It knows, which key to usue from REPORTDATA.
> 4. The runtime will then pass this to Q.
> 5. Q will check if ATTRIBUTE.PROVISION_KEY is set. If it is, Q will
>    know that the enclave is allowed to get attested. Then it will
>    sign the report with the guarded public key pair and send it to
>    the attestation server.

I think you have this a little bit off.  AIUI E won't have
ATTRIBUTE.PROVISION_KEY set -- Q will.  Q uses the provisioning key to
convince an Intel server that it's running on a genuine Intel CPU, and
the Intel server will return a signed certificate that Q can chain off
of to generate attestations for E.

Dave, I would rephrase what you're saying a bit.  The PROVISION_KEY
attribute allows enclaves to access keys that are unique to a
processor and unchangeable.  Unlike other SGX keys, these keys are not
affected by OWNER_EPOCH changes and therefore cannot be reset.

--Andy
Jarkko Sakkinen Oct. 24, 2020, 8:23 p.m. UTC | #10
On Sat, Oct 24, 2020 at 08:47:28AM -0700, Andy Lutomirski wrote:
> On Sat, Oct 24, 2020 at 4:34 AM Jarkko Sakkinen <kernel.org@kernel.org> wrote:
> >
> > On Fri, Oct 23, 2020 at 07:19:05AM -0700, Dave Hansen wrote:
> > > On 10/23/20 3:17 AM, Jarkko Sakkinen wrote:
> > > > On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
> > > >> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> > > >>> + * Failure to explicitly request access to a restricted attribute will cause
> > > >>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> > > >>> + * is access to the PROVISION_KEY.
> > > >> Could we also justify why access is restricted, please?  Maybe:
> > > >>
> > > >>    Access is restricted because PROVISION_KEY is burned uniquely
> > > >>    into each each processor, making it a perfect unique identifier
> > > >>    with privacy and fingerprinting implications.
> > > >>
> > > >> Are there any other reasons for doing it this way?
> > > > AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> > > > PROVISION_SEALING_KEY also have random salt added, i.e. they change
> > > > every boot cycle.
> > > >
> > > > There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> > > > 3D :-)
> > >
> > > Does that mean there are no privacy implications from access to the
> > > provisioning keys?  If that's true, why do we need a separate permission
> > > framework for creating provisioning enclaves?
> >
> > As I've understood it, the key material for those keys is not even
> > required in the current SGX architecture, it was used in the legacy EPID
> > scheme, but the attribute itself is useful.
> >
> > Let's assume that we have some sort of quoting enclave Q, which guards a
> > public key pair, which signs quotes of other enclaves. Let's assume we
> > have an attestation server A, which will enable some capabilities [*],
> > if it receives a quote signed with that public key pair.
> >
> > 1. E gets the report key with EGETKEY.
> > 2. E constructs REPORTDATA (37.16) and TARGETINFO (37.17) structures.
> >    The former describes the enclaves contents and attributes and latter
> >    the target, i.e. Q in this artitificial example.
> > 3. E calls EREPORT to generate a structure called REPORT MAC'd with the
> >    *targets* report key. It knows, which key to usue from REPORTDATA.
> > 4. The runtime will then pass this to Q.
> > 5. Q will check if ATTRIBUTE.PROVISION_KEY is set. If it is, Q will
> >    know that the enclave is allowed to get attested. Then it will
> >    sign the report with the guarded public key pair and send it to
> >    the attestation server.
> 
> I think you have this a little bit off.  AIUI E won't have
> ATTRIBUTE.PROVISION_KEY set -- Q will.  Q uses the provisioning key to
> convince an Intel server that it's running on a genuine Intel CPU, and
> the Intel server will return a signed certificate that Q can chain off
> of to generate attestations for E.

Right, I was confused by that RAND column, until Jethro corrected me.

Actually, quoting enclave (QE) authorizes itself with a provisioning
certification enclave (PCE), which holds certificates and revocation
lists for provisioning secrets unique to a CPU. And the sequence that I
described happens between PCE and QE. It accepts requests from enclaves
with ATTRIBUTES.PROVISION key bits set to 1 according to:

  https://software.intel.com/content/dam/develop/external/us/en/documents/intel-sgx-support-for-third-party-attestation-801017.pdf

The source code for the reference  is available here:

  https://github.com/intel/SGXDataCenterAttestationPrimitives

And binaries are here:

  https://01.org/intel-softwareguard-extensions/downloads/intel-sgx-dcap-1.6-release

They are provided for the inevitable reason that, it is the way bind to
the hardware, i.e. proof that you are running on a genuine CPU.

The network part is that PCE and QE can certify to an application, if an
enclave running in a different computer is an enclave.

> Dave, I would rephrase what you're saying a bit.  The PROVISION_KEY
> attribute allows enclaves to access keys that are unique to a
> processor and unchangeable.  Unlike other SGX keys, these keys are not
> affected by OWNER_EPOCH changes and therefore cannot be reset.

/Jarkko
Dr. Greg Oct. 27, 2020, 10:38 a.m. UTC | #11
On Sat, Oct 24, 2020 at 11:23:11PM +0300, Jarkko Sakkinen wrote:

Good morning, I hope the day is starting well for everyone.

> On Sat, Oct 24, 2020 at 08:47:28AM -0700, Andy Lutomirski wrote:
> > On Sat, Oct 24, 2020 at 4:34 AM Jarkko Sakkinen <kernel.org@kernel.org> wrote:
> > >
> > > On Fri, Oct 23, 2020 at 07:19:05AM -0700, Dave Hansen wrote:
> > > > On 10/23/20 3:17 AM, Jarkko Sakkinen wrote:
> > > > > On Tue, Oct 20, 2020 at 02:19:26PM -0700, Dave Hansen wrote:
> > > > >> On 10/2/20 9:50 PM, Jarkko Sakkinen wrote:
> > > > >>> + * Failure to explicitly request access to a restricted attribute will cause
> > > > >>> + * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
> > > > >>> + * is access to the PROVISION_KEY.
> > > > >> Could we also justify why access is restricted, please?  Maybe:
> > > > >>
> > > > >>    Access is restricted because PROVISION_KEY is burned uniquely
> > > > >>    into each each processor, making it a perfect unique identifier
> > > > >>    with privacy and fingerprinting implications.
> > > > >>
> > > > >> Are there any other reasons for doing it this way?
> > > > > AFAIK, if I interperet the SDM correctl, PROVISION_KEY and
> > > > > PROVISION_SEALING_KEY also have random salt added, i.e. they change
> > > > > every boot cycle.
> > > > >
> > > > > There is "RAND = yes" on those keys in Table 40-64 of Intel SDM volume
> > > > > 3D :-)
> > > >
> > > > Does that mean there are no privacy implications from access to the
> > > > provisioning keys?  If that's true, why do we need a separate permission
> > > > framework for creating provisioning enclaves?
> > >
> > > As I've understood it, the key material for those keys is not even
> > > required in the current SGX architecture, it was used in the legacy EPID
> > > scheme, but the attribute itself is useful.
> > >
> > > Let's assume that we have some sort of quoting enclave Q, which guards a
> > > public key pair, which signs quotes of other enclaves. Let's assume we
> > > have an attestation server A, which will enable some capabilities [*],
> > > if it receives a quote signed with that public key pair.
> > >
> > > 1. E gets the report key with EGETKEY.
> > > 2. E constructs REPORTDATA (37.16) and TARGETINFO (37.17) structures.
> > >    The former describes the enclaves contents and attributes and latter
> > >    the target, i.e. Q in this artitificial example.
> > > 3. E calls EREPORT to generate a structure called REPORT MAC'd with the
> > >    *targets* report key. It knows, which key to usue from REPORTDATA.
> > > 4. The runtime will then pass this to Q.
> > > 5. Q will check if ATTRIBUTE.PROVISION_KEY is set. If it is, Q will
> > >    know that the enclave is allowed to get attested. Then it will
> > >    sign the report with the guarded public key pair and send it to
> > >    the attestation server.
> > 
> > I think you have this a little bit off.  AIUI E won't have
> > ATTRIBUTE.PROVISION_KEY set -- Q will.  Q uses the provisioning key to
> > convince an Intel server that it's running on a genuine Intel CPU, and
> > the Intel server will return a signed certificate that Q can chain off
> > of to generate attestations for E.

> Right, I was confused by that RAND column, until Jethro corrected me.

The RAND column is probably misnamed, it doesn't really imply random
in the common sense of the meaning.  It implies that a 256 bit nonce
(keyid) can be supplied to the ENCLU[EGETKEY] instruction to perturb
the key derivation process.

The value is actually available in plaintext form as part of the
metadata for sealed data.

If it was really a random value, attestation wouldn't work.

> Actually, quoting enclave (QE) authorizes itself with a provisioning
> certification enclave (PCE), which holds certificates and revocation
> lists for provisioning secrets unique to a CPU. And the sequence that I
> described happens between PCE and QE. It accepts requests from enclaves
> with ATTRIBUTES.PROVISION key bits set to 1 according to:
> 
>   https://software.intel.com/content/dam/develop/external/us/en/documents/intel-sgx-support-for-third-party-attestation-801017.pdf
> 
> The source code for the reference  is available here:
> 
>   https://github.com/intel/SGXDataCenterAttestationPrimitives
> 
> And binaries are here:
> 
>   https://01.org/intel-softwareguard-extensions/downloads/intel-sgx-dcap-1.6-release
>
> They are provided for the inevitable reason that, it is the way bind
> to the hardware, i.e. proof that you are running on a genuine CPU.
>
> The network part is that PCE and QE can certify to an application,
> if an enclave running in a different computer is an enclave.

All of this discussion has lacked a certain amount of precision, as a
result the original issue with respect to Dave's concern regarding the
privacy implications of an enclave posessing the PROVISION_KEY
attribute has been lost.

First of all, it is important to note that two types of attestation
are available, EPID and DCAP/ECDSA.  They differ in their
implementation with respect to which enclaves need to have access to
derivation of the PROVISION_KEY.  What does remain constant is the
role that the PROVISION_KEY plays in all this.

The Platform Certification Enclave (PCE) has two roles:

1.) Generate a Platform Provisioning IDentifier (PPID).

2.) Certification of the fact that an enclave, other then the PCE, is
running on the same platform at a particular Trusted Computing Base
(TCB) level.

Being able to generate a PPID is the most privacy sensitive operation
that an enclave can peform, hence the recommendation to restrict
access to the attribute bit that allows an enclave to create a
derivation of the root provisioning key.

The PPID is a 256 bit symmetric key that is generated with the keyid
and security version values all set to null values.  As a result, any
enclave with a given MRSIGNER value will generate the same key value.
That value is used by Intel, and potentially others, to uniquely
identify the platform as long as it exists.

The PPID can be admixed with other information, such as the platform
security version of an enclave, to create a unique identifier for the
TCB state of enclave based software running on a particular platform.
This is role 2 of the PCE that I noted above.

In DCAP attestation, which is what Jarkko is referring to, both the
Quoting Enclave (QE) and PCE have access to PROVISION_KEY derivation.

In EPID attestation the PCE and the Provisioning Enclave (PVE) have
access to PROVISION_KEY derivation.

I guess it is up to community consensus as to whether or not this is a
privacy/security sensitive issue.  It provides precise enough
identification that Intel uses it to determine whether or not a
platform should be allowed or denied the ability to participate in
EPID attestation.

I believe that this is being used to to force the cloud based
platforms to use DCAP rather then EPID based attestation.  The
provision keys for these SKU's are not included in the Intel
Attestation Service (IAS) database so they cannot identify themselves
for provisioning of an EPID private key.

Since Intel has access to the root provisioning keys it can identify a
platform a-priori.  Other entities can use this infrastructure for
uniquely identifying platforms but it has to be done via an enrollment
process for a given signing key.

> /Jarkko

Hopefully the above clarifications are helpful.

Have a good day.

Dr. Greg

As always,
Dr. Greg Wettstein, Ph.D, Worker      Autonomously self-defensive
Enjellic Systems Development, LLC     IOT platforms and edge devices.
4206 N. 19th Ave.
Fargo, ND  58102
PH: 701-281-1686                      EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"I suppose that could could happen but he wouldn't know a Galois Field
 if it kicked him in the nuts."
                                -- Anonymous mathematician
                                   Resurrection.
diff mbox series

Patch

diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h
index e401fa72eaab..b6ba036a9b82 100644
--- a/arch/x86/include/uapi/asm/sgx.h
+++ b/arch/x86/include/uapi/asm/sgx.h
@@ -25,6 +25,8 @@  enum sgx_page_flags {
 	_IOWR(SGX_MAGIC, 0x01, struct sgx_enclave_add_pages)
 #define SGX_IOC_ENCLAVE_INIT \
 	_IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init)
+#define SGX_IOC_ENCLAVE_PROVISION \
+	_IOW(SGX_MAGIC, 0x03, struct sgx_enclave_provision)
 
 /**
  * struct sgx_enclave_create - parameter structure for the
@@ -63,4 +65,13 @@  struct sgx_enclave_init {
 	__u64 sigstruct;
 };
 
+/**
+ * struct sgx_enclave_provision - parameter structure for the
+ *				  %SGX_IOC_ENCLAVE_PROVISION ioctl
+ * @attribute_fd:	file handle of the attribute file in the securityfs
+ */
+struct sgx_enclave_provision {
+	__u64 attribute_fd;
+};
+
 #endif /* _UAPI_ASM_X86_SGX_H */
diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c
index 7bdb49dfcca6..d01b28f7ce4a 100644
--- a/arch/x86/kernel/cpu/sgx/driver.c
+++ b/arch/x86/kernel/cpu/sgx/driver.c
@@ -134,6 +134,10 @@  static const struct file_operations sgx_encl_fops = {
 	.get_unmapped_area	= sgx_get_unmapped_area,
 };
 
+const struct file_operations sgx_provision_fops = {
+	.owner			= THIS_MODULE,
+};
+
 static struct miscdevice sgx_dev_enclave = {
 	.minor = MISC_DYNAMIC_MINOR,
 	.name = "enclave",
@@ -141,6 +145,13 @@  static struct miscdevice sgx_dev_enclave = {
 	.fops = &sgx_encl_fops,
 };
 
+static struct miscdevice sgx_dev_provision = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "provision",
+	.nodename = "sgx/provision",
+	.fops = &sgx_provision_fops,
+};
+
 int __init sgx_drv_init(void)
 {
 	unsigned int eax, ebx, ecx, edx;
@@ -181,5 +192,12 @@  int __init sgx_drv_init(void)
 		return ret;
 	}
 
+	ret = misc_register(&sgx_dev_provision);
+	if (ret) {
+		pr_err("Creating /dev/sgx/provision failed with %d.\n", ret);
+		misc_deregister(&sgx_dev_enclave);
+		return ret;
+	}
+
 	return 0;
 }
diff --git a/arch/x86/kernel/cpu/sgx/driver.h b/arch/x86/kernel/cpu/sgx/driver.h
index e4063923115b..72747d01c046 100644
--- a/arch/x86/kernel/cpu/sgx/driver.h
+++ b/arch/x86/kernel/cpu/sgx/driver.h
@@ -23,6 +23,8 @@  extern u64 sgx_attributes_reserved_mask;
 extern u64 sgx_xfrm_reserved_mask;
 extern u32 sgx_xsave_size_tbl[64];
 
+extern const struct file_operations sgx_provision_fops;
+
 long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 
 int sgx_drv_init(void);
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index cf5a43d6daa2..3c04798e83e5 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -679,6 +679,49 @@  static long sgx_ioc_enclave_init(struct sgx_encl *encl, void __user *arg)
 	return ret;
 }
 
+/**
+ * sgx_ioc_enclave_provision - handler for %SGX_IOC_ENCLAVE_PROVISION
+ * @enclave:	an enclave pointer
+ * @arg:	userspace pointer to a struct sgx_enclave_provision instance
+ *
+ * Mark the enclave as being allowed to access a restricted attribute bit.
+ * The requested attribute is specified via the attribute_fd field in the
+ * provided struct sgx_enclave_provision.  The attribute_fd must be a
+ * handle to an SGX attribute file, e.g. "/dev/sgx/provision".
+ *
+ * Failure to explicitly request access to a restricted attribute will cause
+ * sgx_ioc_enclave_init() to fail.  Currently, the only restricted attribute
+ * is access to the PROVISION_KEY.
+ *
+ * Note, access to the EINITTOKEN_KEY is disallowed entirely.
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+static long sgx_ioc_enclave_provision(struct sgx_encl *encl, void __user *arg)
+{
+	struct sgx_enclave_provision params;
+	struct file *attribute_file;
+	int ret;
+
+	if (copy_from_user(&params, arg, sizeof(params)))
+		return -EFAULT;
+
+	attribute_file = fget(params.attribute_fd);
+	if (!attribute_file)
+		return -EINVAL;
+
+	if (attribute_file->f_op != &sgx_provision_fops) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	encl->attributes_mask |= SGX_ATTR_PROVISIONKEY;
+	ret = 0;
+
+out:
+	fput(attribute_file);
+	return ret;
+}
 
 long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
@@ -704,6 +747,9 @@  long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 	case SGX_IOC_ENCLAVE_INIT:
 		ret = sgx_ioc_enclave_init(encl, (void __user *)arg);
 		break;
+	case SGX_IOC_ENCLAVE_PROVISION:
+		ret = sgx_ioc_enclave_provision(encl, (void __user *)arg);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;