# KMS v2 crypto changes ### Unchanged ```mermaid stateDiagram-v2 KEK note right of KEK accessed via plugin end note KEK --> DEK: encrypts DEK --> etcd: EDEK stored ``` ### Current KMS v2 ```mermaid stateDiagram-v2 resource %% https://github.com/kubernetes/kubernetes/pull/86124#issuecomment-564596094 note right of resource stored as nonce|encrypted_dek|ciphertext end note etcd_path note left of etcd_path unique per object in etcd /PATH_PREFIX/secrets/NAMESPACE/NAME end note DEK --> aes_gcm counter_nonce_8 --> nonce_12 rand_nonce_4 --> nonce_12 nonce_12 --> aes_gcm etcd_path --> aes_gcm: additional_data aes_gcm --> resource: encrypts ``` ### Proposed KMS v2 The idea is to extend the limited 12 byte AES-GCM nonce with a 32 byte `info` (randomly generated per write) that is fed into HKDF-Expand (the `secret` is the "DEK seed" and the `hash` is SHA-256). We read 32 bytes from HKDF-Expand to use as the AES-GCM DEK. We want the crypto properties of KMS v1 (one DEK per write) without the network overhead. The DEK seed (32 random bytes) is generated on server start up and automatically rotated whenever the remote KEK changes. Note that the HKDF-Extract step is skipped because we already have a good pseudo random key (thus there is no `salt`, only `info`). This allows us to return to a purely per-write random 12 byte nonce for AES-GCM because each generated DEK+nonce combination is unique (the chance of collision is negligible). VM state restores will no longer be an issue. While not strictly necessary, a cache will be used to memoize the HKDF operations as they are fully deterministic based on the inputs. This significantly reduces the overhead of the key generation both in terms of CPU time and memory allocations. Note that the `info` must be stored (in the clear) with the ciphertext, meaning we increase the storage overhead by 32 bytes. ```mermaid stateDiagram-v2 etcd_path note left of etcd_path unique per object in etcd /PATH_PREFIX/secrets/NAMESPACE/NAME end note resource note right of resource stored as info|nonce|encrypted_seed|ciphertext end note DEK_seed --> hkdf_expand: pseudo random key sha256 --> hkdf_expand: hash rand_nonce_32 --> hkdf_expand: info param hkdf_expand --> DEK: generates DEK --> aes_gcm: key rand_nonce_12 --> aes_gcm: nonce etcd_path --> aes_gcm: additional_data aes_gcm --> resource: encrypts ```