[U-Boot] [PATCH v2] Implement generalised RSA public exponents for verified boot

Michael van der Westhuizen michael at smart-africa.com
Fri May 30 22:47:22 CEST 2014


Hi Simon,

Thanks for the feedback.

I'll take care of the nits and look into removing some special casing.

On 30 May 2014, at 9:04 PM, Simon Glass <sjg at chromium.org> wrote:

> Hi Michael,
> 
<snip>
>> 
>> /**
>> + * num_pub_exponent_bits() - Number of bits in the public exponent
>> + *
>> + * @key:       RSA key
>> + * @k:         Storage for the number of public exponent bits
>> + */
>> +static int num_public_exponent_bits(const struct rsa_public_key *key, int *k)
> 
> s/k/keyp/ or something like that.
> 
> Also is this function able to just use ffs() or similar?

flsll() yes, but that's not portable to Linux.

> 
<snip>

>> +}
>> +
>> +/**
>>  * pow_mod() - in-place public exponentiation
>>  *
>>  * @key:       RSA key
>> @@ -132,6 +171,7 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
>> {
>>        uint32_t *result, *ptr;
>>        uint i;
>> +       int j, k;
>> 
>>        /* Sanity check for stack size - key->len is in 32-bit words */
>>        if (key->len > RSA_MAX_KEY_BITS / 32) {
>> @@ -141,18 +181,49 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
>>        }
>> 
>>        uint32_t val[key->len], acc[key->len], tmp[key->len];
>> +       uint32_t a_scaled[key->len];
>>        result = tmp;  /* Re-use location. */
>> 
>>        /* Convert from big endian byte array to little endian word array. */
>>        for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
>>                val[i] = get_unaligned_be32(ptr);
>> 
>> -       montgomery_mul(key, acc, val, key->rr);  /* axx = a * RR / R mod M */
>> -       for (i = 0; i < 16; i += 2) {
>> -               montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
>> -               montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
>> +       if (0 != num_public_exponent_bits(key, &k))
>> +               return -EINVAL;
>> +
>> +       if (k < 2) {
>> +               debug("Public exponent is too short (%d bits, minimum 2)\n",
>> +                     k);
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (!is_public_exponent_bit_set(key, k - 1) ||
>> +           !is_public_exponent_bit_set(key, 0)) {
>> +               debug("Invalid RSA public exponent 0x%llx.\n", key->exponent);
> 
> What is invalid about it? Perhaps expand the message?
> 
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* the bit at e[k-1] is 1 by definition, so start with: C := M */
>> +       montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
>> +       /* retain scaled version for intermediate use */
> 
> Join these two comments, also the style should be:
> 
> /*
> * The bit at ...
> * ...
> */
> 
>> +       memcpy(a_scaled, acc, key->len * 4);
> 
> What is 4? is it sizeof(uint32_t?). I wonder if we could replace the
> line immediately above and remove this memcpy()?
> 
> For example, if you did:
> 
>       montgomery_mul(key, result, val, key->rr); /* acc = a * RR / R mod n */

Yes, it's sizeof(uint32_t) - that would probably be a good thing to spell out too.

result points to tmp, which is going to be repeatedly overwritten in the loop, but we need a_scaled to stay constant (as the result of the first montgomery_mul) throughout... or did I misunderstand your point?

> 
>> +
>> +       for (j = k - 2; j > 0; --j) {
>> +               montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
>> +
>> +               if (is_public_exponent_bit_set(key, j)) {
>> +                       /* acc = tmp * val / R mod n */
>> +                       montgomery_mul(key, acc, tmp, a_scaled);
>> +               } else {
>> +                       /* e[j] == 0, copy tmp back to acc for next operation */
>> +                       memcpy(acc, tmp, key->len * 4);
>> +               }
>>        }
>> -       montgomery_mul(key, result, acc, val);  /* result = XX * a / R mod M */
>> +
>> +       /* the bit at e[0] is always 1 */
>> +       montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
>> +       montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
>> +       memcpy(result, acc, key->len * 4);


<snip>

Michael



More information about the U-Boot mailing list