 W.A. Three simple letters, but what stands behind them is not simple at all. For various reasons, the Corona 1 app has been one of the most talked about digital projects 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 1 app, Thomas Klingweil. And I'm probably not the only one here at IC3, RC3, who's 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 Klingweil. Thomas, the stream is yours. Hello everybody. I'm Thomas Klingweil and today in the session, I would like to talk about the German Corona 1 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 the use 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 there and how we mitigated them, of course. And then I would like to type a little bit into the risk calculation of the app to show you what it actually means if there's a red or a green screen visible to the end user. First of all, we can ask ourselves the question, what is the Corona 1 app actually? So here it is. This is the German Corona 1 app. You can download it from the app stores and once you have onboarded 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 to be permanently active and it has just updated this afternoon, so everything is all right. Let's say you've just been tested at a doctor's, then you could click this button here and you get to this screen. We are able to retrieve your test result digitally. To do this, you can scan a QR code, which is on the form you will see 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 1 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 will 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's the rolling proximity identifier key and the associated encrypted metadata key. This part down here, we can skip for the moment being and look at the generation of the 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 exposure notification 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 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 on the 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 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 a server and I'm drastically simplifying here so they received the other phone. Here they are downloaded all those diagnosis keys are extracted again and as you can see the same functions are applied again HKDF then AES and we get a lot of rolling proximity identifiers from matching here 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 exposure 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 one app it's a dashed line which means there's more documentation available online so I can only invite you to go to the 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 stores 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 collecting, 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 the push message came in remotely but actually it only uses remote local messages but what would the app be without the actual backend infrastructure so you can see here that's the corona one app server that's the actual backend for managing all the keys and you see the upload path here it's aggregated there then provided through the 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 through a so-called teletun which is the most basic way because people call up the hotline get one of those teletun enter it 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 result server up here which can be queried by the verification server so users can get their 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 data flow 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 will be a god which is then fed into the corona one 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 we 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 hashed GUID and the hashed registration token making sure that a 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 start here but the verification server connects to the test result server by using the hashed GUID which can get from the hashed registration token here and then it can ask the test result server and the test result server might have a data set connecting the hashed GUID to a test result and this check needs to be done because the test result server might also have no information for this hashed GUID and this only means that no test result has to be received yet this is what happens here in step eight the lab information system the LIS can supply the test result server with a package of hashed GUID and the test result so it's stored there and if it's available already in a test result server it is returned to the verification server here in step seven and accordingly in step eight to the app you might have noted the test result is also neither cached nor stored here in the verification server which means if the user then decides to upload the keys a ton is required to pass on to the back end for verification of the positive test an equal flow needs to be followed so in step nine again the registration token is passed to the ton end point the verification server once more needs to check with the test result server that it's actually a positive test result gets back here in step 11 the ton is generated in step 12 you can see the ton is not stored in plain text but it's stored as a hash but the plain text is returned to the app which can then bundle it with the diagnosis keys extracted from the explosion notification framework and upload it to the corona one app server or more specifically the submission service but this also needs to verify that it's authentic so it takes it in step 15 to the verification server on the verify endpoint where the ton is validated and validation means it is marked as used already so the same ton cannot be used twice and then the response is given to the back end here which can then if it's positive so which means if it's an authentic ton can store the diagnosis keys 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 okay if someone is requesting something from the registration token endpoint this person has been tested maybe on that specific day then there's the 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 ton endpoint takes place in step nine then we know the person has been tested positive so okay we're using HTTPS so we cannot actually learn which endpoint 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 okay and then of course we've got also the submission service in step 14 where users upload their diagnosis keys and their ton and this is really really without any possibility for discussion because if a app contacts the Corona1 app server and builds up a connection there 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 talks the app talks to the Corona1 app back end it could also be possible to relate those keys to an origin IP address for example or 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 the test results to receive the test result if it's positive to retrieve a ton or to upload their keys so generating noise is the key so what the app actually does is simulate the back end traffic by sending those fake or dummy requests according to a so-called playbook so we've got a 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 a real event or they might be triggered by just some random trigger so scanning a qr code or entering a tailor ton 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 okay there has been a 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 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 term 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 stuff and creating noise so users really uploading their diagnosis keys cannot be picked out from all the noise and to make sure that our backend is 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 the response to a real request also on the data both directions from the client to the server and from the server to the client gets 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 their size does not help in finding out what's actually going on now you could say okay if there's so much additional traffic because there are fake requests being sent out and fake uploads being done and so on this must cost a lot of data traffic to the users and there's the good point it is all zero rated with the german mobile operators which means it's not charged to the end customers but it's just being paid for now there's 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 we've 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 the risk calculation we can have a look at which information is available here so we've got the information about encounters which are 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 identifies belonging to a single diagnosis key so a 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 30 minutes are full and if there's more encounters with the same diagnosis key basically a new window started and so on a single exposure window only contains a single device so it's a 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 a server processed on the back end 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 symptoms 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 on 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 we can say that's the symptom start down here and around that date of symptom begin 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 okay 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 users 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 a increased risk but all the time before here only has a low transmission risk level assigned 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 Apple 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 risk calculation within the app instead of doing it in the framework mainly because we have decided we want a eight level transmission risk level 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 day since onset of symptoms and the report type which is always confirmed test here in Europe so we got those three bits actually which we can now use as transmission risk level which is encoded on the server in those two fields added to the keys on 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 we just dropped 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 65 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 those are 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 weight exposure time what we get here is a normalized exposure time per exposure window and those times for each window are added up for the whole day and then there'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 it's counted or not then at 63 it's this line and at 55 so we see okay 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 it 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 at a low attenuation so at a close proximity so that's 18 minutes and nine minutes those are those three dots here at a medium attenuation so a little bit further 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 a red status already with a single window now in this example we can always see that's pretty far away and there's been one close encounter here transmission risk level eight even pre-filtering has it been at least 10 minutes below 73 decibels? nope okay then we already drop it now there'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 okay so we've got four dots below 73 decibels gives us 12 minutes yes transmission risk level three okay that's easy yes and now we can do the calculation it has been six minutes at the low attenuation those two dots here okay they count full and zero minutes at the medium attenuation you see this part here is empty and the transmission risk level eight gives us a factor of 1.6 if we now multiply those six minutes by 1.6 we get 9.6 minutes so if this has been the only encounter for that day that's still 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 okay so thank you Thomas this was a pre-recorded 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 um maybe to start maybe to start with the first question by Amhar in IRC on security and replay attacks Italy and Netherlands published the TAK SDK so early that they are still valid we learned that yesterday in the time machine presentation how is this handled in the european corporation and can you make them adhere to the security requirements this is the first question for you Thomas okay so thank you for this question the way we handle keys coming in from other european countries that's fully european federation gateway service is that they are handled as if they were national keys which means they are putting some kind of embargo for two hours until so two hours after the end of their validity to make sure that such replay attacks are not possible all right I hope that answers to that actually it's so okay and then that was another one international interoperability is it only or is there also a cooperation between you and for example Switzerland so so far we've got the cooperation with other EU countries that's from the european union which app interoperates already and regarding the integration of non-EU countries that's basically a political decision which has to be made from this place as well then so that's nothing I as an architect can drive or control so so far it's only EU countries all right and then they have some comments and also questions on community interaction and implementation of new features which seems a little slow for them there was for example a proposal for a 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 was there are you aware of this so I've I've personally seen that there are proposals online and that there's 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 I'm the sorry to say that again I'm the architect so I can't decide which feature is going to be implemented it's just as soon as the decision has been made that we need a new feature so we've been 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 all right I mean it's often the case I suppose with great projects I do the projects yeah 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 and the ISC seem to be changing every month so are you aware of this kind of position of community management 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 clarification is needed from an architecture 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 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 yeah that's great to know actually so people have some answers on that maybe one last very concrete question by Duffman and the ISC is the inability of the app to show the time-day of exposure to the 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 yeah okay so the only information the exposure 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 1115 you were meeting with a friend and you get the notification that at 1115 you had that exact encounter it would be easy to tell whom you've met who's been infected and that's something not not desired that you can trace it back to a certain person so we personification would basically then be the thing all right and I hope we have time for this last question to ask an ISC have you considered training a machine learning method to classify the risk levels instead of the used rule-based method so I mean classifying the risk levels through machine learning is something I'm not aware of yet so the thing it's all based on basically a cooperation with the Fraunhofer Institute where they have basically reenacted certain situations that 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 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 for Thomas for giving this talk for being part of this first remote case experience and for giving us some insight into the back end of the corona one app thank you I was happy to do so thank you for having me here