in fakekms/symmetric_rpcs.go [173:281]
func (f *fakeKMS) RawDecrypt(ctx context.Context, req *kmspb.RawDecryptRequest) (*kmspb.RawDecryptResponse, error) {
if err := allowlist("name", "ciphertext", "ciphertext_crc32c", "additional_authenticated_data", "additional_authenticated_data_crc32c", "initialization_vector", "initialization_vector_crc32c").check(req); err != nil {
return nil, err
}
name, err := parseCryptoKeyVersionName(req.Name)
if err != nil {
return nil, err
}
ckv, err := f.cryptoKeyVersion(name)
if err != nil {
return nil, err
}
if ckv.pb.State != kmspb.CryptoKeyVersion_ENABLED {
return nil, errFailedPrecondition("key version %s is not enabled", name)
}
def, _ := algorithmDef(ckv.pb.Algorithm)
if def.Purpose != kmspb.CryptoKey_RAW_ENCRYPT_DECRYPT {
return nil, errFailedPrecondition("keys with algorithm %s may not be used for raw decryption",
nameForValue(kmspb.CryptoKeyVersion_CryptoKeyVersionAlgorithm_name, int32(ckv.pb.Algorithm)))
}
if req.Ciphertext == nil {
return nil, errInvalidArgument("ciphertext is empty")
}
var ciphertext []byte = req.Ciphertext
if len(ciphertext) > maxCiphertextSize {
return nil, errInvalidArgument("len(ciphertext)=%d, want len(ciphertext)<=%d", len(ciphertext), maxCiphertextSize)
}
ciphertextChecksum := crc32c(ciphertext)
if req.CiphertextCrc32C != nil && ciphertextChecksum.Value != req.CiphertextCrc32C.Value {
return nil, errInvalidArgument("invalid ciphertext checksum")
}
if len(req.InitializationVector) > 16 {
return nil, errInvalidArgument("len(initialization_vector)=%d, want len(initialization_vector)<=%d", len(req.InitializationVector), maxIvSize)
}
ivChecksum := crc32c(req.InitializationVector)
if req.InitializationVector != nil && req.InitializationVectorCrc32C != nil && ivChecksum.Value != req.InitializationVectorCrc32C.Value {
return nil, errInvalidArgument("invalid iv checksum")
}
if req.AdditionalAuthenticatedData != nil {
switch ckv.pb.Algorithm {
case kmspb.CryptoKeyVersion_AES_128_GCM, kmspb.CryptoKeyVersion_AES_256_GCM:
break
default:
return nil, errInvalidArgument("cannot specify aad when using %s",
nameForValue(kmspb.CryptoKeyVersion_CryptoKeyVersionAlgorithm_name, int32(ckv.pb.Algorithm)))
}
}
aadChecksum := crc32c(req.AdditionalAuthenticatedData)
if req.AdditionalAuthenticatedData != nil && req.AdditionalAuthenticatedDataCrc32C != nil && aadChecksum.Value != req.AdditionalAuthenticatedDataCrc32C.Value {
return nil, errInvalidArgument("invalid aad checksum")
}
var key []byte
var ok bool
if key, ok = ckv.keyMaterial.([]byte); !ok {
return nil, err
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, errInternal("AES cipher creation failed: %v", err)
}
var plaintext []byte
switch ckv.pb.Algorithm {
case kmspb.CryptoKeyVersion_AES_128_GCM, kmspb.CryptoKeyVersion_AES_256_GCM:
if len(ciphertext) < defaultTagLength {
return nil, errInvalidArgument("len(ciphertext)=%d, want len(ciphertext) > %d", len(ciphertext), defaultTagLength)
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, errInternal("GCM cipher creation failed: %v", err)
}
plaintext, err = aesgcm.Open(nil, req.InitializationVector, ciphertext, req.AdditionalAuthenticatedData)
if err != nil {
return nil, errInternal("decryption failed: %v", err)
}
case kmspb.CryptoKeyVersion_AES_128_CTR, kmspb.CryptoKeyVersion_AES_256_CTR:
plaintext = make([]byte, len(ciphertext))
aesctr := cipher.NewCTR(block, req.InitializationVector)
aesctr.XORKeyStream(plaintext, ciphertext)
case kmspb.CryptoKeyVersion_AES_128_CBC, kmspb.CryptoKeyVersion_AES_256_CBC:
plaintext = make([]byte, len(ciphertext))
aescbc := cipher.NewCBCDecrypter(block, req.InitializationVector)
aescbc.CryptBlocks(plaintext, ciphertext)
default:
return nil, errInternal("unhandled algorithm")
}
return &kmspb.RawDecryptResponse{
Plaintext: plaintext,
PlaintextCrc32C: crc32c(plaintext),
VerifiedCiphertextCrc32C: req.CiphertextCrc32C != nil,
VerifiedAdditionalAuthenticatedDataCrc32C: req.AdditionalAuthenticatedDataCrc32C != nil,
VerifiedInitializationVectorCrc32C: req.InitializationVectorCrc32C != nil,
ProtectionLevel: ckv.pb.ProtectionLevel,
}, nil
}