*rC3 preroll music*
Herald: All right, CWA - three simple letters, but what stands behind them is
not simple at all. For various reasons. The Corona-Warn-App has been one of the most
talked about digital project of the year. Behind its rather simplistic facade there
are many considerations that went into the App's design to protect its users and
their data, while they might not be visible for most users, these goals had a
direct influence on the software architecture. For instance, the risk
calculation. Here today to talk about some of these backend elements is one of the
solution architects of the Corona-Warn-App - Thomas Klingbeil. And I'm probably not
the only one here at rC3, who is an active user. And I'm pretty curious to hear more
about what's going on behind the scenes of the App. So without further ado, let's
give a warm virtual welcome to Thomas Klingbeil. Thomas, the stream is yours.
Thomas Klingbeil: Hello, everybody. I'm Thomas Klingbeil, and today in the
session, I would like to talk about the German Corona-Warn-App and give you a
little tour behind the scenes of the App development, the underlying technologies
and which things are invisible to the end user, but still very important for the App
itself. First, I would like to give you a short introduction to the App, the
underlying architecture and to used technologies, for example, the Exposure
Notification Framework. Then I would like to have a look on the communication
between the App and the backend and looking at which possible privacy threats
could be found and how we mitigated them, of course. And then I would like to dive a
little bit into the risk calculation of the App to show you what it actually
means, If there is a red or a green screen, visible to the end user. First of
all, we can ask ourselves the question, what is the Corona-Warn-App, actually? So,
here it is. This is the German Corona-Warn-App, you can download it from the App stores and
once you have unboarded onto the App, you will see the following: up here it shows
you that the exposure logging is active, which means this is the currently active
App. Then you have this green card. Green means it's low risk because there have
been no exposures so far. The logging has been permanently active and it has just
updated this afternoon. So everything is all right. Let's say you have just been
tested at a doctor's, then you could click this button here and you get to the
screen, we you're able to retrieve your test result digitally. To do this, you can scan
a QR code, which is on the phone, you received from your doctor, and then you
will get an update as soon as the test result is available. Of course, you can
also get more information about the active exposure logging when you click the button
up here, then you get to this screen and there you can learn more about the
transnational exposure logging, because the German Corona-Warn-App is not alone.
It is connected to other Corona-Apps of other countries within Europe. So users
from other countries can meet and they would be informed mutually about possible
encounters. So just to be sure, I would like to quickly dive into the terminology
of the exposure notification framework. So you know what I'm talking about during
this session. It all starts with a Temporary Exposure Key which is generated
on the phone and which is valid for 24 hours. From this Temporary Exposure Key,
several things are derived. First, for example, there is the Rolling Proximity
Identifier Key and the Associated Encrypted Metadata Key. This part down
here, we can skip for a moment being and look at the generation of Rolling
Proximity Identifiers. Those Rolling Proximity Identifiers are only valid for
10 minutes each because they are regularly exchanged once the Bluetooth MAC-Address
change takes place. So the Rolling Proximity Identifier is basically the
Bluetooth payload your phone uses, when the Exposion Verification Framework is
active and broadcasting. When I say broadcasting, I mean every 250
milliseconds your phone sends out its own Rolling Proximity Identifiers, so other
phones around, which are scanning for signal in the air basically can catch them
and store them locally. So let's look at the receiving side. This is what we see
down here and now, as I've already mentioned, we've got those Bluetooth low
energy beacon mechanics sending out those Rolling Proximity Identifiers and they're
received down here. This is all a very simplified schematic, just to give you an
impression of what's going on there. So now we've got those Rolling Proximity
Identifiers stored under receiving phone and now, somehow, this other phone needs
to find out that there has been a match, this happens by transforming those
Temporary Exposure Keys into Diagnosis Keys, which is just a renaming. But as
soon as someone has tested positive and a Temporary Exposure Key is linked to a
positive diagnosis, it is called Diagnosis Key and they are uploaded to the server.
And I'm drastically simplifying here. So they receive the other phone here they're
downloaded, all those Diagnosis Keys are extracted again. And as you can see, the
same functions applied, again HKDF, then AES, and we get a lot of Rolling Proximity
Identifiers for matching down here. And those are the ones we have stored and now
we can match them and find out which of those Rolling Proximity Identifiers we
have seen so far. And, of course, the receiving phone can also make sure that
the Rolling Proximity Identifiers belonging to a single Diagnosis Key, which
means they belong to one single other phone, are connected to each other. So we
can also track exposures which have lasted longer than 10 minutes. So, for example,
if you are having a meeting of 90 minutes, this would allow the explosion
notification framework to get together those up to nine Rolling Proximity
Identifiers and transform them into a single encounter, which you then get
enriched with those associated encrypted metadata, which is basically just the
transmit power. As a summary, down here. So now that we know which data are being
transferred from phone to phone, we can have a look at the actual architecture of
the App itself. This gray box here is the mobile phone, and down here is the German
Corona-Warn-App, it's a dashed line, which means there's more documentation available
online. So I can only invite you to go to GitHub repository. Have a look at our code
and, of course, our documentation. So there are more diagrams available. And as
you can see, the App itself does not store a lot of data. So those boxes here are
storages. So it only store something called a Registration Token and the
contact journal entries for our most recent version, which means that's all the
App stores itself. What you can see here is that it's connected to the operating
system API/SDK for the exposure notifications, so that's the exposure
notification framework to which we interface, which takes care of all the key
connecting, broadcasting and key matching as well. Then there's a protocol buffer
library which we need for the data transfer, and we use the operating system
cryptography libraries or, basically, the SDK. So we don't need to include external
libraries for that. What you can see here is the OS API/SDK for push messages. But
this is not remote push messaging, but only locally. So the App triggers local
notifications and to the user, it appears as if the notifications to push message
came in remotely, but actually it only uses local messages. But what would the
App be without the actual backend infrastructure? So you can see here,
that's the Corona-Warn-App server, that's the actual backend for managing all the
keys. And you see the upload path here. It's aggregated then provided through
content delivery network and downloaded by the App here. But we've got more. We've
got the verification server, which has the job of verifying a positive test result.
And how does it do that? There's basically two ways it can either get the information
that a positive test is true though a so- called teleTAN, which is the most basic
way, because people call up the hotline, get one of those teleTAN, entered into the
App and then they are able to upload the Diagnosis Keys or, if people use the fully
digital way, they get their test result through the App. And that's why we have
the test results server up here, which can be queried by the verification server
so users can get the test result through the infrastructure. But that's not all,
because as I've promised earlier, we've also got the connection to other European
countries. So down here is the European Federation Gateway Service, which gives us
the possibility to a) upload our own national keys to this European Federation
Gateway Service, so other countries can download them and distribute them to their
users, but we can also request foreign keys and, gets even better, we can be
informed if new foreign keys are available for download through a callback mechanism,
which is just here on the right side. So once the app is communicating with the
backend, what would actually happen if someone is listening? So we've got our
dataflow here. And. Let's have a look at it, so in step one, we are actually
scanning the QR code with a camera of the phone and extracted from the QR code would
be a GUID, which is then fed into the Corona-Warn-App. You can see here it is
never stored within the app. That's very important, because we wanted to make sure
that as few information as possible needs to be stored within the app and also that
it's not possible to connect information from different sources, for example, to
trace back Diagnosis Key to a GUID to allow personification. It was very
important that this step is not possible. So we had to take care that no data is
stored together and data cannot be connected again. So in step one, we get
this GUID. And this is then hashed on the phone being sent to the verification
server, which in step three generates a so-called Registration Token and stores it
together. So it stores the hash(GUID) and the hash(Registration Token), making sure
that GUID can only be used once and returns the unhashed Registration Token to
the App here. Now the App can store the Registration Token and use it in step five
for polling for test results, but the test results are not available directly on the
verification server, because we do not store it here. But the verification server
connects to the test results server by using the hash(GUID), which can get from
the hash(Registration Token) here, and then it can ask the test results server. And
the test results server might have a data set connecting the hash(GUID) to the test
result. And this check needs to be done because the test results server might also
have no information for this hash(GUID), and this only means that no test result
has received yet. This is what happens here in step A, the Lab Information
system, the LIS, can supply the test results server with a package of
hash(GUID) and the test result - so it's stored there. And if it's available already
on a test result server, it is returned to the verification server and here in step 7 and
accordingly in step 8 to the App. You might have noted the test results is also,
neither cached nor stored here on the verification server, which means if the
user then decides to upload the keys, a TAN is required to pass onto the backend
for verification of the positive test. An equal flow needs to be followed. So in
step 9, again, the Registration Token is passed to the TAN endpoint, the
verification server once more needs to check with the test results server
that it's actually a positive test result. Gets back here in step 11, TAN is
generated in step 12. You can see the TAN is not stored in plaintext, but it's
stored as a hash, but the plaintext is returned to the App, which can
then bundle it with Diagnosis Keys extracted from the exposure notification
framework and upload it to the Corona- Warn-App server or more specifically, the
submission service. But this also needs to verify that it's authentic, so takes it in
step 15 to the verification server on the verify endpoint. Where the TAN is
validated and validation means it is marked as used already, so at the same
time cannot be used twice, and then the response is given to the backend here,
which can then, if it's positive, which means if it's authentic TAN can store the
Diagnosis Key in its own storage. And as you can see, only the Diagnosis Keys are
stored here, nothing else. So there's no correlation possible between Diagnosis
Keys, Registration Token or even GUID because it's completely separate. But
still, what could be found out about users if someone were to observe the network
traffic going on there? An important assumption in the beginning, the content
of all the messages is secure because only secure connections are being used and only
the size of the transfer is observable. So we can, from a network sniffing
perspective observe that a connection is created. We can observe how many bytes are
being transferred back and forth, but we cannot learn about the content of the
message. So here we are, we've got the first communication between App and server
in step two, because we can see: OK, if someone is requesting something from the
Registration Token endpoint, this person has been tested maybe on that specific
day. Then there is next communication going on in step five, because this means
that the person has been tested. I mean, we might know that from step two already,
but this person has still not received the test result. So it might still be positive
or negative. If we can observe that the request to the TAN endpoint takes place in
step 9, then we know the person has been tested positive. So OK, this is
https, so we cannot actually learn which end point is being queried, but there
might be specific sizes to those individual requests which might allow us
to learn about the direction the request is going into. Just as a thought. OK, and
then, of course, we've got also the submission service in step 14 where users
upload their Diagnosis Keys and a TAN, and this is really, really without any
possibility for discussion, because if a App-context, the Corona-Warn-App server
and... builds up a connection - this must mean that the user has been tested
positive and is submitting Diagnosis Keys. Apart from that, once the user submits
Diagnosis Keys, and the App talks to the Corona-Warn-App backend - it could also be
possible to relate those keys to an origin IP-address, for example. Could there be a
way around that? So what we need to do in this scenario and what we did is to
establish plausible deniability, which basically means we generate so much noise
with the connections we build up that it's not possible to identify individuals which
actually use those connections to query their test results to receive the test result,
if it's positive, to retrieve a TAN or to upload the Keys. So generating noise is
the key. So what the App actually does is: simulate the backend traffic by sending
those fake or dummy requests according to a so-called playbook. So we've got... we
call it playbook, from which the App takes which requests to do, how long to wait,
how often to repeat those requests and so on. And it's also interesting that those
requests might either be triggered by real event or they might be triggered by just
some random trigger. So scanning a QR code or entering a teleTAN also triggers this
flow. A little bit different, but it still triggers it, because if you then get your
Registration Token retrieve your test results and the retrieval of your test
results stops at some point, this must mean, OK, there has been the test result -
negative or positive. If it's then observable that you communicate to the
submission service - this would mean that it has been positive. So what the App
actually does is: even if it is negative, it continues sending out dummy requests to
the verification server and it might also, so that's all based on random decisions
within the App, it might also then retrieve a fake TAN and it might do a fake
upload of Diagnosis Keys. So in the end, you're not able to distinguish between an App
actually uploading real data or an App just doing playbook's stuff and creating noise.
So users really uploading the Diagnosis Keys cannot be picked out from all the
noise. And to make sure that our backend, it's not just swamped with all those fake
and dummy requests, there's a special header field, which informs the backend to
actually ignore those requests. But if you would just ignore them and not send a
response - it could be implemented on the client, but then it would be observable
again that it's just a fake request. So what we do is - we let the backend skip
all the interaction with the underlying database infrastructure, do not modify any
data and so on, but there will be a delay in the response and the response will look
exactly the same as if it was to respond to real request. Also on the data, both
directions from the client to the server and from the server to the client, get
some padding, so it's always the same size, no matter what information is contained
in this data packages. So observing the data packages... so the size does not help
in finding out what's actually going on. Now, you could say, OK, if there's so much
additional traffic because they're fake requests being sent out and fake uploads
being done and so on, this must cost a lot of data traffic to the users. There's a
good point. It is all zero rated with German mobile operators, which means it's
not charged to the end customers, but it's just being paid for. Now, there is still that
thing with the extraction of information from the metadata while uploading the Diagnosis
Keys and this metadata might be the source IP address, it might be the user agent
being used. So then you can distinguish Android from iOS and possibly you could
also find out about the OS version and to prevent it with introduced an intermediary
server, which removes the metadata from the requests and just forwards the plain
content of the packages basically to the backend service. So the backend service,
the submission service is not able to tell from where this package came from. Now,
for risk calculation, we can have a look at which information is available here. So
we've got the information about encounters, which calculated at the device
receiving the Rolling Proximity Identifiers as mentioned earlier and those
information come into us in 30 minute exposure windows. So I mentioned earlier
that all the Rolling Proximity Identifiers belonging to a single Diagnosis Key. So
single day UTC basically that is, can be related to each other. But what the
exposure notification framework then does is split up those encounters in 30 minute
windows. So the first scan instance, where another device has been identified, starts
the exposure window and then it's filled up until the 30 minutes are full. And if
there's more encounters with the same Diagnosis Key basically, a new window is
started and so on. The single exposure window only contains a single device. So
it's one to one mapping. And within that window we can find the number of the scan
instances. So scans take place every three to five minutes and within those scan
instances, there are also multiple scans.
And we get the minimum and the average attenuation
per instance, and the attenuation is actually the reported transmit power of
the device minus the signal strength when receiving the signal. So it basically
tells us how much signal strength got lost on the way. If we talk about a low
attenuation, this means the other device has been very close. If the attenuation is
higher, it means the other device is farther away and, from the other way around, so
through the Diagnosis Keys, which have been uploaded to the server, processed on the
backend provided on CDN and came to us through that way, we can also get
information about the infectiousness of the user, which is encoded in something we
call Transmission Risk Level, which tells us how big the risk of infection from that
person on that specific day has been. So, the Transmission Risk Level is based on
the symptom status of a person and the symptom status means: Is the person
symptomatic, asymptomatic, does the person want to tell about the symptoms or
maybe do they not want to tell about the symptoms, and in addition to that, if
there have been symptoms, it can also be clarified whether the symptoms start was a
specific day, whether it has been a range of multiple days when the symptoms
started, or people could also say: "I'm not sure about when the symptoms started,
but there have been symptoms definitely". So this is the first case people can
specify when the symptoms started and we can say that the symptoms start down here
and around that date of the onset of symptoms, it's basically evenly spread the
risk of infection: red means high risk, blue means low risk. See, when you move
around that symptom start day also the infectiousness moves around and there's
basically a matrix from where this information is derived. Again, you can
find that all in the code. And there's also the possibility to say, OK, the
symptoms started somewhere within the last seven days. That's the case up here. See,
it's spread a little bit differently. Users could also specify it started
somewhere from one to two weeks ago. You can see that here in the second chart and
the third chart is the case for when the symptoms started more than two weeks ago.
Now, here's the case, that user specify that they just received a positive test
result. So they're definitely Corona positive, but they have never had
symptoms, which might mean they are asymptomatic or presymptomatic. And,
again, you see around the submission, there is an increased risk, but all the
time before here only has a low transmission level asigned. If users want
to specify that they can't remember when the symptoms started, but they definitely
had symptoms, then it's all spread a little bit differently. And equally, if
users do not want to share the information, whether they had symptoms at
all. So now we've got this big risk calculation chart here, and I would like
to walk you quickly through it. So on the left, we've got the configuration which is
being fed into the exposure notification framework by Appe / Google, because
there's also some mappings which the framework needs from us. There is some
internal configuration because we have decided to do a lot of the risk
calculation within the App instead of doing it in the framework, mainly because
we have decided we want a eight levels, transmission risk levels, instead of the
only three levels, so low, standard and high, which Apple and Google provide to
us. For the sake of having those eight levels, we actually sacrifice the
parameters of infectiousness, which is derived from the parameter days since
onset of symptoms and the report type, which is always a confirmed test in Europe.
So we got those three bits actually, which we can now use as a Transmission Risk
Level, which is encoded on the server in those two fields, added to the Keys and
the content delivery network, downloaded by the App and then passed through the
calculation here. So it comes in here. It is assembled from those two parameters,
Report Type and Infectiousness, and now it goes along. So first, we need to look,
whether the sum of the durations at below 73 decibels. So that's our first threshold
has been less than 10 minutes. If it has been less than 10 minutes, just drop the
whole exposure window. If it has been more or equal 10 minutes, we might use it,
depending on whether the Transmission Risk Level is larger or equal three and we use
it. And now we actually calculate the relevant time and times between 60...
between 55 and 63 decibels are only counted half, because that's a medium distance and
times at below 55 decibels, that's up here are counted full, then added up. And
then we've got the weight exposure time and now we've got this transmission risk
level, which leads us to a normalization factor, basically. And this is multiplied
with the rate exposure time. What we get here is the normalized exposure time per
exposure window and those times for each window are added up for the whole day. And
then that's the threshold of 15 minutes, which decides whether the day had a high
risk of infection or a low risk. So now that you all know how to do those
calculations, we can walk through it for three examples. So the first example is
here: it's a transmission risk level of seven. You can see those all are pretty
close so our magic thresholds are here at 73. That's for whether that's counted or
not. Then at 63, it's this line. And at 55. So we see, OK, there's been a lot of
close contact going on and some medium range contact as well. So let's do the
pre-filtering, even though we already see it has been at least 10 minutes below 73
decibels. Yes, definitely, because each of those dots represents three minutes. So,
for this example calculation, I just assumed the scan windows are three minutes
apart. Is it at least transmission risk level three? Yes, it's even seven. So now
we do the calculation. It has been 18 minutes a day low attenuation, so at a
close proximity, so that's 18 minutes and nine minutes those and those - three dots
here at a medium attenuation. So a little bit farther apart, they count as four and
a half minutes. We've got a factor here adding it up, it gets us to 25 minutes
multiplied by 1.4 giving us 33... 31.5 minutes, which means red status. Already
with a single window. Now, in this example, we can always see that's pretty
far away and that's been one close encounter here, transmission risk level
eight even, pre-filtering: has it been at least 10 minutes below 73 decibels? Nope.
OK, then we already drop it. Now that's the third one. Transmission risk level
eight again. It has been a little bit away, but there's also been some close
contact, so we do the pre-filtering: has it been at least 10 minutes below 73? Now
we already have to look closely. So, yes. It is below 73, this one as well. OK, so
we've got four dots below 73 decibels. Gives us 12 minutes. Yes, transmission
risk level three. OK, that's easy. Yes. And now we can do the calculation. It has
been six minutes at the low attenuation - those two dots here. OK, they count full
and zero minutes at the medium attenuation. You see this part is empty
and the transmission risk level eight gives us a factor of 1.6. If we now
multiply the six minutes by 1.6, we get 9.6 minutes. So if this has been the only
encounter for a day, that's stil green. But if, for example, you had two
encounters of this kind, so with the same person or with different people, then it
would already turn into red because then it's close to 20 minutes, which is above
the 15 minute threshold. Now, I would like to thank you for listening to my session,
and I'm available for Q&A shortly.
Herald: OK, so thank you, Tomas. This was a prerecorded talk and the discussion was
very lively in the IRC during the talk, and I'm glad that Thomas will be here for
the Q&A. Maybe to start with the first question by MH in IRC on security and
replay attacks: Italy and Netherlands published TAKs DKs so early today are
still valid. We learned that yesterday and the time between presentation, how is this
handled in the European cooperation and can you make them adhere to the security
requirements? This is the first question for you, Thomas.
Thomas: OK, so thank you for this question. The way we handle Keys coming
in from other European contries, that's through the European federation
gateway service is, that they are handled
as if they were national keys, which means they are put in some kind of
embargo for two hours until... so two hours after the end of their validity to
make sure that replay attacks are not possible.
Herald: All right, I hope that answers this actually. OK, and then there was
another one on international interoperability: is it EU only or is
there is also cooperation between EU and, for example, Switzerland?
Thomas: So so far, we've got the cooperation with other EU countries from *audio glitches*
the European Union, which interoperates already, and regarding the integration of
non-EU countries, that's basically a political decision that has to be made
from this place as well. So that's nothing I as an architect can drive or control. So
so far, it's only EU countries. Herald: All right. And then I have some
comments and also questions on community interaction and implementation of new
features, which seems a little slow for some. There was, for example, a proposal
for functionality called Crowd Notifier for events and restaurants to check in by
scanning a QR code. Can you tell us a bit more about this or what's there? Are you
aware of this? Thomas: So I've personally seen that there
are proposals online, and that is also a lively discussion on those issues, but
what you need to keep in mind is that we are also... we have the task of developing
this App for the federal ministry of Health, and they are basically the ones
requesting features and then there's some scoping going on. So I'm personally and so
to say that again, I am the architect so I can't decide which features are going to
be implemented. It's just as soon as the decision has been made that we need a new
feature, so after we've been given the task, then I come in and prepare the
architecture for that. So I'm not aware of the current state of those developments,
to be honest, because that's out of my personal scope.
Herald: All right. I mean, it's often the case, I suppose, with great projects, with
huge project. But overall, people seem to be liking the fact that everything is
available on GitHub. But some people are really dedicated and seem to be a bit
disappointed that interaction with the community on GitHub seems a bit slow,
because some issues are not answered as people would hope it would be. Do you know
that about some ideas on adding dedicated community managers to the GitHub community
around the App? So the people we speak with, that was one note in IRC, actually
seem to be changing every month. So are you aware of this kind of position of
community management. Thomas: So there's people definitely
working on the community management, there's also a lot of feedback and
comments coming in from the community, and I'm definitely aware that there are people
working on that. And, for example, I get asked by them to jump in on certain
questions where verification was needed from an architectural point of view. And
that's... if you look at GitHub, there's also some issues I've been answering, and
that's because our community team has asked me to jump in there. So but the
feedback that people are not fully satisfied with the way how the community
is handled, is something I would definitely take back to our team
internally and let them know about it. Herald: Yeah, that's great to know,
actually. So people will have some answers on that. Maybe one last very concrete
question by duffman in the IRC: Is the inability of the App to show the time/day
of exposures a limitation of the framework or is it an implementation
choice? And what would be the privacy implications of introducing such a
feature? Actually, a big question, but maybe you can cut it short.
Thomas: Yeah, OK, so the only information, the exposion notification framework by
Google / Apple can give us - is the date of the exposure, and date always relates
to UTC there. And so we never get the time of the actual exposure back. And when
moving to the exposure windows, we also do not get the time back of the exposure
window. And the implications if you were able to tell the exact time of the
encounter, would be that people are often aware where they've been at a certain
time. And let's say at 11:15, you were meeting with a friend and you get a
notification that at 11:15, you had that exact encounter, it would be easy to tell
whom you've met, who's been infected. And that's something not desired, that you can
trace it back to a certain person. So the personification would basically then be
the thing. Herald: All right, and I hope we have time
for this last question asked on IRC: have you considered training a machine
learning method to classified the risk levels instead of the used rule-based
method? Thomas: So, I mean, classifying the risk
levels through machine learning is something I'm not aware of yet. So the
thing is, it's all based on basically a cooperation with the Fraunhofer Institute,
where they have basically reenacted certain situations, did some measurements
and that's what has been transferred into the risk model. So all those thresholds
are derived from, basically, practical tests. So no ML at the moment.
Herald: All right, so I suppose this was our last question and again, Thomas, a
warm round of virtual applause to you and thank you again, Thomas, for giving this
talk, for being part of this first remote case experience and for giving us some
insight into the backend of the Corona- Warn-App. Thank you.
Thomas: Was happy to do so. Thank you for having me here.
*rC3 postroll music*
Subtitles created by c3subtitles.de in the year 2021. Join, and help us!