Hello, this is Dr. Miller and this
is Episode fifteen point three of
Assembly.
Today, we're going to talk about
cross platform areas and
then the as intricate intrinsics
and their implementation, and
then we'll disassemble these
intrinsics and look at them.
So cross platform as.
So if you go out there and Google
a tiny ass library or
one that is very small,
you can find a cross
platform C version that somebody
has written.
It's called Tiny Ass and C and
I put a GitHub link here
to this person's code.
And so one of the things that they
do is they implement a lot of the
different A-S
encryption libraries.
And it's it's pretty easy to go
through them and sort of read
how they work. And we've got a
couple of different ones here.
So, for example, there's
functions to initialize
the context of the library.
And then there is a couple of
different ways of encrypting.
So we have electronic codebook or
ECB and then we have cipher
block, Cheney or CBC.
And if you go and read on those,
you'll learn about why
electronic codebook is useful
and when you would want to use it,
and then when cipher block chaining
is useful and when you want to use
that.
And so we have both the encrypt and
the decrypt functions that we can
use inside of their.
And so one of the things that you'll
see and if you go in Google
about a so as uses the
Reindl soft cipher
defines this Xbox, and
so this Xbox is a bunch of lights
that are used for substitutions
that we can have. And we have a
forward one and we have an inverse
one.
So when you go through and look at
the as code, you'll end up seeing
all of these bytes.
So zero six three.
So this is defining what all those
boxes are.
And so in order to use it,
the programmer has to define
all of these bytes so that the
encryption, when they implement it,
is going to work properly.
And so, for example, we'll see here.
This is another function mixed
Cullum's. Right.
Which we've talked about before a
little bit.
But what it's going to do is it's
going to mix these columns
based on how A-s says that they're
supposed to be mixed.
Right. And so we've got a bunch of
different indexes and
you've got to make sure that you get
that right for the different columns
inside of the state matrix.
Another example is the shift rose
again in a Stazi, and
you can go and look at the source
code.
But this is shifting those rows into
different locations
and we can see that
again, it involves quite a bit of
code, right.
In comparison to what we'll look at
in the next one.
The one benefit of the previous
one is that it's cross
platform. So if your architecture
doesn't support these asymmetric
six, then you can use it.
But if you do have hardware support,
then you can use the asynchronous
implementation and there are a
couple of different versions of it.
So this is just one of the
implementations that I found.
Again, there's some code on GitHub
and it supports, again, the
initialization of the Auki
expansion and then it supports
the encrypt and decrypt.
And this is just and one hundred and
twenty eight bit s implementation.
Again, there's additional
ones that can be implemented
and those are implemented in that
cross platform one.
So a couple of things we see the
emem intrinsics, so that's
going to define a lot of different
memory access operations
that we might want to use, as
well as some other raw assembly
instructions.
And so when you're looking in here
and you see a type that is not your
normal type, that's because they're
using the W.M.
extension in order to implement
those as intrinsics.
So here again, we're going to see
these are basically raw assembly
commands. So it's going to take
Xcode and it's going to generate as
close to assembly as it can.
And it takes arguments.
And so then it implements that very
directly into our assembly
code. And we'll see how that
one to one correspondence works.
But we here have some macros.
So this is the key round and this
is for encryption.
And so we can see the key round is
actually this a pound of fine here.
And what pound of fine means is that
it's basically going to replace
this code with all of this
code. And so for every key round,
we end up taking the key at AI
and we have our round and then we do
that assist and then there's
some shuffle, some exercise,
and then we're we do one more X or
at the end. Right.
And so for each one of these rounds,
it's going to expand to one of
these.
And then this down here is for the
decryption. So it actually sets up
both of them at the same time.
So when we get to the encrypt
function, again, this is in S.
But this is the M.
A Yes.
Encrypt, right?
We see our we see a couple of loads
and an X and then we have our
encrypts for all of the rounds
and then we have the as encrypt last
at the very end.
Right. And so this is the very raw
implementation of that, using those
as intrinsics.
If we notice we didn't we're not
going to see that s box.
Right. So that is sort of built in
to the processor.
So it knows what that substitution
boxes, when it's going to go and do
encryption and
it's just implemented is one
instruction instead of the whole
bunch of instructions that we saw
inside of the C version.
Decryption is going to be similar.
Right. So, again, this is where
it sets up the inverse key for
decryption. So in this
person's implementation, where we
have it all at once, so we generate
the key
expansion. Right.
And then we do the inverse.
Right. So that's that inverse mix
columns, EMC that's in there.
So that's going to raw get
created for us directly
in assembly.
And then it's able to use the
decrypt with the key at
these different positions.
Again, we can see where those get
loaded and then they encrypt
decrypt last uses K
zero. So that initial
one that gets set is
used on the last one.
And so we have again, the
intrinsics.
We're able to use those in order to
very directly access the hardware
in order to do these operations.
And you'll see that a lot with
very specific extensions that
people want to use inside of C
in order to speed up their code.
And so now we can take that as
librarian, we can basically
disassemble it so we can see what
the assembly looks like.
So, for example, we can see
each one of these operations
ends up basically a one to one
correspondence between,
for example, key genesis,
the number one.
Right. That is this substitution
right here.
And it's got our round which are
around us. One, right.
Two four eight.
We can all see those on there.
And then we can see that we have the
shuffle operation and then
we can see we have the XOR
operations and there's a couple
loads inside of there.
And so again, it's a very direct
correspondence.
If you would were to take
the C version and decrypt
it. Clearly, it's not going to be
able to use the as libraries.
And additionally, it's going to do
all of that math for
encryption inside of the hardware.
And so at the end of the day, it's
going to take up more memory and
it's going to be slower.
And here we can see the encryption.
So again, we've got some load and
XOR and then we've got our encrypt.
We've got to invert
columns in there.
So we've got a couple of extra
operations, but it's directly
corresponding.
We got our ace encrypt
is going to directly correspond to
that and we can see our maximum
registers in there and the compiler
is managing all of those for us.
But if you're disassembling
some code and you see the V as
encrypt or Vachss decrypt,
right. You know that they're going
to use a yes for their encryption
mechanism.
So today we talked about a cross
platform, a yes and then sort
of compared that with the
implementation that can leverage
the alias intrinsics.
And then we disassemble it to sort
of see that there was a direct
correspondence between the
intrinsics defined in that WFM
library and the
assembly code that will get
generated for that.
So what are the benefits of using a
yes and I.
So we have reduced code size and
then we'll have faster execution.
If you have questions, you can email
me, millirems, you in custody
and you can find me on Twitter at
Milhouse 30.