RE: Key endianness?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx>
> Sent: Monday, October 21, 2019 2:54 PM
> To: Pascal Van Leeuwen <pvanleeuwen@xxxxxxxxxxxxxx>
> Cc: linux-crypto@xxxxxxxxxxxxxxx; herbert@xxxxxxxxxxxxxxxxxxx
> Subject: Re: Key endianness?
> 
> On Mon, 21 Oct 2019 at 14:40, Pascal Van Leeuwen
> <pvanleeuwen@xxxxxxxxxxxxxx> wrote:
> >
> > > -----Original Message-----
> > > From: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx>
> > > Sent: Monday, October 21, 2019 1:59 PM
> > > To: Pascal Van Leeuwen <pvanleeuwen@xxxxxxxxxxxxxx>
> > > Cc: linux-crypto@xxxxxxxxxxxxxxx; herbert@xxxxxxxxxxxxxxxxxxx
> > > Subject: Re: Key endianness?
> > >
> > > On Mon, 21 Oct 2019 at 12:56, Pascal Van Leeuwen
> > > <pvanleeuwen@xxxxxxxxxxxxxx> wrote:
> > > >
> > > > Another endianness question:
> > > >
> > > > I have some data structure that can be either little or big endian,
> > > > depending on the exact use case. Currently, I have it defined as u32.
> > > > This causes sparse errors when accessing it using cpu_to_Xe32() and
> > > > Xe32_to_cpu().
> > > >
> > > > Now, for the big endian case, I could use htonl()/ntohl() instead,
> > > > but this is inconsistent with all other endian conversions in the
> > > > driver ... and there's no little endian alternative I'm aware of.
> > > > So I don't really like that approach.
> > > >
> > > > Alternatively, I could define a union of both a big and little
> > > > endian version of the data but that would require touching a lot
> > > > of legacy code (unless I use a C11 anonymous union ... not sure
> > > > if that would be allowed?) and IMHO is a bit silly.
> > > >
> > > > Is there some way of telling sparse to _not_ check for "correct"
> > > > use of these functions for a certain variable?
> > > >
> > >
> > >
> > > In this case, just use (__force __Xe32*) to cast it to the correct
> > > type. This annotates the cast as being intentionally endian-unclean,
> > > and shuts up Sparse.
> > >
> > Thanks for trying to help out, but that just gives me an
> > "error: not an lvalue" from both sparse and GCC.
> > But I'm probably doing it wrong somehow ...
> >
> 
> It depends on what you are casting. But doing something like
> 
> u32 l = ...
> __le32 ll = (__force __le32)l
> 
> should not trigger a sparse warning.
> 
I was actually casting the left side, not the right side,
as that's where my sparse issue was. Must be my poor grasp
of the C language hurting me here as I don't understand why
I'm not allowed to cast an array element to a different type
of the _same size_ ...

i.e. why can't I do (__be32)some_u32_array[3] = cpu_to_be32(some_value)?

I managed to work around it by doing *(__be32 *)&some_u32_array[3] =
but that's pretty ugly ... a better approach is still welcome.

> 
> > > > Regards,
> > > > Pascal van Leeuwen
> > > > Silicon IP Architect, Multi-Protocol Engines @ Verimatrix
> > > > www.insidesecure.com
> > > >
> > > > > -----Original Message-----
> > > > > From: Pascal Van Leeuwen
> > > > > Sent: Monday, October 21, 2019 11:04 AM
> > > > > To: linux-crypto@xxxxxxxxxxxxxxx; herbert@xxxxxxxxxxxxxxxxxxx
> > > > > Subject: Key endianness?
> > > > >
> > > > > Herbert,
> > > > >
> > > > > I'm currently busy fixing some endianness related sparse errors reported
> > > > > by this kbuild test robot and this triggered my to rethink some endian
> > > > > conversion being done in the inside-secure driver.
> > > > >
> > > > > I actually wonder what the endianness is of the input key data, e.g. the
> > > > > "u8 *key" parameter to the setkey function.
> > > > >
> > > > > I also wonder what the endianness is of the key data in a structure
> > > > > like "crypto_aes_ctx", as filled in by the aes_expandkey function.
> > > > >
> > >
> > > crypto_aes_ctx uses CPU endianness for the round keys.
> > >
> > So these will need to be consistently handled using cpu_to_Xe32.
> >
> 
> If you are using the generic aes_expandkey and want to reuse the key
> schedule, it is indeed good to be aware that both the round keys
> themselves as well as the key length are recorded in CPU endianness.
> 
Actually, I have a big patch standing by getting rid of aes_expandkey()
altogether as I don't need _any_ of those round keys generated, ii
was just used for AES key validity checks and nothing else.

But since that patch is not ready for prime time yet, I have to fix
these sparse errors for the time being.

> > > In general, though, there is no such thing as endianness for a key
> > > that is declared as u8[], it is simply a sequence of bytes.
> > >
> > Depends a bit on the algorithm. Some keys are indeed defined as byte
> > streams, in which case you have a point. Assuming you mean that the
> > crypto API follows the byte order as defined by the algorithm spec.
> >
> > But sometimes the key data is actually a stream of _words_ (example:
> > Chacha20) and then endianness _does_ matter. Same thing applies to
> > things like nonces and initial counter values BTW.
> >
> 
> Endianness always matters, and both AES and ChaCha are rather similar
> in that respect in the sense that it is the algorithm that defines how
> a byte stream is mapped onto 32-bit words, and in both cases, they use
> little endianness.
> 
Thanks, that's actually something I can _use_ ;-)

> 
> > > If the
> > > hardware chooses to reorder those bytes for some reason, it is the
> > > responsibility of the driver to take care of that from the CPU side.
> > >
> > Which still requires you to know the byte order as used by the API.
> >
> 
> Only if API means the AES or ChaCha specific helper routines that we
> have in the kernel. If you are using the AES helpers, then yes, you
> need to ensure that you use the same convention. But the algorithms
> themselves are fully defined by their specification, and so what other
> implementations in the kernel do is not really relevant.
> 
What is relevant is what the API expects ... and from 20 years of 
experience I would say many algorithm specifications are not exactly 
very clear on the byte order at all, often assuming this to be 
"obvious". (and if it's not little-endian, it's not obvious to me ;-)

Very often getting the byte order right was just trial and error 
using known-good reference vectors and just trying every possible
byte/word/whatever swap you could think of. (hence "ellendianness")

> 
> 
> > >
> > > > > Since I know my current endianness conversions work on a little endian
> > > > > CPU, I guess the big question is whether the byte order of this key
> > > > > data is _CPU byte order_ or always some _fixed byte order_ (e.g. as per
> > > > > algorithm specification).
> > > > >
> > > > > I know I have some customers using big-endian CPU's, so I do care, but
> > > > > I unfortunately don't have any platform available to test this with.
> > > > >
> > >
> > > You can boot big endian kernels on MacchiatoBin, in case that helps
> > > (using u-boot, not EFI)
> > >
> > I'm sure _someone_ can, I'm not so sure _I_ can ;-)
> >
> > Regards,
> > Pascal van Leeuwen
> > Silicon IP Architect, Multi-Protocol Engines @ Verimatrix
> > www.insidesecure.com


Regards,
Pascal van Leeuwen
Silicon IP Architect, Multi-Protocol Engines @ Verimatrix
www.insidesecure.com





[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux