Our next talk is about reproducible builds the first 10 years and I'll let Holger explain
Hello everybody. So I'm not a lunar I'm Holger but that was the interest light of
lunar's talk 10 years and two days ago. I'm based in Hamburg I work on Debian
since many years and I've also been to foster many years. Ten years ago we did
the first setup with all videos and all rooms and then I gave up with video and
cut and voile for reproducible builds. We're working mostly on Debian but I try
to make or try to contribute help make all software all free software reproducible
and it's pretty complex topic ask me anything anytime during the next two
days because there's a lot of information in this talk. So reproducible builds. This is not my
talk but the talk of the people working on this these are over 150 people and it's not my
knowledge we have them in Git so if you are missing there then you can add yourself to this
repository and be here. So about you who knows about reproducible builds why and how a bit.
Yay that is awesome I can go home now thank you. Who has contributed to reproducible builds?
Wee thank you.
Who knows that reproducible builds have been around for more than 30 years? Ten years.
Because 30 years really old not as old as net BST or maybe it is. Who knows about S-Bomb?
The industry. So S-Bomb is software build of materials and basically our build info files
from 2014 also already have this contain all the build environment describe what's in there.
It's the same concept more or less. And we need you it's not going reproducible builds
nothing five or ten or even fifty people can do it needs to be done in every software project
needs continuous testing that software is reproducible. But I think we can do it and there's still a lot of work to do.
So I give a short introduction the problem source code is freely available which is not a problem
but most people use binaries and that is a problem. And no one really knows if this binary really comes from the source code.
I'll get to that in a moment. And as a result there are various supply chain attacks.
So long time ago more than ten years ago there was a threat on devil mailing list in 2007
and it was known but it seemed undoable. This email would be really cool if deviant policy required that packages could be rebuilt
bit identical from source and then somebody replied I see no benefit.
Someone else replied I for one think this is technically infeasible but hey I'm happy to be proved wrong.
I'm happy to prove them wrong. So that was ten years ago but the idea also appeared in the year 2000 already in another threat.
And then in 2017 we learned that GCC was reproducible in the early 90s on several architectures and not only GCC but also binutils and the whole new tool chain.
But that got lost that got bit rotten and people forgot.
So fast forward to last year. There was a mail on the wire guard mailing list of VPN up for Android said that the bills are now reproducible.
The release is identical on their website Google Play store on an asteroid. And that was well and they didn't even tell us.
Yay so great. We're super happy.
This logo by the way we developed in 2016. So it's also 80 years old was a logo by design committee and in the end I think it turned out nice anyhow.
So our definition when is it reproducible. It built is reproducible given the same source code built environment and built instructions.
Any party can recreate it by bit identical copies of all specified artifact. Pretty simple.
Yeah it gets more complicated because you need to have everything. What is source code. What is the environment and so on.
So our mission is to enable anyone to independently verify that a given source produces bit by bit identical results.
And by that we are an important building block in making supply chains more secure. Nothing more nothing less reproducible builds are not more secure than others.
They're just built more securely and unsecure software still remains unsecure.
But with reproducible builds you cannot be sure that you run this insecure software.
And this again is from Luna's talk from 10 years ago. It's pretty much the same definition that we have now.
And by 2024 reproducible builds have been widely understood. We have resources documentation. We have public scientific publication.
There's lots of material online. And even the White House has said about us. They made a release which in 2021 government statement which requires software bill of materials for governmental software.
And at the moment only recommends reproducible builds. But hey the White House recommends our work. Yay.
How did we get there. Money.
Snowden.
Why money. Bitcoin.
10 years ago actually 12 years ago in 2012 or 11 the software was made reproducible because Bitcoin all bitcoins were worth four billion.
I think there was very much more now. But they were still afraid if there was a compromised Bitcoin client would steal the Bitcoin.
The developers would be accused of having a back door and they didn't want this. So they basically made reproducible builds.
And Snowden is kind of obvious. And so the tour people made tour browser reproducible in 2013.
Because they were afraid that they would get back door. And tour browser is Firefox. One of the biggest software projects in the world.
50 or 70 or whatever megabyte binary at the time. Every bit was the same. And there was. Wow.
So how did we really get there.
Lot of work by many people over many years.
And.
Debcom 13 in 2013 there was a box of small workshop last minute 30 attendees and that kicked off the Debbie in a thought for reproducible builds.
And then Luna had this another box at that conference team.
And the stock here.
And we had the first package that patches for the package to Debbie and package maintainer.
We sorted the files and created built info files built info files is where we store the environment and the sources and the product.
The output the binaries.
And with that we can reproduce them. And that was all done in 2014 already.
And in September 2014 I started systematic builds of Debbie and packages twice.
First does handle packages and then all 25,000 at that time.
And Mike Perry and said she gave a presentation at Congress.
See Congress in December of 2014 showing my graphs.
It was really nice sitting in the audience and suddenly seeing this graph I made.
And I have some from the slides.
So this is the presentation.
2014 again.
And I want to believe that is really the problem with trusting somebody that this binary comes from.
Whether it's needs to need to believe me or Microsoft or your government or Debbie and you need to believe somebody saying that's not believing is not scientific at all.
And I am the developer.
It's I know it's on my machine and I'm upstanding careful and yeah.
But we develop us are also excellent targets.
I just spoke with somebody who's producing the GPG binaries for Windows who would have interest to compromise that several nation states.
So.
And they had that to very nice proof of concept.
So the most secure computer in the world is that network most computers on network USB access.
24 seven you can compromise computers and especially if one computer gives you access to 100 millions of other computers or lots of money or whatever the state secrets.
Where whatever you terrorist or war taxi want to make.
So they made a small back door.
They use the CDE against SS eight where the the.
It's greater and it should be greater equal.
That's the difference and gives you who to exploit.
And in the binary the difference is one bit.
So they are seven e.
Seven C is the difference whether somebody can get root on your computer.
And it's very hard to detect.
And then they made another thing.
They made a Linux kernel module which modifies.
That if the compiler looks at the source code and it's not a good thing.
And then they made another thing and they made a Linux kernel module which modifies.
That if the compiler looks at the source code it will take different compile different code than if you look at it with an editor.
And then they made a proof of concept for that.
So these attacks are not only feasible they are possible and probably be done.
And this was the graph they showed.
No they must have showed an earlier graph because it was from 2014.
But anyway the green pack is the percentage of Debian packages reproducible.
The orange one are unreproducible and the red ones are failing to build.
But it was still more than half the packages were quite early reproducible.
So 2015.
Luna and myself gave a talk here.
And this was the first talk where we were spread from Debian to going to all free software projects.
I think it was quite nicely perceived.
Because since then we have lots of collaboration.
And Luna gave her presentation at CCCCAM presenting many problems.
We found many many problems and come on ways to work against them.
And we had the first reproducible build summit in Athens.
We had the time I think we were 25 people from 15 projects or something.
And we wrote source date epoch spec which I explained in a second.
And divorce code.
So first the common reason for unreproducibility is time stamps.
People leave time stamps everywhere.
And they leave more time stamps.
Really every documentation tool has time stamps.
Compilers have time stamps.
And there's build parses.
Also very annoying.
And the rest.
And the rest is about 400 different kind of issues or something.
But it's mostly time stamps and build parses.
And for build parses to get that is very easy.
You just rebuild in the same build parses.
And nowadays with name spaces it's also trivial to do.
And for time stamps we came up with source date epoch.
Who knows about source date epoch?
Yoo hoo hoo.
Build time stamps are largely meaningless.
Source date epoch describes the time of the last modification of the source.
In seconds since the unique epoch.
Because that is consistent.
This is deterministic.
It doesn't change.
And this means that was when the software last changed.
And when you know the build environment you also know all the libraries you're using.
So there's no use to record a time stamp.
And that's supported by a lot of software today.
If this build environment variable is set.
Then it's used and there's 100 tools.
DCC is using it.
Pundock is using it.
Whatever is using it.
And the specification is also really stable.
We modified it once in 2017 and that's it.
So it's been working.
And it's available on the internet.
Difascope.
Who knows about Difascope?
You should all know about Difascope.
I met lawyers who know Difascope.
Who uses Difascope?
Nothing against lawyers.
I explained it.
Difascope tries to get to the bottom of what makes files or directories different.
It will recursively unpack archives into many kinds and transforms various binary formats
into more human readable form to compare them.
So you have a tar archive.
And in the tar archive is a PDF.
And in the PDF is an image.
And the image has a varying time stamp.
Difascope will show this.
And it has large file system formats.
So basically for anything.
APK files, DEX files, all file systems,
GBG, keybox databases, HTML, anything.
There's more JPEG, whatever.
It compares two objects.
And this is also why there's a lot of different types of files.
And it's not just a file.
It's a file.
And it compares objects.
And this is also why lawyers like to use it,
because they compare two PDFs,
and then they see which text changes.
And there's other use cases,
but we don't also use it to find out why something is unreproducible.
Not if it's unreproducible.
If it's unreproducible, it's easy because the hash doesn't match.
But really why?
And it falls back on HexStump.
It does fuzzy matching
and many things.
It does disassembling.
Here you can also go to try Diffrescope Org and upload two objects and it will show you the difference.
Not sure if you can read this, but basically the colors are.
There's an archive, there's at the top, there's the bits are different,
and then here you see really the diff between the two versions.
And because I compared two different versions, 5.06 and 5.07, the version numbers of course change.
But you can look at many differences with Diffrescope.
If you haven't taken a look at Diffrescope, do.
So in the last 10 years we filed almost 4,000 bucks with patches and 3,500 of them have already been merged.
So there's only 300 left and there's still some more coming.
And in general in Debian we found over 32,000 bucks.
Most are failing to build from source because we constantly rebuild Debian, but there's also many other things.
The Reproducer Builds is also a huge QA effort.
And yeah, we have a Git repository very categorized the issues and put, okay, this package is also affected by this.
And Luna's talk is also a good reference for this.
And it's because it's much easier to describe what makes a problem a package unreproducible,
we have created the unreproducible packages package which shows many, many problems and how to fix them,
because a reproducible package is very, it's hard to show why it's reproducible.
It's very easy to show what's unreproducible.
And some of the unexpected benefits we had is lower development costs and increased development speeds through less developer time.
Google is one of the main users of this benefit because the builds are way faster, of course you can cash way more.
And it's also good for software development to see if this change really just affects this part you thought it would be effect.
And for license compliance, you can only be sure it's free software if you know the binary is coming from the source.
As you're running some binary, maybe it matches the license, maybe it doesn't, who knows.
Yeah, and you have reproducible verified S-bombs.
S-bombs are just a statement with reproducible builds you have verified S-bombs.
So we made these summits over the years, mostly in Europe.
And we're going to have a summit this year as well.
There were always like 50 people around something.
But there were many, many projects there.
Like all the BSD, FDROID, Github, Microsoft, RATAT, Apache, Maven, whatever, many, many, many.
And there was another benefit, bootstrapable org.
It began as a breakout session at the Reproducible Build Summit in Berlin.
Who knows about bootstrapable org?
Some people.
So my understanding is you have 500 byte block which can build in this very small assembler,
which builds another small assembler, which builds a tiny C-C, which builds an old GCC,
which builds an old GCC, which builds modern GCC.
So you bootstrap from sources only.
And they bootstrap Dix, which is another Linux distribution.
It's pretty amazing.
They have their own talk here.
And that is just because there was an idea to do this and people really tried this.
And bootstrapping, completely bootstrapping from source has not been done since the 60s or 70s.
We all just use binaries, building binaries, building binaries.
For the summit this year, we don't know where, we don't know when.
We need a location for 50 people.
We need some sponsors to cover the costs.
And we need you to make it happen.
Please talk to me after the event if you have an idea where to hold this.
In general, we have some funding.
We are a Software Freedom Conservancy project since 2018.
Funding is for Chris Lam, Mati Aritzolo, Vagrant Cascadian and myself.
We support our continuous work, the development, community work,
developing software, designing processes, the summit.
Thanks to all our sponsors.
So short overview of various projects, which is mostly about Debian.
So these are the CI results for Debian Trixie.
We are now in the 95% range and it's pretty boring.
The graph has become very boring.
This is a bit nicer.
So these are the past Debian releases.
Bookworm is the current release.
Bullseye is two years ago.
Buster is four years ago.
And you can see the unreproducible packages have gone constantly down,
but there are still over 600 unreproducible packages.
And these I really want to get to zero.
This is still the goal.
So these are the CI results for Debian Unstable for the last 10 years.
And you can see in the right here in the end in 2023,
we stopped varying the build pass.
That's why we went from 85 to 95%.
But Debian is constantly growing and we are getting constantly getting more reproducible.
So in 2017, we changed or Debian changed policy and now says packages should build reproducible.
It's not a must.
It's just that would be really nice.
And of course I want to get to the must, but that is not so easy.
So I want to have reproducible packages must not regress as a next step.
And in 2025, because that will be after the next Debian release.
And also new packages must build reproducible.
I don't want any new packages which are not reproducible.
It's been 10 years, it's over.
And finally in whatever 2027, one, two more releases.
I think all packages must build reproducible to be allowed into testing unstable.
That can be an unstable experimental.
You can experiment with that.
And really 100% is the goal.
And 100% reproducible is a political decision and nothing technical.
Because we can always say, okay, you're out.
And that is political, not technical.
So we need to change policy.
And we can work around must have offenders using whitelist in the beginning.
Like at the moment Grubb and Linux kernel are not reproducible.
And I guess most people want to use them.
And goal is still 100%.
Whitelist are just a way to achieve that goal eventually.
Because with that we can kick the others out.
And then Debian testing migration.
I'm not sure how many know Debian workflow.
So there's packages get uploaded to unstable, then they move to testing.
And eventually testing is declared stable.
So this moving to testing, this migration, there's various penalties or can be introduced.
And since three months or something, it now shows if the package is unreproducible,
there's no penalty or nothing yet.
But I think for the next release, there should be penalties for violating,
not regressing, and new packages must be reproducible.
And the framework is now there.
It's just not activated yet.
And the whitelisting part I already said.
So, and this, this is a bit stepped for the next part.
Because what I showed you before these other graphs,
this graph is just about continuous integration where we build the package twice
in maximum variation to see why a package is not reproducible.
But what we really want to do is Debian builds a package once,
and we want to rebuild it to see if we can reproduce it.
And we don't want to find differences, we want to find the same thing.
So for this, this, we have made this other rebuilder,
and this was already working two years ago, and it also showed good results,
but then it stopped working.
Because we need the working snapshot Debian org service.
Snapshot has all the Debian binaries ever released.
And without snapshot, we cannot recreate the same environment.
But snapshot is buggy.
And this has been buggy for five years.
And so this is broken.
Sad.
And Snaps fixing snapshot, it's 150 terabytes of data.
It has four pushes per day, gaining 70 gigabytes of data every day.
One project to fix, so I got access to fix it.
Yay.
We need something soon.
We still need to fix snapshot, so if somebody wants big data,
we need this, please talk to me.
But at the summit last year, we also did, we don't need the whole snapshot.
We only want to reproduce 70,000 binary packages,
and they will depend on 30,000 packages.
So 40,000 packages are never used as built-in pens.
And then it looks at the build info files,
because the build info file describes the environment,
and those 30,000 packages are only used on 100,000 variations.
So we only need 100,000 packages.
That's just 100 gigabytes per arch and suit, so that's nothing.
It's just two terabytes or something.
It fits on my laptop.
So we rebuild our snapshot, it was born.
And that's a cache for Snapshot WNORG,
which only stores the packages used as built-in pens today.
And if new version is, then the old built-in pens are not needed anymore.
Because Snapshot has this problem, seeding this still takes a week,
but we've done this, and then each arch only takes hours to seed from another instance.
And we already run two instances of rebuild a snapshot,
and our goal is to allow many instances,
so you can just have your snapshot cache in your institution and use it.
And this is needed because DAP rebuild,
which is used for rebuilding DAP packages,
then uses the boot snap together with meta-snap.
Because the packages don't have the trust information,
and the meta-snap has the metadata from Snapshot WNORG,
so you have a trust pass there.
But because there's only five minutes left, I will skip those details.
And rebuild a snapshot only has one issue at the moment,
because we only started it in early December,
and then there was Christmas and Congress and whatever,
so we didn't fix this issue.
And this is, Lynx and Yosh have really helped with that.
I've done some work, but the coding part is mostly them.
I've done the design work.
I hope to have this working in a month or at least two.
I don't really care when. We've waited five years, so yay.
And so Outlook testing migration can use and force policy,
but we need real rebuilders,
because we don't want to test immigration just on CI results.
And therefore the rebuilders, we need a working snapshot,
and we will keep the CI builds to really still find the issues.
I can give a very short overview now in the last three minutes
about other projects.
Tails is easy. Tails was the first project which is reproducible.
You can rebuild the Tails ISO, and be sure that's the same ISO.
ArchDinox has rebuilt us in Snapshot Binary and Active Community.
They really rock. They know more about this than I do.
Zouza is one person, but maybe that person will be allowed to do a reproducible Zouza fork
on company time this year.
So Zouza, I'm looking forward to Zouza in this regard.
MixoS and GeekZoS are by design reproducible,
but they also have still the unreproducible Linux software.
Yachto has support for reproducible images,
and FDroid also has reproducible packages in the repository.
Alpine has basic support.
FreeBSD, the base system is reproducible for all BSDs.
We never tested OpenBSD, and we never tested the ports.
Fedora Red Hat Ubuntu is not interested, it seems,
but that is not really true anymore.
Fedora has enabled in Macro, so that source state epoch is now used
when building packages, so Fedora could have this easily.
Ubuntu, I would really love a Debian fork, which is reproducible.
Take the Debian sources, throw away the Debian build processes,
do them new, and make a Debian binary fork, which is reproducible.
So many projects support reproducible builds in a way or another,
but it's mostly in theory, so it's unclear what it does,
how users benefit.
Tales is easy. Tales has one ISO, one checks them, you can recreate it
with Debian with 60,000 packages.
How do you verify them? It's still open.
And this is massive success.
This was thought impossible 10 years ago.
This is, again, a 10-year-old slide.
In theory, we are done.
In practice, we have shown that reproducible builds can be done in theory.
We need rebuilders, we need to store the results,
we need defined criteria, how tools should treat the data,
and then we need to use these tools.
Because if you have several rebuilders, which you basically want,
what you do with the results are not matching.
And yeah, those last 5% or it's maybe 2% now,
we still need to fix the software.
And we need project-level consensus and commitment
to keep reproducible builds working in practice.
Thank you.
Thank you for the talk. I learned a lot actually.
I had vaguely heard about it, but very good introduction.
Anyone have any questions?
Hello, Agarhe.
Most of the graphs you were showing were for AMD64, I think.
Do you have any information about the other architectures?
Is there any difference between AMD64 and ARM64, for example?
We also have graph for ARM64, I-386 and ARMHF,
and I just got an offer for RISC64 hardware.
So when we do this rebuilders, we want to have every WN architecture.
But it's, yeah, get there.
Any more questions?
How about, I actually have several questions.
How about source releases?
Because this is a problem with many projects
that they don't have reproducible sources.
If you want to get an expulsion or something,
unless the original tower is around,
you cannot remake it easily from a weapon.
It's getting out of the...
The releases of the source code or the source release?
The releases of the source code.
For many projects, it's still hard.
Is there any effort around that?
It depends mostly on the tools,
like whether G-SIP or GitHub, when it creates an archive, is reproducible.
We have basically decided not to look at this,
because if you do a release once, you have version X,
and that version X stays.
Being able to reproduce will recreate the same version.
We've just decided to be out of scope.
But it's worthwhile, do it.
Another thing is variants.
For some distributions,
they support a lot of variants of packages,
and these distributions are more interested in causal analysis.
How we arrive at certain versions
and why we didn't arrive at it.
Because this is what enables us to fix
the things that didn't allow us to have a reproducible build.
And if you have 100 variants multiplied by 1000 packages,
that's a problem.
I would not say that the number of packages matters.
Of course, if they are reproducible, you can have 100,000 of packages.
Is there any effort in causal analysis
of why a package is not reproducible?
Can you very hardly understand you, because it's so loud.
Is there any effort to build tools to do causal analysis?
Why the packages are?
Yes, we've built this. This is the framework to analyze this.
But first you check whether the packages are reproducible,
but just comparing the hash.
Build it twice, and if the hash is the same, it is the same.
And if not, you can use Difloscope to analyze why.
We've also had Bernhard Wiedemann from ZUSA
also made some scripts to analyze the build logs
to make a statistically analyze on this.
So there is work on this as well.
There is endless work on this area.
We should talk about Snapchat, the Levian, and Thare.
We should, Julian.
Definition, I assume, that we have given the same build environment.
What are the best practices to deliver the same build environment
in long term?
Are there any best practices for that?
Well, just recreating the build environment is different from distribution to distribution,
and it's often a challenge.
Could you repeat it?
Recreating the build environment is often difficult,
and it depends very much on the distribution how to do this.
But it can be done.
So what are the best practices?
What about containerization or something like that,
or VMs or whatever?
VMs help with that, yes,
but it's also you need to record the build environment while you build,
and then have some tools to recreate it.
Okay, so are there any tools right now for kind of defining build environment?
There are several tools, yes.
Any keywords for that?
There's DepriBuild for Debian, there's Reprobild for Arch Linux,
there's, I don't know how OpenWRT does it,
but depending on the distro there's different ones.
Great talk.
I was really fascinated by you describing how we can now potentially
build from source code, bootstrap from, you know, 500 bytes,
and then ancient versions of GCC and upwards.
I think one of the reasons that is fascinating is because it addresses,
Ken Thompson's attacks that he described in On Trusting Trust,
which has been a major weakness in the security of the whole industry.
When can I do this with Debian?
When can I build Debian from source completely like back in the 60s?
There you would need to talk to the bootstrap over people to bootstrap Debian really.
I think you can do it probably today if you do the work.
The sources are there.
Somebody just needs to do it.
And about this trusting trust from, can Richie what you mentioned,
there's now from David Wheeler, there's reverse double compilation,
where you rebuild both compilers, two compilers twice with each other,
and if they produce the same results then you can be more or really sure
that this trusting trust issue is resolved.
There was a nice paper through the last year, October,
for this 30s or 40s anniversary of Trusting Trust.
Any more questions?
It's not really a question, it's more a comment.
For people who come from TPMs and attestation, attestation always works on binaries,
and the question you always have is, what is the source code corresponding to the binary?
And the only process we know forgetting that is actually reproducible builds.
And so there's a lot of people in the security community actually trying to advocate for reproducible builds,
just so we can prove to our customers that this binary hash corresponds to this source code.
And the comment is just that this is actually a very important use case
that is rising enormously in importance with the attestation requirements
of confidential computing and the like, that you can actually use to plead for funding
for guys like the NSA or other people, because this is suddenly becoming really, really important.
I just have a total beginner question.
So I have source code checked out somewhere, and I want to have a reproducible build.
So how do I go there?
I can set source stage epoch, but that doesn't really match because each of those files have a different date.
So is there an easy just to make this way, and then it will analyze the source states,
set the right source epoch and things like that, or how do I get there?
It depends. But first you set source state epoch just to the last modification of the whole source.
So if you have 10 source files, just the latest timestamp.
And then you just build it, and you build it twice, and you compare it.
And with that, if you just build it now twice, you already have some variations,
like randomization, hashes are not sorting the same, but maybe you don't catch the issue with the timestamp.
So you build it once today and once tomorrow.
And then you compare it, either they are the same, or if not, then you compare them with DIFFERSCOPE to see where is the difference.
And according to this, you do whatever is needed to remove the difference.
Okay, then is there an easy tool to give me the right timestamp to set for source stage epoch?
Or when I have a make file, I may be even able to say,
Analyze the date and give me the highest one as source state epoch.
There is not the right timestamp. Often the right timestamp is no timestamp.
And some people just set it to January 1st, 1970, or just drop it.
Because if the timestamp is just there to be a timestamp, if it's really meaningless, you can just drop it.
The other thing is you replace the build timestamp with the timestamp of source state epoch.
Then you still have a timestamp, but what's the timestamp worse?
Just kind of saying that one thing I have done several times in projects is to add,
for the reason of getting the same source table each time,
added a make target or something like that to basically touch all files with a timestamp derived from a file.
And this file will be some sort of manifest.
So you can check that against the files and also use it as a source for all the timestamps.
It's not perfect because sometimes there's timestamps inside files,
and you need to manually add something to edit that, but it's a good starting point to do that.
Thank you for the talk.
What are the main challenges to make the Linux kernel representative?
At the moment, the main challenges are signatures on kernel modules.
Then we came up with the solution that if you rebuild something and you get the same bits,
then you can just reapply the signature again because the signature will match again,
but for that you still need to have the signature.
So it's mostly, it's not impossible, but it's busy work.
And because the signing process is also a secure boot change and there's time requirements
to get the signing in, that is more problematic than the technical challenges.
Okay, and that's time. Thank you very much for the talk.