1// Copyright 2022 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package hpke 18 19import ( 20 "bytes" 21 "math/rand" 22 "testing" 23 24 "github.com/google/tink/go/subtle/random" 25 "github.com/google/tink/go/subtle" 26 pb "github.com/google/tink/go/proto/hpke_go_proto" 27) 28 29func TestNewEncryptDecryptUnknownKEM(t *testing.T) { 30 params := validParams(t) 31 params.Kem = pb.HpkeKem_KEM_UNKNOWN 32 pubKey, privKey := pubPrivKeys(t, params) 33 34 if _, err := NewEncrypt(pubKey); err == nil { 35 t.Error("NewEncrypt(unknown KEM): got success, want err") 36 } 37 if _, err := NewDecrypt(privKey); err == nil { 38 t.Error("NewDecrypt(unknown KEM): got success, want err") 39 } 40} 41 42func TestNewEncryptDecryptUnknownKDF(t *testing.T) { 43 params := validParams(t) 44 params.Kdf = pb.HpkeKdf_KDF_UNKNOWN 45 pubKey, privKey := pubPrivKeys(t, params) 46 47 if _, err := NewEncrypt(pubKey); err == nil { 48 t.Error("NewEncrypt(unknown KDF): got success, want err") 49 } 50 if _, err := NewDecrypt(privKey); err == nil { 51 t.Error("NewDecrypt(unknown KDF): got success, want err") 52 } 53} 54 55func TestNewEncryptDecryptUnknownAEAD(t *testing.T) { 56 params := validParams(t) 57 params.Aead = pb.HpkeAead_AEAD_UNKNOWN 58 pubKey, privKey := pubPrivKeys(t, params) 59 60 if _, err := NewEncrypt(pubKey); err == nil { 61 t.Error("NewEncrypt(unknown AEAD): got success, want err") 62 } 63 if _, err := NewDecrypt(privKey); err == nil { 64 t.Error("NewDecrypt(unknown AEAD): got success, want err") 65 } 66} 67 68func TestNewEncryptDecryptMissingParams(t *testing.T) { 69 pubKey, privKey := pubPrivKeys(t, nil) 70 71 if _, err := NewEncrypt(pubKey); err == nil { 72 t.Error("NewEncrypt(missing params): got success, want err") 73 } 74 if _, err := NewDecrypt(privKey); err == nil { 75 t.Error("NewDecrypt(missing params): got success, want err") 76 } 77} 78 79func TestNewEncryptMissingPubKeyBytes(t *testing.T) { 80 pubKey, _ := pubPrivKeys(t, validParams(t)) 81 pubKey.PublicKey = nil 82 if _, err := NewEncrypt(pubKey); err == nil { 83 t.Error("NewEncrypt(nil pub key): got success, want err") 84 } 85 pubKey.PublicKey = []byte{} 86 if _, err := NewEncrypt(pubKey); err == nil { 87 t.Error("NewEncrypt(zero-length pub key): got success, want err") 88 } 89} 90 91func TestNewDecryptMissingPrivKeyBytes(t *testing.T) { 92 _, privKey := pubPrivKeys(t, validParams(t)) 93 privKey.PrivateKey = nil 94 if _, err := NewDecrypt(privKey); err == nil { 95 t.Error("NewDecrypt(nil priv key): got success, want err") 96 } 97 privKey.PrivateKey = []byte{} 98 if _, err := NewDecrypt(privKey); err == nil { 99 t.Error("NewDecrypt(zero-length priv key): got success, want err") 100 } 101} 102 103func TestEncryptDecrypt(t *testing.T) { 104 aeadIDs := []pb.HpkeAead{pb.HpkeAead_AES_128_GCM, pb.HpkeAead_AES_256_GCM, pb.HpkeAead_CHACHA20_POLY1305} 105 for _, aeadID := range aeadIDs { 106 params := &pb.HpkeParams{ 107 Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, 108 Kdf: pb.HpkeKdf_HKDF_SHA256, 109 Aead: aeadID, 110 } 111 pubKey, privKey := pubPrivKeys(t, params) 112 113 enc, err := NewEncrypt(pubKey) 114 if err != nil { 115 t.Fatalf("NewEncrypt: err %q", err) 116 } 117 dec, err := NewDecrypt(privKey) 118 if err != nil { 119 t.Fatalf("NewDecrypt: err %q", err) 120 } 121 122 wantPT := random.GetRandomBytes(200) 123 ctxInfo := random.GetRandomBytes(100) 124 ct, err := enc.Encrypt(wantPT, ctxInfo) 125 if err != nil { 126 t.Fatalf("Encrypt: err %q", err) 127 } 128 gotPT, err := dec.Decrypt(ct, ctxInfo) 129 if err != nil { 130 t.Fatalf("Decrypt: err %q", err) 131 } 132 if !bytes.Equal(gotPT, wantPT) { 133 t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) 134 } 135 } 136} 137 138func TestDecryptModifiedCiphertextOrContextInfo(t *testing.T) { 139 pubKey, privKey := pubPrivKeys(t, validParams(t)) 140 enc, err := NewEncrypt(pubKey) 141 if err != nil { 142 t.Fatalf("NewEncrypt: err %q", err) 143 } 144 dec, err := NewDecrypt(privKey) 145 if err != nil { 146 t.Fatalf("NewDecrypt: err %q", err) 147 } 148 149 wantPT := random.GetRandomBytes(200) 150 ctxInfo := random.GetRandomBytes(100) 151 ct, err := enc.Encrypt(wantPT, ctxInfo) 152 if err != nil { 153 t.Fatalf("Encrypt: err %q", err) 154 } 155 gotPT, err := dec.Decrypt(ct, ctxInfo) 156 if err != nil { 157 t.Fatalf("Decrypt: err %q", err) 158 } 159 if !bytes.Equal(gotPT, wantPT) { 160 t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) 161 } 162 163 tests := []struct { 164 name string 165 ct []byte 166 ctxInfo []byte 167 }{ 168 {"extended ct", append(ct, []byte("hi there")...), ctxInfo}, 169 {"flip byte ct", flipRandByte(t, ct), ctxInfo}, 170 {"short ct", ct[:len(ct)-5], ctxInfo}, 171 {"empty ct", []byte{}, ctxInfo}, 172 {"extended ctxInfo", ct, append(ctxInfo, []byte("hi there")...)}, 173 {"flip byte ctxInfo", ct, flipRandByte(t, ctxInfo)}, 174 {"short ctxInfo", ct, ctxInfo[:len(ctxInfo)-5]}, 175 {"empty ctxInfo", ct, []byte{}}, 176 } 177 178 for _, test := range tests { 179 t.Run(test.name, func(t *testing.T) { 180 if _, err := dec.Decrypt(test.ct, test.ctxInfo); err == nil { 181 t.Error("Decrypt: got success, want err") 182 } 183 }) 184 } 185} 186 187func TestEncryptDecryptEmptyContextInfo(t *testing.T) { 188 pubKey, privKey := pubPrivKeys(t, validParams(t)) 189 enc, err := NewEncrypt(pubKey) 190 if err != nil { 191 t.Fatalf("NewEncrypt: err %q", err) 192 } 193 dec, err := NewDecrypt(privKey) 194 if err != nil { 195 t.Fatalf("NewDecrypt: err %q", err) 196 } 197 198 wantPT := random.GetRandomBytes(200) 199 ctxInfo := []byte{} 200 ct, err := enc.Encrypt(wantPT, ctxInfo) 201 if err != nil { 202 t.Fatalf("Encrypt: err %q", err) 203 } 204 gotPT, err := dec.Decrypt(ct, ctxInfo) 205 if err != nil { 206 t.Fatalf("Decrypt: err %q", err) 207 } 208 if !bytes.Equal(gotPT, wantPT) { 209 t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) 210 } 211} 212 213// TestDecryptEncapsulatedKeyWithFlippedMSB checks that ciphertexts with its 214// encapsulated key MSB flipped fails to decrypt. See details at b/213886185. 215func TestDecryptEncapsulatedKeyWithFlippedMSB(t *testing.T) { 216 pubKey, privKey := pubPrivKeys(t, validParams(t)) 217 enc, err := NewEncrypt(pubKey) 218 if err != nil { 219 t.Fatalf("NewEncrypt: err %q", err) 220 } 221 dec, err := NewDecrypt(privKey) 222 if err != nil { 223 t.Fatalf("NewDecrypt: err %q", err) 224 } 225 226 wantPT := random.GetRandomBytes(200) 227 ctxInfo := random.GetRandomBytes(100) 228 ct, err := enc.Encrypt(wantPT, ctxInfo) 229 if err != nil { 230 t.Fatalf("Encrypt: err %q", err) 231 } 232 gotPT, err := dec.Decrypt(ct, ctxInfo) 233 if err != nil { 234 t.Fatalf("Decrypt: err %q", err) 235 } 236 if !bytes.Equal(gotPT, wantPT) { 237 t.Errorf("Decrypt: got %q, want %q", gotPT, wantPT) 238 } 239 240 // Flip the MSB of the encapsulated key, which is the first 32 bytes of ct. 241 ct[31] = ct[31] ^ 128 242 if _, err := dec.Decrypt(ct, ctxInfo); err == nil { 243 t.Error("Decrypt with encapsulated key MSB flipped: got success, want err") 244 } 245} 246 247func validParams(t *testing.T) *pb.HpkeParams { 248 t.Helper() 249 return &pb.HpkeParams{ 250 Kem: pb.HpkeKem_DHKEM_X25519_HKDF_SHA256, 251 Kdf: pb.HpkeKdf_HKDF_SHA256, 252 Aead: pb.HpkeAead_AES_256_GCM, 253 } 254} 255 256func pubPrivKeys(t *testing.T, params *pb.HpkeParams) (*pb.HpkePublicKey, *pb.HpkePrivateKey) { 257 t.Helper() 258 259 priv, err := subtle.GeneratePrivateKeyX25519() 260 if err != nil { 261 t.Fatalf("GeneratePrivateKeyX25519: err %q", err) 262 } 263 pub, err := subtle.PublicFromPrivateX25519(priv) 264 if err != nil { 265 t.Fatalf("PublicFromPrivateX25519: err %q", err) 266 } 267 268 pubKey := &pb.HpkePublicKey{ 269 Version: 0, 270 Params: params, 271 PublicKey: pub, 272 } 273 privKey := &pb.HpkePrivateKey{ 274 Version: 0, 275 PublicKey: pubKey, 276 PrivateKey: priv, 277 } 278 return pubKey, privKey 279} 280 281func flipRandByte(t *testing.T, b []byte) []byte { 282 t.Helper() 283 ret := make([]byte, len(b)) 284 copy(ret, b) 285 randByte := rand.Intn(len(b)) 286 ret[randByte] = ret[randByte] ^ 255 287 return ret 288} 289