diff mbox series

selftests/sgx: fix EINIT failure dueto SGX_INVALID_SIGNATURE

Message ID 20210301051836.30738-1-tianjia.zhang@linux.alibaba.com (mailing list archive)
State Accepted
Commit 567c39047dbee341244fe3bf79fea24ee0897ff9
Headers show
Series selftests/sgx: fix EINIT failure dueto SGX_INVALID_SIGNATURE | expand

Commit Message

tianjia.zhang March 1, 2021, 5:18 a.m. UTC
q2 is not always 384-byte length. Sometimes it only has 383-byte.
In this case, the valid portion of q2 is reordered reversely for
little endian order, and the remaining portion is filled with zero.

Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
---
 tools/testing/selftests/sgx/sigstruct.c | 41 +++++++++++++------------
 1 file changed, 21 insertions(+), 20 deletions(-)

Comments

Jarkko Sakkinen March 1, 2021, 9:54 a.m. UTC | #1
On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> q2 is not always 384-byte length. Sometimes it only has 383-byte.

What does determine this?

> In this case, the valid portion of q2 is reordered reversely for
> little endian order, and the remaining portion is filled with zero.

I'm presuming that you want to say "In this case, q2 needs to be reversed because...".

I'm lacking these details:

1. Why the length of Q2 can vary?
2. Why reversing the bytes is the correct measure to counter-measure
   this variation?

/Jarkko

> Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
> ---
>  tools/testing/selftests/sgx/sigstruct.c | 41 +++++++++++++------------
>  1 file changed, 21 insertions(+), 20 deletions(-)
> 
> diff --git a/tools/testing/selftests/sgx/sigstruct.c b/tools/testing/selftests/sgx/sigstruct.c
> index dee7a3d6c5a5..92bbc5a15c39 100644
> --- a/tools/testing/selftests/sgx/sigstruct.c
> +++ b/tools/testing/selftests/sgx/sigstruct.c
> @@ -55,10 +55,27 @@ static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m,
>  	return true;
>  }
>  
> +static void reverse_bytes(void *data, int length)
> +{
> +	int i = 0;
> +	int j = length - 1;
> +	uint8_t temp;
> +	uint8_t *ptr = data;
> +
> +	while (i < j) {
> +		temp = ptr[i];
> +		ptr[i] = ptr[j];
> +		ptr[j] = temp;
> +		i++;
> +		j--;
> +	}
> +}
> +
>  static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
>  		      uint8_t *q2)
>  {
>  	struct q1q2_ctx ctx;
> +	int len;
>  
>  	if (!alloc_q1q2_ctx(s, m, &ctx)) {
>  		fprintf(stderr, "Not enough memory for Q1Q2 calculation\n");
> @@ -89,8 +106,10 @@ static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
>  		goto out;
>  	}
>  
> -	BN_bn2bin(ctx.q1, q1);
> -	BN_bn2bin(ctx.q2, q2);
> +	len = BN_bn2bin(ctx.q1, q1);
> +	reverse_bytes(q1, len);
> +	len = BN_bn2bin(ctx.q2, q2);
> +	reverse_bytes(q2, len);
>  
>  	free_q1q2_ctx(&ctx);
>  	return true;
> @@ -152,22 +171,6 @@ static RSA *gen_sign_key(void)
>  	return key;
>  }
>  
> -static void reverse_bytes(void *data, int length)
> -{
> -	int i = 0;
> -	int j = length - 1;
> -	uint8_t temp;
> -	uint8_t *ptr = data;
> -
> -	while (i < j) {
> -		temp = ptr[i];
> -		ptr[i] = ptr[j];
> -		ptr[j] = temp;
> -		i++;
> -		j--;
> -	}
> -}
> -
>  enum mrtags {
>  	MRECREATE = 0x0045544145524345,
>  	MREADD = 0x0000000044444145,
> @@ -367,8 +370,6 @@ bool encl_measure(struct encl *encl)
>  	/* BE -> LE */
>  	reverse_bytes(sigstruct->signature, SGX_MODULUS_SIZE);
>  	reverse_bytes(sigstruct->modulus, SGX_MODULUS_SIZE);
> -	reverse_bytes(sigstruct->q1, SGX_MODULUS_SIZE);
> -	reverse_bytes(sigstruct->q2, SGX_MODULUS_SIZE);
>  
>  	EVP_MD_CTX_destroy(ctx);
>  	RSA_free(key);
> -- 
> 2.19.1.3.ge56e4f7
> 
>
tianjia.zhang March 2, 2021, 5:06 a.m. UTC | #2
On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
> 
> What does determine this?
> 
>> In this case, the valid portion of q2 is reordered reversely for
>> little endian order, and the remaining portion is filled with zero.
> 
> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> 
> I'm lacking these details:
> 
> 1. Why the length of Q2 can vary?
> 2. Why reversing the bytes is the correct measure to counter-measure
>     this variation?
> 
> /Jarkko
> 

When use openssl to generate a key instead of using the built-in 
sign_key.pem, there is a probability that will encounter this problem.

Here is a problematic key I encountered. The calculated q1 and q2 of 
this key are both 383 bytes, If the length is not processed, the 
hardware signature will fail.

-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

good luck!

Tianjia
Andy Lutomirski March 2, 2021, 5:54 a.m. UTC | #3
On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
<tianjia.zhang@linux.alibaba.com> wrote:
>
>
>
> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> > On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> >> q2 is not always 384-byte length. Sometimes it only has 383-byte.
> >
> > What does determine this?
> >
> >> In this case, the valid portion of q2 is reordered reversely for
> >> little endian order, and the remaining portion is filled with zero.
> >
> > I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> >
> > I'm lacking these details:
> >
> > 1. Why the length of Q2 can vary?
> > 2. Why reversing the bytes is the correct measure to counter-measure
> >     this variation?
> >
> > /Jarkko
> >
>
> When use openssl to generate a key instead of using the built-in
> sign_key.pem, there is a probability that will encounter this problem.
>
> Here is a problematic key I encountered. The calculated q1 and q2 of
> this key are both 383 bytes, If the length is not processed, the
> hardware signature will fail.

Presumably the issue is that some keys have parameters that have
enough leading 0 bits to be effectively shorter.  The openssl API
(and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
variable-size integers.

>
> -----BEGIN RSA PRIVATE KEY-----
> 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
> -----END RSA PRIVATE KEY-----
>
> good luck!
>
> Tianjia
>
Jarkko Sakkinen March 2, 2021, 12:51 p.m. UTC | #4
Nit: "due to"

Start with capital letter "Fix"

On Tue, Mar 02, 2021 at 01:06:52PM +0800, Tianjia Zhang wrote:
> 
> 
> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> > On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> > > q2 is not always 384-byte length. Sometimes it only has 383-byte.
> > 
> > What does determine this?
> > 
> > > In this case, the valid portion of q2 is reordered reversely for
> > > little endian order, and the remaining portion is filled with zero.
> > 
> > I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> > 
> > I'm lacking these details:
> > 
> > 1. Why the length of Q2 can vary?
> > 2. Why reversing the bytes is the correct measure to counter-measure
> >     this variation?
> > 
> > /Jarkko
> > 
> 
> When use openssl to generate a key instead of using the built-in
> sign_key.pem, there is a probability that will encounter this problem.
> 
> Here is a problematic key I encountered. The calculated q1 and q2 of this
> key are both 383 bytes, If the length is not processed, the hardware
> signature will fail.

Why is reversing bytes the correct way to fix the issue?

> -----BEGIN RSA PRIVATE KEY-----
> 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
> -----END RSA PRIVATE KEY-----
> 
> good luck!
> 
> Tianjia
> 
> 

/Jarkko
Jarkko Sakkinen March 2, 2021, 1:47 p.m. UTC | #5
On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
> <tianjia.zhang@linux.alibaba.com> wrote:
> >
> >
> >
> > On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> > > On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> > >> q2 is not always 384-byte length. Sometimes it only has 383-byte.
> > >
> > > What does determine this?
> > >
> > >> In this case, the valid portion of q2 is reordered reversely for
> > >> little endian order, and the remaining portion is filled with zero.
> > >
> > > I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> > >
> > > I'm lacking these details:
> > >
> > > 1. Why the length of Q2 can vary?
> > > 2. Why reversing the bytes is the correct measure to counter-measure
> > >     this variation?
> > >
> > > /Jarkko
> > >
> >
> > When use openssl to generate a key instead of using the built-in
> > sign_key.pem, there is a probability that will encounter this problem.
> >
> > Here is a problematic key I encountered. The calculated q1 and q2 of
> > this key are both 383 bytes, If the length is not processed, the
> > hardware signature will fail.
> 
> Presumably the issue is that some keys have parameters that have
> enough leading 0 bits to be effectively shorter.  The openssl API
> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
> variable-size integers.

But the test uses a static key. It used to generate a key on fly but
in some of the last versions I replaced key generation with a static
key:

static RSA *gen_sign_key(void)
{
	unsigned long sign_key_length;
	BIO *bio;
	RSA *key;

	sign_key_length = (unsigned long)&sign_key_end -
			  (unsigned long)&sign_key;

	bio = BIO_new_mem_buf(&sign_key, sign_key_length);
	if (!bio)
		return NULL;

	key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
	BIO_free(bio);

	return key;
}

/Jarkko
tianjia.zhang March 3, 2021, 12:03 p.m. UTC | #6
On 3/2/21 1:54 PM, Andy Lutomirski wrote:
> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
> <tianjia.zhang@linux.alibaba.com> wrote:
>>
>>
>>
>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
>>>
>>> What does determine this?
>>>
>>>> In this case, the valid portion of q2 is reordered reversely for
>>>> little endian order, and the remaining portion is filled with zero.
>>>
>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
>>>
>>> I'm lacking these details:
>>>
>>> 1. Why the length of Q2 can vary?
>>> 2. Why reversing the bytes is the correct measure to counter-measure
>>>      this variation?
>>>
>>> /Jarkko
>>>
>>
>> When use openssl to generate a key instead of using the built-in
>> sign_key.pem, there is a probability that will encounter this problem.
>>
>> Here is a problematic key I encountered. The calculated q1 and q2 of
>> this key are both 383 bytes, If the length is not processed, the
>> hardware signature will fail.
> 
> Presumably the issue is that some keys have parameters that have
> enough leading 0 bits to be effectively shorter.  The openssl API
> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
> variable-size integers.
> 

I agree with your opinion.

Thanks,
Tianjia
tianjia.zhang March 3, 2021, 12:12 p.m. UTC | #7
On 3/2/21 8:51 PM, Jarkko Sakkinen wrote:
> Nit: "due to"
> 
> Start with capital letter "Fix"
> 

Will do in the next patch.

> On Tue, Mar 02, 2021 at 01:06:52PM +0800, Tianjia Zhang wrote:
>>
>>
>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
>>>
>>> What does determine this?
>>>
>>>> In this case, the valid portion of q2 is reordered reversely for
>>>> little endian order, and the remaining portion is filled with zero.
>>>
>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
>>>
>>> I'm lacking these details:
>>>
>>> 1. Why the length of Q2 can vary?
>>> 2. Why reversing the bytes is the correct measure to counter-measure
>>>      this variation?
>>>
>>> /Jarkko
>>>
>>
>> When use openssl to generate a key instead of using the built-in
>> sign_key.pem, there is a probability that will encounter this problem.
>>
>> Here is a problematic key I encountered. The calculated q1 and q2 of this
>> key are both 383 bytes, If the length is not processed, the hardware
>> signature will fail.
> 
> Why is reversing bytes the correct way to fix the issue?
> 

This is caused by the incorrect length of the reversed data. If the 
length of q2 is 383 bytes, the inversion will cause the first byte to be 
zero. For this, please refer to the signature tool in sgx sdk:

https://github.com/intel/linux-sgx/blob/master/sdk/sign_tool/SignTool/sign_tool.cpp#L381

If it can be repaired, it may be possible to use to generate 
sign_key.pem key on fly instead of using the static key.

Best regards,
Tianjia
Jia Zhang March 10, 2021, 12:44 p.m. UTC | #8
On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
> On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
>> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
>> <tianjia.zhang@linux.alibaba.com> wrote:
>>>
>>>
>>>
>>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
>>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
>>>>
>>>> What does determine this?
>>>>
>>>>> In this case, the valid portion of q2 is reordered reversely for
>>>>> little endian order, and the remaining portion is filled with zero.
>>>>
>>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
>>>>
>>>> I'm lacking these details:
>>>>
>>>> 1. Why the length of Q2 can vary?
>>>> 2. Why reversing the bytes is the correct measure to counter-measure
>>>>     this variation?
>>>>
>>>> /Jarkko
>>>>
>>>
>>> When use openssl to generate a key instead of using the built-in
>>> sign_key.pem, there is a probability that will encounter this problem.
>>>
>>> Here is a problematic key I encountered. The calculated q1 and q2 of
>>> this key are both 383 bytes, If the length is not processed, the
>>> hardware signature will fail.
>>
>> Presumably the issue is that some keys have parameters that have
>> enough leading 0 bits to be effectively shorter.  The openssl API
>> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
>> variable-size integers.
> 
> But the test uses a static key. It used to generate a key on fly but

IMO even though the test code, it comes from the linux kernel, meaning
that its quality has a certain guarantee and it is a good reference, so
the test code still needs to ensure its correctness.

Jia

> in some of the last versions I replaced key generation with a static
> key:
> 
> static RSA *gen_sign_key(void)
> {
> 	unsigned long sign_key_length;
> 	BIO *bio;
> 	RSA *key;
> 
> 	sign_key_length = (unsigned long)&sign_key_end -
> 			  (unsigned long)&sign_key;
> 
> 	bio = BIO_new_mem_buf(&sign_key, sign_key_length);
> 	if (!bio)
> 		return NULL;
> 
> 	key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
> 	BIO_free(bio);
> 
> 	return key;
> }
> 
> /Jarkko
>
Jarkko Sakkinen March 10, 2021, 9:39 p.m. UTC | #9
On Wed, Mar 10, 2021 at 08:44:44PM +0800, Jia Zhang wrote:
> 
> 
> On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
> > On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
> >> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
> >> <tianjia.zhang@linux.alibaba.com> wrote:
> >>>
> >>>
> >>>
> >>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> >>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> >>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
> >>>>
> >>>> What does determine this?
> >>>>
> >>>>> In this case, the valid portion of q2 is reordered reversely for
> >>>>> little endian order, and the remaining portion is filled with zero.
> >>>>
> >>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> >>>>
> >>>> I'm lacking these details:
> >>>>
> >>>> 1. Why the length of Q2 can vary?
> >>>> 2. Why reversing the bytes is the correct measure to counter-measure
> >>>>     this variation?
> >>>>
> >>>> /Jarkko
> >>>>
> >>>
> >>> When use openssl to generate a key instead of using the built-in
> >>> sign_key.pem, there is a probability that will encounter this problem.
> >>>
> >>> Here is a problematic key I encountered. The calculated q1 and q2 of
> >>> this key are both 383 bytes, If the length is not processed, the
> >>> hardware signature will fail.
> >>
> >> Presumably the issue is that some keys have parameters that have
> >> enough leading 0 bits to be effectively shorter.  The openssl API
> >> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
> >> variable-size integers.
> > 
> > But the test uses a static key. It used to generate a key on fly but
> 
> IMO even though the test code, it comes from the linux kernel, meaning
> that its quality has a certain guarantee and it is a good reference, so
> the test code still needs to ensure its correctness.

Hmm... what is working incorrectly then?

/Jarkko
Jia Zhang March 11, 2021, 2:47 a.m. UTC | #10
On 2021/3/11 上午5:39, Jarkko Sakkinen wrote:
> On Wed, Mar 10, 2021 at 08:44:44PM +0800, Jia Zhang wrote:
>>
>>
>> On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
>>> On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
>>>> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
>>>> <tianjia.zhang@linux.alibaba.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
>>>>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>>>>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
>>>>>>
>>>>>> What does determine this?
>>>>>>
>>>>>>> In this case, the valid portion of q2 is reordered reversely for
>>>>>>> little endian order, and the remaining portion is filled with zero.
>>>>>>
>>>>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
>>>>>>
>>>>>> I'm lacking these details:
>>>>>>
>>>>>> 1. Why the length of Q2 can vary?
>>>>>> 2. Why reversing the bytes is the correct measure to counter-measure
>>>>>>     this variation?
>>>>>>
>>>>>> /Jarkko
>>>>>>
>>>>>
>>>>> When use openssl to generate a key instead of using the built-in
>>>>> sign_key.pem, there is a probability that will encounter this problem.
>>>>>
>>>>> Here is a problematic key I encountered. The calculated q1 and q2 of
>>>>> this key are both 383 bytes, If the length is not processed, the
>>>>> hardware signature will fail.
>>>>
>>>> Presumably the issue is that some keys have parameters that have
>>>> enough leading 0 bits to be effectively shorter.  The openssl API
>>>> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
>>>> variable-size integers.
>>>
>>> But the test uses a static key. It used to generate a key on fly but
>>
>> IMO even though the test code, it comes from the linux kernel, meaning
>> that its quality has a certain guarantee and it is a good reference, so
>> the test code still needs to ensure its correctness.
> 
> Hmm... what is working incorrectly then?

In current implementation, it is working well, after all the static key
can derive the full 384-byte length of q1 and q2. As mentioned above, if
someone refers to the design of signing tool from selftest code, it is
quite possible that the actual implementation will use dynamical or
external signing key deriving shorter q1 and/or q2 in length.

Going back the technical background, I'm not a crypto expert, so I
choose to check the code, doc and make experiment.

Accorindg to intel sdm vol3 37.14:

```
SIGSTRUCT includes four 3072-bit integers (MODULUS, SIGNATURE, Q1, Q2).
Each such integer is represented as a byte strings of length 384, with
the most significant byte at the position “offset + 383”, and the least
significant byte at position “offset”.

...

The 3072-bit integers Q1 and Q2 are defined by:
q1 = floor(Signature^2 / Modulus);
q2 = floor((Signature^3 - q1 * Signature * Modulus) / Modulus);
```

and the implementation of singing tool from Intel SGX SDK
(https://github.com/intel/linux-sgx/blob/master/sdk/sign_tool/SignTool/sign_tool.cpp#L381
), the most significant byte shuld be at the position “offset +
q1/q2_actuall_len”, and the padding portion should be filled with zero,
and don't involve the order reverse, but the selftest code always does.
This is the root cause of SGX_INVALID_SIGNATURE.

Just simplily enforce size_q1 and size_q2 to SE_KEY_SIZE, and generate
randome siging key with `openssl genrsa -3 -out signing_key.pem 3072`,
the SGX_INVALID_SIGNATURE error will appear up quickly.

Jia

> 
> /Jarkko
>
Jarkko Sakkinen March 11, 2021, 3:42 a.m. UTC | #11
On Thu, Mar 11, 2021 at 10:47:50AM +0800, Jia Zhang wrote:
> 
> 
> On 2021/3/11 上午5:39, Jarkko Sakkinen wrote:
> > On Wed, Mar 10, 2021 at 08:44:44PM +0800, Jia Zhang wrote:
> >>
> >>
> >> On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
> >>> On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
> >>>> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
> >>>> <tianjia.zhang@linux.alibaba.com> wrote:
> >>>>>
> >>>>>
> >>>>>
> >>>>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> >>>>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> >>>>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
> >>>>>>
> >>>>>> What does determine this?
> >>>>>>
> >>>>>>> In this case, the valid portion of q2 is reordered reversely for
> >>>>>>> little endian order, and the remaining portion is filled with zero.
> >>>>>>
> >>>>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> >>>>>>
> >>>>>> I'm lacking these details:
> >>>>>>
> >>>>>> 1. Why the length of Q2 can vary?
> >>>>>> 2. Why reversing the bytes is the correct measure to counter-measure
> >>>>>>     this variation?
> >>>>>>
> >>>>>> /Jarkko
> >>>>>>
> >>>>>
> >>>>> When use openssl to generate a key instead of using the built-in
> >>>>> sign_key.pem, there is a probability that will encounter this problem.
> >>>>>
> >>>>> Here is a problematic key I encountered. The calculated q1 and q2 of
> >>>>> this key are both 383 bytes, If the length is not processed, the
> >>>>> hardware signature will fail.
> >>>>
> >>>> Presumably the issue is that some keys have parameters that have
> >>>> enough leading 0 bits to be effectively shorter.  The openssl API
> >>>> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
> >>>> variable-size integers.
> >>>
> >>> But the test uses a static key. It used to generate a key on fly but
> >>
> >> IMO even though the test code, it comes from the linux kernel, meaning
> >> that its quality has a certain guarantee and it is a good reference, so
> >> the test code still needs to ensure its correctness.
> > 
> > Hmm... what is working incorrectly then?
> 
> In current implementation, it is working well, after all the static key
> can derive the full 384-byte length of q1 and q2. As mentioned above, if
> someone refers to the design of signing tool from selftest code, it is
> quite possible that the actual implementation will use dynamical or
> external signing key deriving shorter q1 and/or q2 in length.

A self-test needs is not meant to be generic to be directly used in 3rd
party code. With the current key there is not issue => there is no issue.

> 
> Going back the technical background, I'm not a crypto expert, so I
> choose to check the code, doc and make experiment.
> 
> Accorindg to intel sdm vol3 37.14:
> 
> ```
> SIGSTRUCT includes four 3072-bit integers (MODULUS, SIGNATURE, Q1, Q2).
> Each such integer is represented as a byte strings of length 384, with
> the most significant byte at the position “offset + 383”, and the least
> significant byte at position “offset”.
> 
> ...
> 
> The 3072-bit integers Q1 and Q2 are defined by:
> q1 = floor(Signature^2 / Modulus);
> q2 = floor((Signature^3 - q1 * Signature * Modulus) / Modulus);
> ```
> 
> and the implementation of singing tool from Intel SGX SDK
> (https://github.com/intel/linux-sgx/blob/master/sdk/sign_tool/SignTool/sign_tool.cpp#L381
> ), the most significant byte shuld be at the position “offset +
> q1/q2_actuall_len”, and the padding portion should be filled with zero,
> and don't involve the order reverse, but the selftest code always does.
> This is the root cause of SGX_INVALID_SIGNATURE.
> 
> Just simplily enforce size_q1 and size_q2 to SE_KEY_SIZE, and generate
> randome siging key with `openssl genrsa -3 -out signing_key.pem 3072`,
> the SGX_INVALID_SIGNATURE error will appear up quickly.
> 
> Jia
> 
> > 
> > /Jarkko
> > 
> 

/Jarkko
tianjia.zhang March 11, 2021, 4:53 a.m. UTC | #12
On 3/11/21 11:42 AM, Jarkko Sakkinen wrote:
> On Thu, Mar 11, 2021 at 10:47:50AM +0800, Jia Zhang wrote:
>>
>>
>> On 2021/3/11 上午5:39, Jarkko Sakkinen wrote:
>>> On Wed, Mar 10, 2021 at 08:44:44PM +0800, Jia Zhang wrote:
>>>>
>>>>
>>>> On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
>>>>> On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
>>>>>> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
>>>>>> <tianjia.zhang@linux.alibaba.com> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
>>>>>>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>>>>>>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
>>>>>>>>
>>>>>>>> What does determine this?
>>>>>>>>
>>>>>>>>> In this case, the valid portion of q2 is reordered reversely for
>>>>>>>>> little endian order, and the remaining portion is filled with zero.
>>>>>>>>
>>>>>>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
>>>>>>>>
>>>>>>>> I'm lacking these details:
>>>>>>>>
>>>>>>>> 1. Why the length of Q2 can vary?
>>>>>>>> 2. Why reversing the bytes is the correct measure to counter-measure
>>>>>>>>      this variation?
>>>>>>>>
>>>>>>>> /Jarkko
>>>>>>>>
>>>>>>>
>>>>>>> When use openssl to generate a key instead of using the built-in
>>>>>>> sign_key.pem, there is a probability that will encounter this problem.
>>>>>>>
>>>>>>> Here is a problematic key I encountered. The calculated q1 and q2 of
>>>>>>> this key are both 383 bytes, If the length is not processed, the
>>>>>>> hardware signature will fail.
>>>>>>
>>>>>> Presumably the issue is that some keys have parameters that have
>>>>>> enough leading 0 bits to be effectively shorter.  The openssl API
>>>>>> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
>>>>>> variable-size integers.
>>>>>
>>>>> But the test uses a static key. It used to generate a key on fly but
>>>>
>>>> IMO even though the test code, it comes from the linux kernel, meaning
>>>> that its quality has a certain guarantee and it is a good reference, so
>>>> the test code still needs to ensure its correctness.
>>>
>>> Hmm... what is working incorrectly then?
>>
>> In current implementation, it is working well, after all the static key
>> can derive the full 384-byte length of q1 and q2. As mentioned above, if
>> someone refers to the design of signing tool from selftest code, it is
>> quite possible that the actual implementation will use dynamical or
>> external signing key deriving shorter q1 and/or q2 in length.
> 
> A self-test needs is not meant to be generic to be directly used in 3rd
> party code. With the current key there is not issue => there is no issue.
> 

For keys generated on fly, self-test does not work properly, this 
experience is really worse.

Best regards,
Tianjia
Jia Zhang March 11, 2021, 5:55 a.m. UTC | #13
On 2021/3/11 上午11:42, Jarkko Sakkinen wrote:
> On Thu, Mar 11, 2021 at 10:47:50AM +0800, Jia Zhang wrote:
>>
>>
>> On 2021/3/11 上午5:39, Jarkko Sakkinen wrote:
>>> On Wed, Mar 10, 2021 at 08:44:44PM +0800, Jia Zhang wrote:
>>>>
>>>>
>>>> On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
>>>>> On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
>>>>>> On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
>>>>>> <tianjia.zhang@linux.alibaba.com> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
>>>>>>>> On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
>>>>>>>>> q2 is not always 384-byte length. Sometimes it only has 383-byte.
>>>>>>>>
>>>>>>>> What does determine this?
>>>>>>>>
>>>>>>>>> In this case, the valid portion of q2 is reordered reversely for
>>>>>>>>> little endian order, and the remaining portion is filled with zero.
>>>>>>>>
>>>>>>>> I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
>>>>>>>>
>>>>>>>> I'm lacking these details:
>>>>>>>>
>>>>>>>> 1. Why the length of Q2 can vary?
>>>>>>>> 2. Why reversing the bytes is the correct measure to counter-measure
>>>>>>>>     this variation?
>>>>>>>>
>>>>>>>> /Jarkko
>>>>>>>>
>>>>>>>
>>>>>>> When use openssl to generate a key instead of using the built-in
>>>>>>> sign_key.pem, there is a probability that will encounter this problem.
>>>>>>>
>>>>>>> Here is a problematic key I encountered. The calculated q1 and q2 of
>>>>>>> this key are both 383 bytes, If the length is not processed, the
>>>>>>> hardware signature will fail.
>>>>>>
>>>>>> Presumably the issue is that some keys have parameters that have
>>>>>> enough leading 0 bits to be effectively shorter.  The openssl API
>>>>>> (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
>>>>>> variable-size integers.
>>>>>
>>>>> But the test uses a static key. It used to generate a key on fly but
>>>>
>>>> IMO even though the test code, it comes from the linux kernel, meaning
>>>> that its quality has a certain guarantee and it is a good reference, so
>>>> the test code still needs to ensure its correctness.
>>>
>>> Hmm... what is working incorrectly then?
>>
>> In current implementation, it is working well, after all the static key
>> can derive the full 384-byte length of q1 and q2. As mentioned above, if
>> someone refers to the design of signing tool from selftest code, it is
>> quite possible that the actual implementation will use dynamical or
>> external signing key deriving shorter q1 and/or q2 in length.
> 
> A self-test needs is not meant to be generic to be directly used in 3rd
> party code. With the current key there is not issue => there is no issue.

Alright. So what we should do is to add a comment to explain why the
selfcode does something wrong and essentially it is intended.

Jia

> 
>>
>> Going back the technical background, I'm not a crypto expert, so I
>> choose to check the code, doc and make experiment.
>>
>> Accorindg to intel sdm vol3 37.14:
>>
>> ```
>> SIGSTRUCT includes four 3072-bit integers (MODULUS, SIGNATURE, Q1, Q2).
>> Each such integer is represented as a byte strings of length 384, with
>> the most significant byte at the position “offset + 383”, and the least
>> significant byte at position “offset”.
>>
>> ...
>>
>> The 3072-bit integers Q1 and Q2 are defined by:
>> q1 = floor(Signature^2 / Modulus);
>> q2 = floor((Signature^3 - q1 * Signature * Modulus) / Modulus);
>> ```
>>
>> and the implementation of singing tool from Intel SGX SDK
>> (https://github.com/intel/linux-sgx/blob/master/sdk/sign_tool/SignTool/sign_tool.cpp#L381
>> ), the most significant byte shuld be at the position “offset +
>> q1/q2_actuall_len”, and the padding portion should be filled with zero,
>> and don't involve the order reverse, but the selftest code always does.
>> This is the root cause of SGX_INVALID_SIGNATURE.
>>
>> Just simplily enforce size_q1 and size_q2 to SE_KEY_SIZE, and generate
>> randome siging key with `openssl genrsa -3 -out signing_key.pem 3072`,
>> the SGX_INVALID_SIGNATURE error will appear up quickly.
>>
>> Jia
>>
>>>
>>> /Jarkko
>>>
>>
> 
> /Jarkko
>
Jarkko Sakkinen March 12, 2021, 4:53 p.m. UTC | #14
On Thu, Mar 11, 2021 at 12:53:49PM +0800, Tianjia Zhang wrote:
> 
> 
> On 3/11/21 11:42 AM, Jarkko Sakkinen wrote:
> > On Thu, Mar 11, 2021 at 10:47:50AM +0800, Jia Zhang wrote:
> > > 
> > > 
> > > On 2021/3/11 上午5:39, Jarkko Sakkinen wrote:
> > > > On Wed, Mar 10, 2021 at 08:44:44PM +0800, Jia Zhang wrote:
> > > > > 
> > > > > 
> > > > > On 2021/3/2 下午9:47, Jarkko Sakkinen wrote:
> > > > > > On Mon, Mar 01, 2021 at 09:54:37PM -0800, Andy Lutomirski wrote:
> > > > > > > On Mon, Mar 1, 2021 at 9:06 PM Tianjia Zhang
> > > > > > > <tianjia.zhang@linux.alibaba.com> wrote:
> > > > > > > > 
> > > > > > > > 
> > > > > > > > 
> > > > > > > > On 3/1/21 5:54 PM, Jarkko Sakkinen wrote:
> > > > > > > > > On Mon, Mar 01, 2021 at 01:18:36PM +0800, Tianjia Zhang wrote:
> > > > > > > > > > q2 is not always 384-byte length. Sometimes it only has 383-byte.
> > > > > > > > > 
> > > > > > > > > What does determine this?
> > > > > > > > > 
> > > > > > > > > > In this case, the valid portion of q2 is reordered reversely for
> > > > > > > > > > little endian order, and the remaining portion is filled with zero.
> > > > > > > > > 
> > > > > > > > > I'm presuming that you want to say "In this case, q2 needs to be reversed because...".
> > > > > > > > > 
> > > > > > > > > I'm lacking these details:
> > > > > > > > > 
> > > > > > > > > 1. Why the length of Q2 can vary?
> > > > > > > > > 2. Why reversing the bytes is the correct measure to counter-measure
> > > > > > > > >      this variation?
> > > > > > > > > 
> > > > > > > > > /Jarkko
> > > > > > > > > 
> > > > > > > > 
> > > > > > > > When use openssl to generate a key instead of using the built-in
> > > > > > > > sign_key.pem, there is a probability that will encounter this problem.
> > > > > > > > 
> > > > > > > > Here is a problematic key I encountered. The calculated q1 and q2 of
> > > > > > > > this key are both 383 bytes, If the length is not processed, the
> > > > > > > > hardware signature will fail.
> > > > > > > 
> > > > > > > Presumably the issue is that some keys have parameters that have
> > > > > > > enough leading 0 bits to be effectively shorter.  The openssl API
> > > > > > > (and, sadly, a bunch  of the ASN.1 stuff) treats these parameters as
> > > > > > > variable-size integers.
> > > > > > 
> > > > > > But the test uses a static key. It used to generate a key on fly but
> > > > > 
> > > > > IMO even though the test code, it comes from the linux kernel, meaning
> > > > > that its quality has a certain guarantee and it is a good reference, so
> > > > > the test code still needs to ensure its correctness.
> > > > 
> > > > Hmm... what is working incorrectly then?
> > > 
> > > In current implementation, it is working well, after all the static key
> > > can derive the full 384-byte length of q1 and q2. As mentioned above, if
> > > someone refers to the design of signing tool from selftest code, it is
> > > quite possible that the actual implementation will use dynamical or
> > > external signing key deriving shorter q1 and/or q2 in length.
> > 
> > A self-test needs is not meant to be generic to be directly used in 3rd
> > party code. With the current key there is not issue => there is no issue.
> > 
> 
> For keys generated on fly, self-test does not work properly, this experience
> is really worse.

It does not generate keys on fly. There's a static key.

/Jarkko
diff mbox series

Patch

diff --git a/tools/testing/selftests/sgx/sigstruct.c b/tools/testing/selftests/sgx/sigstruct.c
index dee7a3d6c5a5..92bbc5a15c39 100644
--- a/tools/testing/selftests/sgx/sigstruct.c
+++ b/tools/testing/selftests/sgx/sigstruct.c
@@ -55,10 +55,27 @@  static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m,
 	return true;
 }
 
+static void reverse_bytes(void *data, int length)
+{
+	int i = 0;
+	int j = length - 1;
+	uint8_t temp;
+	uint8_t *ptr = data;
+
+	while (i < j) {
+		temp = ptr[i];
+		ptr[i] = ptr[j];
+		ptr[j] = temp;
+		i++;
+		j--;
+	}
+}
+
 static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
 		      uint8_t *q2)
 {
 	struct q1q2_ctx ctx;
+	int len;
 
 	if (!alloc_q1q2_ctx(s, m, &ctx)) {
 		fprintf(stderr, "Not enough memory for Q1Q2 calculation\n");
@@ -89,8 +106,10 @@  static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
 		goto out;
 	}
 
-	BN_bn2bin(ctx.q1, q1);
-	BN_bn2bin(ctx.q2, q2);
+	len = BN_bn2bin(ctx.q1, q1);
+	reverse_bytes(q1, len);
+	len = BN_bn2bin(ctx.q2, q2);
+	reverse_bytes(q2, len);
 
 	free_q1q2_ctx(&ctx);
 	return true;
@@ -152,22 +171,6 @@  static RSA *gen_sign_key(void)
 	return key;
 }
 
-static void reverse_bytes(void *data, int length)
-{
-	int i = 0;
-	int j = length - 1;
-	uint8_t temp;
-	uint8_t *ptr = data;
-
-	while (i < j) {
-		temp = ptr[i];
-		ptr[i] = ptr[j];
-		ptr[j] = temp;
-		i++;
-		j--;
-	}
-}
-
 enum mrtags {
 	MRECREATE = 0x0045544145524345,
 	MREADD = 0x0000000044444145,
@@ -367,8 +370,6 @@  bool encl_measure(struct encl *encl)
 	/* BE -> LE */
 	reverse_bytes(sigstruct->signature, SGX_MODULUS_SIZE);
 	reverse_bytes(sigstruct->modulus, SGX_MODULUS_SIZE);
-	reverse_bytes(sigstruct->q1, SGX_MODULUS_SIZE);
-	reverse_bytes(sigstruct->q2, SGX_MODULUS_SIZE);
 
 	EVP_MD_CTX_destroy(ctx);
 	RSA_free(key);