in client/client.go [272:379]
func (c *StetClient) wrapShares(ctx context.Context, unwrappedShares [][]byte, opts sharesOpts) (wrappedShares []*configpb.WrappedShare, keyURIs []string, err error) {
if len(unwrappedShares) != len(opts.kekInfos) {
return nil, nil, fmt.Errorf("number of shares to wrap (%d) does not match number of KEKs (%d)", len(unwrappedShares), len(opts.kekInfos))
}
var kmsClients *cloudkms.ClientFactory
if c.testKMSClients != nil {
kmsClients = c.testKMSClients
} else {
kmsClients = cloudkms.NewClientFactory(c.Version)
}
defer kmsClients.Close()
for i, share := range unwrappedShares {
wrapped := &configpb.WrappedShare{
Hash: shares.HashShare(share),
}
kek := opts.kekInfos[i]
switch x := kek.KekType.(type) {
case *configpb.KekInfo_RsaFingerprint:
key, err := PublicKeyForRSAFingerprint(kek, opts.asymmetricKeys)
if err != nil {
return nil, nil, fmt.Errorf("failed to find public key for RSA fingerprint: %w", err)
}
wrapped.Share, err = rsa.EncryptOAEP(sha256.New(), rand.Reader, key, share, nil)
if err != nil {
return nil, nil, fmt.Errorf("error wrapping key share: %v", err)
}
case *configpb.KekInfo_KekUri:
// Configure CloudKMS Client, with Confidential Space credentials if applicable.
creds := ""
if opts.confSpaceConfig != nil {
creds = opts.confSpaceConfig.FindMatchingCredentials(kek.GetKekUri(), configpb.CredentialMode_ENCRYPT_ONLY_MODE)
}
kmsClient, err := kmsClients.Client(ctx, creds)
if err != nil {
return nil, nil, fmt.Errorf("error initializing Cloud KMS Client with credentials \"%v\": %v", creds, err)
}
cryptoKey, err := getKekCryptoKey(ctx, kmsClient, kek)
if err != nil {
return nil, nil, fmt.Errorf("Error retrieving KEK Metadata: %v", err)
}
var uri string
// Wrap share via KMS.
switch pl := cryptoKey.GetPrimary().ProtectionLevel; pl {
case rpb.ProtectionLevel_SOFTWARE, rpb.ProtectionLevel_HSM:
var err error
wrapOpts := cloudkms.WrapOpts{
Share: share,
KeyName: strings.TrimPrefix(kek.GetKekUri(), gcpKeyPrefix),
}
wrapped.Share, err = cloudkms.WrapShare(ctx, kmsClient, wrapOpts)
if err != nil {
return nil, nil, fmt.Errorf("error wrapping key share: %v", err)
}
uri = kek.GetKekUri()
case rpb.ProtectionLevel_EXTERNAL:
kmd, err := externalKEKMetadata(cryptoKey)
if err != nil {
return nil, nil, fmt.Errorf("error creating KEK Metadata: %v", err)
}
// A nil ekmCertPool indicates the host's Root CAs will be used to connect to the EKM.
ekmWrappedShare, err := c.ekmSecureSessionWrap(ctx, share, *kmd, nil)
if err != nil {
return nil, nil, fmt.Errorf("error wrapping with secure session: %v", err)
}
wrapped.Share = ekmWrappedShare
uri = kmd.uri
case rpb.ProtectionLevel_EXTERNAL_VPC:
kmd, ekmCerts, err := c.getExternalVPCKeyInfo(ctx, cryptoKey, creds)
if err != nil {
return nil, nil, fmt.Errorf("error getting external VPC key info: %v", err)
}
ekmWrappedShare, err := c.ekmSecureSessionWrap(ctx, share, *kmd, ekmCerts)
if err != nil {
return nil, nil, fmt.Errorf("error wrapping with secure session: %v", err)
}
wrapped.Share = ekmWrappedShare
uri = kmd.uri
default:
return nil, nil, fmt.Errorf("unsupported protection level %v", pl)
}
// Return the URI used: the Cloud KMS one in the case of a software
// or HSM key, and the external key URI for an external key.
keyURIs = append(keyURIs, uri)
default:
return nil, nil, fmt.Errorf("unsupported KekInfo type: %v", x)
}
wrappedShares = append(wrappedShares, wrapped)
}
return wrappedShares, keyURIs, nil
}