diff --git a/docs/fido2-impl.md b/docs/fido2-impl.md deleted file mode 100644 index a5c8ba4..0000000 --- a/docs/fido2-impl.md +++ /dev/null @@ -1,86 +0,0 @@ -This page aims to document the security related aspects of the FIDO2 -implementation on Solo. This is to make it easier for public review and -comments. - -# Key generation - -Solo aims to achieve 256 bit (32 byte) security with its FIDO2 implementation, -even in light of physical side channels. - -When Solo is first programmed, it will be "uninitialized," meaning it won't -have any secret material, until the first time it boots, then it will leverage -the TRNG to generate all necessary material. This only happens once. - -A master secret, `M`, is generated at initialization. This is only used for -all key generation and derivation in FIDO2. Solo uses a key wrapping method -for FIDO2 operation. - -** NOTE: The masked implementation of AES is planned, but not yet implemented. Currently it is normal AES. ** - -## Key wrapping - -When you register a service with a FIDO2 or U2F authenticator, the -authenticator must generate a new keypair unique to that service. This keypair -could be stored on the authenticator to be used in subsequent authentications, -but now a certain amount of memory needs to be allocated for this. On embedded -devices, there isn't much memory to spare and users will allows frustratingly -hit the limit of this memory. - -The answer to this problem is to do key wrapping. The authenticator just -stores `M` and uses `M` and the TRNG to generate new keys and derive previous -keys on the fly. A random number, `R`, is generated, and is placed in the -FIDO2/U2F `KEYID` parameter. The service stores `KEYID` after registering a -key and will issue it back to the authenticator for subsequent authentications. - -In essence, the following happens at registration. - -1. Generate `R`, calculate private key, `K`, using `HMAC(M,R)` -2. Derive public key, `P`, from `K` -3. Return `P` and `R` to service. (`R` is in `KEYID` parameter) -4. Service stores `P` and `R`. - -Now on authenication. - -1. Service issues authentication request with `R` in `KEYID` parameter. -2. \* Authenticator generates `K` by calculating `HMAC(M,R)`. -3. Proceed normally as if `K` was loaded from storage memory. - - - - -## Key derivation - -** Planned, but not yet implemented. ** - -Master secret `M` consists of 64 bytes, split into equal parts `M1` and `M2`. -In theory, we should only need 32 bytes to achieve 256 security, but we also -plan to have side channel security hence the added bytes. - -Our HMAC currently is a two step process. First, just generate a normal -`SHA256-HMAC`. - -1. `tmp = SHA256_HMAC(M1, R)` - -We could proceed using `tmp` as our secret key, `K`. But our `SHA256-HMAC` -implementation isn't side channel resistant and we won't bother trying to add -side channel resistance. So we add an additional stage that is side channel -resistant. - -2. `K = aes256_masked(M2, tmp)` - -We add a masked AES encryption to provide side channel resistance. Masked AES -is well studied and relatively easy to implement. An adversary may be able to -recover `M1` via SCA but not `M2`. - - - -* There are other details I leave out. There's also an authentication tag -in the `KEYID` parameter to ensure this is a key generated by the Solo -key. diff --git a/docs/solo/fido2-impl.md b/docs/solo/fido2-impl.md index 2bd5866..a5c8ba4 100644 --- a/docs/solo/fido2-impl.md +++ b/docs/solo/fido2-impl.md @@ -57,6 +57,8 @@ keys which are then used for FIDO2/U2F. --> ## Key derivation +** Planned, but not yet implemented. ** + Master secret `M` consists of 64 bytes, split into equal parts `M1` and `M2`. In theory, we should only need 32 bytes to achieve 256 security, but we also plan to have side channel security hence the added bytes.