0

I'd like to develop a simple Android application that authorizes access to a server in the following way:

  • The app stores a local counter t_count of access tokens which initializes at t_count = X;
  • Whenever the user wants to access the server, the app signs a proof that it consumed one token and sends it to the server via a local connection;
  • Once the machine acknowledges the proof, the app securely decrements the token counter;
  • If t_count = 0, the app should prevent the user from sending consumption proofs.

The most important here is that the app can only decrement the counter, and only with an associated a signed proof of consumption. No other modifications should be allowed, even if the user has root access. Ideally, this counter should be stored in a TEE-protected environment.

While doing some research I discovered Android supports a TEE-backed key storage that prevents attackers from extracting private keys. However, it is unclear to me whether I can use this functionality to store an arbitrary counter or, if not, what would be the best way to protect it. I don't know how I can securely update and verify the counter either (or even if this is possible). I don't have any background in Android development.

Thanks in advance.

EDIT: I cannot place the counter in the server because in my use case the user can access many servers which are offline. Hence, the easiest way to keep track of the accesses is to manage the counter inside the user's device (if it can be done securely).

Gabriel Rebello
  • 1,077
  • 1
  • 11
  • 17
  • "Android supports a TEE-backed key storage" -- that depends on device. "whether I can use this functionality to store an arbitrary counter" -- AFAIK, no. The key storage is for keys. – CommonsWare Jun 18 '22 at 19:36
  • Why is the client involved in any way other than taking the request? If you need to do a token count, why isn't it being done on the server? And not allow access unless the server sends back an authorized response? Keeping track of that locally seems like a waste of time, since it needs to confirm with the server anyway – Gabe Sechan Jun 18 '22 at 20:07
  • @GabeSechan The real use case I'm aiming for is a little more complicated than this. I plan to have many servers which are not connected with each other, so I cannot have them maintain a synchronized global token counter per user. But still users can access multiple servers using the same count. Hence, a practical way to do it would be to manage the counter inside the user's device (if it can be done securely). Then a consumption proof is enough for any server to know, without requesting info from other servers, that the user still has tokens to use. I've updated the question to add this. – Gabriel Rebello Jun 18 '22 at 20:35
  • Sure you can. The tokens are held in the db. The db is the source of truth. Now you have multiple servers having a single global counter. How do you think every website that has tokens or credits of some sort does it? – Gabe Sechan Jun 18 '22 at 20:45
  • Maybe I didn't make myself clear. All servers are decentralized and offline, meaning they cannot communicate with each other nor with a global database. Their only connection is a local connection to the user's device. So if I place the counter in the server, I have N (= #servers) segregated counts that cannot be centralized to make a global count. – Gabriel Rebello Jun 18 '22 at 21:16
  • 1
    If the servers are offline, then you can't validate the token either. So your architecture isn't making a lot of sense. Nor does your concern over root access- I'm assuming these are devices you control, and not user owned devices. In the second case, there's no way to prevent the user from cheating. Even secure storage can be cheated by the owner. In the first case, your concern should be securing the device physically and logically, and not worrying about what happen after its owned (which you can't control anyway) – Gabe Sechan Jun 18 '22 at 21:40

1 Answers1

0

What you are trying to do is not possible.

You should never trust a client. From the Server's point of view, it is impossible to tell if it is interacting with software that you developed v.s. software that an attacker developed. Relying on a client to not send "consumption proofs" based purely on a counter that the client has control over is not secure. As an aside, if there exists a way for a client to send "consumption proofs" without actually consuming anything, then it is not a proof of consumption.

If you want to limit accesses to a server, it must be enforced on the server side.