FiloSottile / FiloSottile/hpke
ciphertext slice is overwritten in single-use HPKE Open
- Dominant language
- Go
- Stars
- 18
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
## tl;dr
Single-use HPKE [Open](https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/hpke.go#L232) accepts `enc` and `ciphertext` in a single argument and then creates [two slices](https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/hpke.go#L237) for each, while both referencing the same underlying array.
An [`append`](https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/kem.go#L386) with `enc` slice in [`dhKEMPrivateKey.decap`](https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/kem.go#L377C10-L377C32) (called by [`hpke.NewRecipient`](https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/hpke.go#L162)) appears to be overwriting the underlying array, thus overwriting the `ciphertext` slice and causing `aead.Open` to fail.
## How to reproduce
See [my code on go playground](https://go.dev/play/p/GBusnBxJUX-):
```go
package main
import (
"crypto/ecdh"
"encoding/hex"
"fmt"
"filippo.io/hpke"
)
func main() {
kem, kdf, aead := hpke.DHKEM(ecdh.X25519()), hpke.HKDFSHA256(), hpke.ChaCha20Poly1305()
k, _ := kem.GenerateKey()
pk := k.PublicKey()
// Single-use Open: ciphersuite overwrite!
encANDcipher, _ := hpke.Seal(pk, kdf, aead, nil, []byte("hello world"))
pt, err := hpke.Open(k, kdf, aead, nil, encANDcipher)
fmt.Printf("Plaintext: '%s' / err: %s\n", pt, err) // Plaintext: '' / err: chacha20poly1305: message authentication failed
// Root cause is passing slices to hpke.NewRecipient
encANDcipher, _ = hpke.Seal(pk, kdf, aead, nil, []byte("hello world"))
copied := make([]byte, len(encANDcipher))
copy(copied, encANDcipher)
hpke.NewRecipient(encANDcipher[:32], k, kdf, aead, nil)
fmt.Printf(
"Ciphersuit:\n├── Before:\t%s\n└── After:\t%s\n",
hex.EncodeToString(encANDcipher[32:]),
hex.EncodeToString(copied[32:]))
}
```
## Code
Single-use HPKE Open splits `ciphtertext` (concatenation of `enc` and `ciphertext`) into two slices on line 237:
https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/hpke.go#L229-L243
and passes `enc` to [`NewRecipient`](https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/hpke.go#L162), where it is passed to `decap`:
https://github.com/FiloSottile/hpke/blob/8aa8a04dacd2fb6d7c40e16c3d57037d4eb5e659/kem.go#L377-L388
on line 386, the `append` modifies the underlying array where `ciphertext` resides, causing the subsequent `aead.Open` to fail.
Contributor guide
Assessment
This issue has not been assessed yet.