Dear viewer, these subtitles were generated by a machine via the service Trint and therefore are (very) buggy. If you are capable, please help us to create good quality subtitles: https://c3subtitles.de/talk/702 Thanks!
We are here for the Talk Wheel
of Fortune, analyzing
embedded OS, no generators
with your sweatsuits and
Alere Aliabadi, short
introduction there.
Both researchers, they
work with distributed and embedded
systems groups at the University
of Twin to.
Your sweatsuits is hardening systems
and hands on teacher for
offensive security,
Alea comes
as a
researcher from what we need in bomb
has a chair at system security.
Before that, he was head
of Vulnerability Analysis and Penetration
Testing Group at the Sharif University
of Technology in Tehran, Iran.
Starting with that, I'll just give
over to both of them and we'll have
a great talk and question the answers
later.
Yes, thank you.
Thanks.
All right, welcome, everybody,
to our Talk Wheel of Fortune, analyzing
embittered oys random number generators
to start with yours.
You want to introduce yourself?
I'm yours, Wetzel's, as I already was
introduced. And I'm a researcher at the
Distributed and Embedded System Security
Group. And 20.
This is.
Yeah, I am a
student at distributed an embassy,
some security group of University of
Toronto and visiting researcher at JFC
Central Committee of the local university
Baucom in Germany.
So we start with the introduction
to the EU's random number generator
today, and then we overview
some of the challenges
for generally and for
a specifically for a random number or a
random number generators.
We will have some case studies which
showing these challenges, how it's
affecting already existing
embittered oysters or real time operating
systems. And, well, this
work is actually an ongoing research is
part of your thesis,
which I am supervising.
And
yeah.
So so
first of all, let me say, some are
actually now everywhere from
consumer electronics,
medical devices, critical
infrastructures, military
equipment or aviation.
So actually, you see them everywhere.
And beside that, there is a drive
for connecting essentially the systems
as an Internet of Things,
wireless originary.
These devices was not designed to be
connected to the Internet.
But but now there is a gap which
vendors have to have to fix.
Right. And well, this can cause
problems. As you can see, for example,
for the random number generators, which
specifically work, you can see
there are problems.
For example, millions of devices use
the same high school association and
Triscuit, which made some noises
in the media.
So do
a random number generators.
Well, what is randomness,
I don't want to talk about the
philosophical talk of randomness
here, but well, it's generally
in extreme of if you cannot predict the
next bit with a probability
of more than 50 percent, then let's
call it random.
And another side of it is like entropy,
which is very interesting is a
measurement of information,
unpredictability and how
how unpredictable our information and
usually high entropy means very random
or high randomness.
And of course, why is these things
are important? Because actually random,
random, random numbers are actually
a fundamental part of other
security systems we have.
So, for example, if use it for
cryptography stuff, so for keys, answers
or exploit mitigations, which maybe
you never heard about it, but actually we
are using them for exploding situations
such as HLR or
smashing protections.
So randomness is actually critical for
other other underlying system
which builds up on them.
So that's why they are critical.
So how we can generate random numbers.
So physically, like true random number
generators are like radioactive
radioactive decays or Noisettes.
You can implement it
in two ways as external devices such as
2pm Orishas or
as integrated device within, for example,
into Ivy Bridge, CPU's or Certina
smartcards.
But there are some downsides for, for
example, your expensive or do some
portability issues when the cavender try
to move to the next architecture.
So that's why, because you
can't use those expensive hardwares you
are using, software is a random number.
Generators are like deterministic
algorithms, which you stretch
into sequence of random looking bits.
But the problem is that not all of these
random number generators are designed to
be used for security purposes.
For example, RAND, which we are
going to show it will be used
later by some people.
It's not designed for security purposes,
but some people anyway.
Uh, so
because of that, we have
secure random number generators
and those are usually
they have like three features or
properties, first of all, is that
the output must be indistinguishable from
the uniform and there
must have forward security, which means
that in case the internal internal
state of the of the system is
compromised, still the past
outputs must still appear random.
And again for port security
as a feature, which is that if internal
state is compromised again, the future
output still must appear
appear random, provided that the
preceding is either sufficient or
good quality entropy.
So because of that, designing
random number generators are not easy.
So because of that you have, for example,
some certain standards for it, like
NYST SB 890,
which has some some access to possibly a
source of student trappy.
But the problem is that these are
standard leave some heart problems, for
example, initial seed entropy
or resitting control or
how how is the quality of
the source of the entropy
is so because of that?
Well, some but some other people think
about it and design something else, such
as your or for Tunner,
which already implemented in some advice.
Or is it such as OSX or free BSD
or Aiwass.
So the problem
here is actually a chicken and egg
problem because, well,
to generate random numbers, you need
some kind of sort of entropy or
randomness. But this randomness, again,
needs another source of randomness.
So ideally, you want to use the physical
phenomena such as
like if we consider quantum randomness
is like radioactive decay, shock noises
or non quantum randomness, such as
termite noises, atmospheric noises and
sensory values. Well, this is so
let's say, not always available.
So practically now.
And for example, General-Purpose
Computer, as you can see, that you can
use unpredictable system events.
One good source is the user user
itself. So keystroke timing, mouse
movement or disk access can be used in
general purpose computers as a sort of
source of entropy.
And therefore, actually
we believe that randomness
or randomness should be
provided as a system service
because it's hard and hard to implement
it. And well, of course, people make
mistakes later if we don't.
So actually, many authors actually
already provide such randomness as a
system service, for example.
Do you do you random
in a Unix like system or create
an random API on windows?
And another important thing is that,
again, all of our lots of other security
products are built upon them.
So, for example,
open SSL, for example, assuming that
there is a secure service for our
operating system as a random number
generators and again based on open source
said you have like open access to an open
VPN.
So it's very, very important.
So now I think you're starting.
All right, so we've taken a look at the
general background of random
number generators, and now we'll take a
look at why it's so difficult to get
these right in in the embedded world.
So the common advice when you need random
numbers in the general-purpose world
is just used a few random and draw
from there.
But it's not as easy in the embedded
world because of various design issues,
which mean that operating system,
random number generators and the embedded
world are often absent or broken,
as we'll explore in this dark.
So the three main areas of
constraints are polyculture,
resource constraints and low entropy
environments, which we'll all discuss
into detail and how these relate to
particular implementation difficulties.
So the first of all is that
in the embedded world, you have a
polyculture of operating systems.
Which areas into general-purpose?
Well, you've got Linux, you've got
Windows, you've got your Mac OS X and
the embedded world.
You have various kinds of different
operating systems ranging from high
capability micro kernels to
very small monolithic systems,
all with different constraints and
different kind of capabilities, engaging,
catering to different systems.
So if you design a general operating
system, a random number generator design,
it's very hard to have this standardized
all across the board because of this
variety.
And the same, of course, applies to to
the hardware spectrum because you have a
wide range of microcontrollers and
microprocessors, all with different
capabilities.
And it's not uncommon to see older or
functionally stripped down versions in a
newly filtered devices.
So if you design
a random number generator based on the
assumption that you have some source of
hardware, a random number generator
or physical, a physical source
of entropy, then this means that your
operating system cannot be deployed
across a wide range of chips.
So that's that's definitely a major
design issue there.
And of course, embedded devices
are designed to have a small footprint
and to be resource efficient.
And this translates to various
limitations when designing random number
generators.
So, for example, limitations with regards
to CPU speed translate to
lightweight cryptography requirements.
Power consumption limitations, especially
for battery operated devices, mean
you need to have a simple design to have
limited entropy.
Falling activity and memory
limitations mean you need small entropy
and internal state in the random number
generator in order to implement it in
these strange devices.
And of course, there's the issue of
the embedded world just generally giving,
being very boring.
There is little activity going on and
what activity is going on is usually very
predictable.
And there is a limitation with regard to
to common entropy.
Sources like like Ali discussed and the
general purpose world.
You often use desk activity, timings,
keyboard events, mouse
events. But in the embedded world, you
often have to deal with diskless, nodes.
You don't have peripherals, you don't
have a user, and you don't have hardware,
random number generators.
And even commonly available sources like
Interop request timings are often not
that good because they're too periodic.
And these conditions are usually worse
during good time because you have
predictable boot sequences, there's
little activity going on at boot
and so mantlepiece sources you might want
to rely on are simply not available yet
because they have to be initialized by
the system after the boot sequence.
Yet none blocking interfaces to a random
number generator such as the Daphnia
random interface allow from drawing from
the random number generator, even when
insufficient entropy is actually
available in the system.
And this results in something called the
boot time entropy hole.
So this is particularly bad because
a lot of embedded devices often generate
cryptographic keys on the first system.
So this means that if you have a system
with general low entropy conditions and
an initial state predetermined in the
factory combined with these these
low voltage conditions
and then generating a key, this
results in very,
very serious cryptographic issues.
A common solution you encounter to deal
with with bootcamps. Entropy in the
general-purpose world is using so-called
sealed files, which is basically file
with collected randomness, which is drawn
from by the random number generator
put into the system.
And when that the system shuts down,
it writes to the file again.
But in the embedded world, it's kind of
hard to generally deploy a solution
because how are you going to deal with
diskless notes?
How are you going to draw your entropy
before a file system is mounted, which is
often required?
And still, this doesn't solve the first
good problem.
So some common embedded work arounds
you encounter is including an initial
seed file in the firmware, and this
initial seed file obviously better
be unique and unpredictable firmware
image as it doesn't do you much good
or using personalization data such
as the Mac address or serial number
of rider and using
it as seed entropy, which is also a very
bad idea shown in the research
mentioned on the bottom or using
other dubious sources of entropy such as
Gloc timings, process IDs, foreign
Mac addresses, etc., etc., or
simply including hardcoded regenerated
keys, which is also a bad idea as shown
in the little black box project.
So now that we have an idea
of why it's hard to to to get embedded
operating system, random number
generators, right.
We're going to look at a couple of case
studies of operating systems fielded in
various embedded into the corporate
various embedded systems and how
they get this wrong.
So the first system we'll look at is QNX,
which is a Unix like Botox compliant
Real-Time Operating System, initially
released in 1982 and later acquired
by by BlackBerry.
It's basically the underlying operating
system for BlackBerry OS.
It's used a lot in automotive systems as
well, particularly the entertainment
systems.
You also encountered in carrier grade
routers, military radios and some nuclear
power plants.
And it provides a custom def random
implementation, which is always non
blocking. So you don't have this this
blocking, non blocking distinctions you
have in most Unix systems.
And it's implemented as a userspace
process addressed by external resource
manager.
Because Kernel,
an interesting thing to note is that the
random number generator has always
started after bood by a startup
script.
So that's that's the thing to keep in
mind.
And we reverse engineered the
implementation of the random number
generator, and it turned out to be based
on Yaro by Bruce Schneier and John
Ferguson, but it turned out
to be based on an older
draft implementation of Yaro, another
reference, 01 60 document,
which was which accompanied the
paper release.
So it only as a single entry people and
no fast and slow pulls and no blocks
before is applied to appear in gene
output at all.
It's directly drawn from the internal
state.
So and given zero in turn,
diverges from this older implementation
as well, by mixing Beerenberg output back
into the entropy people and having some
reseat control divergences, which
we'll discuss later on.
So this is the design of
QNX, Yaro, which is relatively simple,
you have your Budiman entropy.
If you run from entropy and it's drawn
into an actual people, and then you have
the output function which draws from the
people and also sits back into
the induced state.
We first tested the randomness, quality
of the device output, using
the dye harder and the statistical test
suite tools it passed both
of these test to, but this only tells us
something about the quality of the
Beerenberg output.
The source entropy can still be heavily
biased, as we'll see later on.
After reverse engineering the boot
time gathering routines, we
found that it draws from four sources
only and these are static and non
configurable.
That's the system time.
The clock cycle counts the currently
active process IDs and the currently
active device names.
And they concatenate days and they pull
it. Rudisha one hash function and the
resulting digest is used to initialize
the QNX zero initial.
So we decided to because this sounded
kind of dodgy, we decided to evaluate
the Butan entropy, because if this is
very biased, it might be feasible for
an attacker to replicate the Berrington
internal state after a reasonable number
of guesses.
So our quality measure is the main
entropy, which basically means how likely
you are to guess a particular value on
the first try and 256
bits of uniformly random data after
56 bits of entropy.
We use the next entropy source testing
tool to evaluate this this data.
And we collected 50 bood runs by
instrumenting the random number
generator and logging the raw data that
was collected during Butan and the
average MIN entropy is zero point zero
two seven six, which
isn't good at all because that means it
has far less than one bit of entropy
for eight bits of raw data.
As you can see in the visualization on
the right were the dark spots are low
entropy spots with a particularly low
entropy spot at the bottom
left.
At the top left, I mean.
So we also have evaluated
the crossbow entropy, because
even if a system has relatively
good entropy quality during
a single Buderim, if it's consistent
among various bood runs, this is also
behavior you don't want.
And it turned out that apart from
having less than stellar
single bood entropy gathering, it
also had a very consistent, predictable
pattern across 50 bood visualizations,
as you can see on the right.
And you need to consider that this is
operating systems like these are deployed
in firmware images.
So processes always spawn in the same
order and there's the same number of
processes.
So all these process ideas that are fed
into the boot time and trappy are
usually static and the same goes for the
device names. And really the only
randomness here comes from the clock time
and the clock cycles.
And even there, there is less variation
than you would want because of the real
time nature of the system.
So this is what the after reverse
engineering, the runtime and entropy
collection engine looks like
on the left. You got your high
performance, got measurements on the top.
You have system information, which is
basically process ID, threat ideas,
flags, all these kind of process
variables which are fed into the
through a Channel one into the Yaro input
function.
And in the bottom left you have your
interrupt the timing source.
In the bottom right there is an
undocumented function, which is
a callback option to a library, possibly
for two random number generator support.
But there is nothing in the documentation
there and it's not clear from the code
either. So.
So some thoughts on this random entropy.
The system information polling has some
problems because there's lots of static
information. Things like user ID, flags
and priority are not likely to vary
at all between different runs and
stack. And programs will only vary if
you enable address space layered
randomization, which is disabled by
by default and time or program
state based randomness is really the only
randomness you're going to get from this
source when it comes to the Interop
timings. One of the big problems is
that it really puts the burden on the
developer because the developer has to
select, which interrupts to draw the
entropy from.
So that means that they have to decide
are these quality sources,
are they not triggered to periodically,
etc., etc..
But this doesn't really matter, because
in almost all QNX versions, there
is no reseat control.
They actually, after reversing the
binary, they implemented the functions,
but it never actually them, which
means that runtime entropy is accumulated
but never actually makes back into the
state. And booting entropy is the only
entropy you'll find in the entropy
of a QNX Yaru implementation.
And this is very dangerous, especially if
you consider the quality of Buthayna
entropy. We earlier saw
in the latest version QNX six
point six. This is there
was an attempt to fix this by integrating
some form of reseating into functions
called during initialization and output.
So whenever they appear in G output, it
recedes from part of the pool.
But an issue is that no entropy
estimation is actually done.
And this is what Yaro was initially
designed to do, to do entropy estimation
on your entropy pools.
So you only received when you have proper
entropy quality in these pools.
But this isn't what it does.
It just receives all the time.
Luckily, we disclosed some of these
issues to BlackBerry and based on our
suggestions, they drafted a new Fortuna
based Beerenberg for the successor
of Yaro.
For those who don't know.
And it's available in batches for QNX six
point six. And it will be the default
random number generator for the upcoming
QNX seven, which should be released, I
think in January or something like that.
So this brings us to the next operating
system, which we can mention because it
was studied under NDA.
It's compliant Real-Time operating system
used in highly sensitive systems such
as the Joint Strike Fighter, the JTR
US military radio system and the
International Space Station.
And it has a random number
generator available via a random
interface.
And it has two associated functions
called your random read, which fills a
buffer with an bytes
from its random function and your random
right, which receives the Berenger using
only the first D word from from
the buffer you provided.
So that that gives you an idea of the
quality of this thing.
So we reverse engineer this as well and
took a look at what the underlying
Berenger actually was.
And it turned out to be the Gillette CB
is the random function with custom
constants.
And as the documentation clearly
states, this is not a secure random
number generator. So I don't know
why they implemented it there, but
it's there.
That's not the worst thing, because
we also discovered a local reseeded
attack because the Dafu random device is
ruled rideable, which means that anyone
in the system can force appearing reseat
regardless of their privileges.
So a very low privileged user
can simply ride the seat due to random
number generator and then all across
the board control the pure output.
So, yeah, that's nice.
But even if that even if that wasn't
enough, we also discovered
a known seed attack, because if you
reverse engineer the initialization
routines, you see that there is no
seeding at all.
There's just a static 32 bit
seed, which is the same across
all these operating system deployments.
It doesn't vary from Fermor.
It's just the same sequence over
and over again. And there's no actual
entropy in the system at all.
So an attacker who knows the beer
and also knows because
beer and GS are deterministic functions.
They also know all corresponding beer,
the output consumed by crypto
applications.
So she can see on the slide here, the
S.A.G. generator simply draws
from the same output we saw earlier
produced by this known seed.
So consider a remote attacker,
no no local attacker who
has a publicly generated on this target
operating system.
And they know the initial period and
they simply cloned a random number
generator, seek the appropriate state
offset, read from the random number
generator, generate a corresponding
public and private keeper.
And if it matches the target publicly,
well, obviously also the private key
matches. And if it doesn't, it it reads
to the next state
offset. And because the state offsets are
determined by how many bytes have been
read from the random device,
this is bounded by a very reasonable
brute force, upper bound because I don't
think more than four gigabytes will have
been read from the random number
generator before generating your keys.
So we can even compute a lot of this
and we can do a live demo.
But this is a screenshot of an attack
on the day of the device
itself, where we will recover the
private key corresponding to the S.H.
Osaki within a couple of Driss.
And yeah,
that's basically it for this operating
system. You're right.
Yeah.
And the funny thing is, I don't think
even they are going to patch it,
but so
the last case I saw, these vehicles works
six point nine.
It's a real time operating system,
initially released in 1987,
is actually using, for example, Mars,
Curiosity Rover, Apache helicopters
or like 47 B drones or
lots of telecommunication equipment.
Well, about weeks
works, actually. It doesn't provide any
secure run up numbers.
And actually, you can see in libraries
such as open, as I said, well, first of
all, there is no reference for it either.
And, well, it will have
predictable consequences, too.
So as you can, if you're searching the
Internet for the developers who are
asking questions about this stuff about
the Explorer, you can see that well,
somebody comes and say, hey, I
incremented use the RAND
function as seeding
source for, I don't know, the
openness, it said.
Which, as you remember, we initially
said that it's not secure,
it's not it shouldn't be used
for security purposes and.
Well, yeah,
well, and if you are thinking that
this three operating system where at
least the first two, which had a problem
and you were laughing a lot about it, is
the divorce actually is not actually in
the Midwest and real time operating
systems, actually, majority of them
do not support any sexual random numbers.
And and vice work
is far from the only one with
these problems. But we'll be exploring
one of the biggest one. And we expect
that they provide something which they
don't.
And you want to take it.
Yeah.
Yeah. So what are the takeaways from
this? Well, the first one is that the
world is harsh because there are
constraints everywhere and low
entropy issues are very serious.
And it's hard to deal with these in
an operating system that seeks deployment
across various kinds of chips with
different capabilities.
CSP orangy design is not a joke.
Secure randomness should be provided as
an operating system service whenever
possible.
Please don't put the burden on developers
because they will screw up across
these issues from the mailing list
I've shown and more scrutiny
is required because the advice just used
a few random shooting, not land a
developer into trouble as it would
with these previous operating systems.
And too much of the embedded security
world is still unexplored terrain.
So we need more offensive research
into these embedded operating systems
to get them almost up to speed with
a general purpose. Well.
So if you're looking for more technical
details on embedded security, I recommend
or talk at Nic's Enigma in 2017
and if you've got any questions, you can
ask them now.
OK, thanks a lot, first,
for questions and answers, please use
the microphones, just line
up behind the microphones and I'll pick
you for your questions.
I'll start with you.
So this is not a question, this is a nice
story that might be replicated,
but only questions at
the moment would be all this is
about randomness.
This is about right.
Because I talked to
an HP lab engineer from
Bristol and he told me the following
story because they had so much
bandwidth on the Internet.
They then decided, well, let's see
what happens if we send a random
bitstream to death row in a foreign
country.
It just took two weeks for
the GC HQ
to knock on the door and ask them
what the heck they are doing there.
And the random number generator they used
was was a noise diet.
OK, thank you.
Question from the Internet is a radio
noise from a software defined radio a
good source of entropy for a random
number generator?
I'm sorry, Karoubi question.
Uh, is radio a noise
that you get from a software defined
radio chip? Would that be a good source
of entropy?
I as a known quantity, yeah.
I mean, I guess it depends on your
threat model because, um,
is it possible that the attacker controls
radio signals around the device
that that draws solemnly from
the the chip
in a specific frequency range?
Yes. Yeah. I mean, if we can control a
specific frequency, then,
well, it's not.
And it's really dependent on the.
Yeah, it could be good, but it really
depends on your threat model.
Is it a remote attack or you're dealing
with an attacker with physical access,
et cetera, et cetera.
One of the slides you mentioned
a little bit closer to the microphone.
One of the slides you mentioned
only boot into a low entropy attack.
Do you have any best practice
recommendations for application?
Because on Lennix,
they have random blocks, for example,
on the BSD, that random does
not block unless it hasn't been seeded
yet and obviously sets it
in the bootloader stage before.
Even the kind of main function answer
is because developers
have to know every operating system.
Well, the problem with the blocking
thing is and this came up in
communications with BlackBerry as well,
is that if you say I only provide
randomness when I have
sufficient entropy in the pool, and I'm
sure that this is high quality, this
is not as easy to do in the embedded
world, because that means that, for
example, if you need some sort of secure
randomness during boot and you don't
have enough entropy, then good times get
really slow, and especially if you have
devices under real time constraints.
This is an engineering hurdle right
there. So I'd say
a paper was published, I think at the
Security and Privacy 2013.
I think it was called something like
Welcome to the Tropics or something
like that.
And there were some good best practices.
Recommendations for the embattled world
are mainly in the form of seed files.
But as we mentioned already, if you have
diskless nodes there, it's kind of an
open problem to design a real good
embedded open source, random number
generator for all across
the board.
Uh, second microphone back there, please.
Uh, thank you.
You mentioned the NDA you have with the
vendor. What is the nature of your
relationship with this vendor?
How did you end up with an NDA, with
them? And how
do you ensure they are not going to fix?
I can just I can just tell you that
it took one year for us to
get to us because they're providing.
Well, they claim security, job security.
So that's how it is,
to be honest, in lots of real time
operating systems, they are living in
1998.
So it's an academic effort, not
a consulting assignment.
OK, thank you.
OK, then you please.
Thanks for good talk.
First question, um,
are the eight
relies on you to fight
random before
for initializing Colonel.
Address randomization, layout
randomization.
Do you think that relying
on bootloader is better
for operating system than trying
to solve random problem with
ugly means?
I mean, don't take into
don't take a random number generating
the responsibility of their operating
system, but put it to bootloader.
Yeah, I mean, I guess that depends on,
uh.
Well, on your design model, for example,
um, that would require you
to, to have a bootloader
that standardized all across the board
where you want to deploy it.
For example, if there is no bootloader
that's suitable for the kind of embedded
systems you want, but you do want an
operating system and it doesn't have a
random number generator, then
you're left without a random number
generator. So it's one of the biggest
problems. And this is where it is.
Polyculture argument comes in is
that in the general-purpose world, you
can make some assumptions about hardware,
roughly looks like this roughly as these
capabilities software the same,
but the number in the embedded world,
there is so much diversity
that it's probably better to
optionally include functionality
all across the, uh, the software stack
in this case than to simply say,
oh, we simply assume it's there in the
bootloader. And then it turns out that
it's not there in the bootloader
or thinks another idea.
Can we rely on the manufacturer,
which makes a small
device without a random number of sources
to put
to feed the device by random
input during the manufacturing?
I mean, attach the device
before selling it to some random,
expensive random number generator,
uh, get the random input and then
go.
Yeah, it's one of the things I mentioned
that's essentially a seed file and it's
one of the things I mentioned in the
slides. If you include a seed
file with your firmware image and you
make sure it's random them firmware
image, then that might be
a workaround.
But that depends on how well the vendor
understands what they're doing, because a
case in point would be the Western
digital self encrypting drives thing
where they actually generated keys based
on the Lipsey Rand function.
So we export.
Yeah, that kind of stuff.
So it could be a solution.
But yeah, that depends on the vendor
whether they do it.
Well, thanks.
You think you OK?
We have time for one short last question.
OK, you have three pretty bad examples
here. Do you have a broader field,
broader view of the field?
Are there is it a general problem
that they are all this bad or did you
just pick the three worst ones that you
stumbled upon?
Are there some operating systems
that do it right, whatever it might
be for this? No, actually, these are the
best. The best.
OK, thank you very much.
A warm round of applause for them again,
please.