func()

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
}