Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): KID in NanoTDF Policy #1197

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type PolicyObject struct {
Body struct {
DataAttributes []attributeObject `json:"dataAttributes"`
Dissem []string `json:"dissem"`
KeyIdentifier string `json:"kid"`
} `json:"body"`
}

Expand Down
22 changes: 11 additions & 11 deletions sdk/nanotdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32,
}
totalBytes += uint32(l)

policyObj, err := createPolicyObject(config.attributes)
policyObj, err := createPolicyObjectKid(config.attributes, config.kasPublicKeyID)
if err != nil {
return nil, 0, fmt.Errorf("fail to create policy object:%w", err)
}
Expand Down Expand Up @@ -674,13 +674,13 @@ func (s SDK) CreateNanoTDF(writer io.Writer, reader io.Reader, config NanoTDFCon
return 0, fmt.Errorf("config.kasURL failed:%w", err)
}

kasPublicKey, err := getECPublicKey(kasURL, s.dialOptions...)
kasPublicKey, kid, err := getECPublicKeyKid(kasURL, s.dialOptions...)
if err != nil {
return 0, fmt.Errorf("getECPublicKey failed:%w", err)
}

slog.Debug("CreateNanoTDF", slog.String("header size", kasPublicKey))

slog.Debug("CreateNanoTDF", slog.String("kasPublicKey", kasPublicKey), slog.String("kid", kid))
// add kid to config.policy
config.kasPublicKeyID = kid
config.kasPublicKey, err = ocrypto.ECPubKeyFromPem([]byte(kasPublicKey))
if err != nil {
return 0, fmt.Errorf("ocrypto.ECPubKeyFromPem failed: %w", err)
Expand Down Expand Up @@ -845,17 +845,17 @@ func (s SDK) ReadNanoTDFContext(ctx context.Context, writer io.Writer, reader io
return uint32(writeLen), nil
}

// getECPublicKey - Contact the specified KAS and get its public key
func getECPublicKey(kasURL string, opts ...grpc.DialOption) (string, error) {
// getECPublicKeyKid - Contact the specified KAS and get its public key
func getECPublicKeyKid(kasURL string, opts ...grpc.DialOption) (string, string, error) {
req := kas.PublicKeyRequest{}
req.Algorithm = "ec:secp256r1"
grpcAddress, err := getGRPCAddress(kasURL)
if err != nil {
return "", err
return "", "", err
}
conn, err := grpc.Dial(grpcAddress, opts...)
if err != nil {
return "", fmt.Errorf("error connecting to grpc service at %s: %w", kasURL, err)
return "", "", fmt.Errorf("error connecting to grpc service at %s: %w", kasURL, err)
}
defer conn.Close()

Expand All @@ -865,10 +865,10 @@ func getECPublicKey(kasURL string, opts ...grpc.DialOption) (string, error) {
resp, err := serviceClient.PublicKey(ctx, &req)

if err != nil {
return "", fmt.Errorf("error making request to KAS: %w", err)
return "", "", fmt.Errorf("error making request to KAS: %w", err)
}

return resp.GetPublicKey(), nil
return resp.GetPublicKey(), resp.GetKid(), nil
}

type requestBody struct {
Expand Down
17 changes: 9 additions & 8 deletions sdk/nanotdf_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import (
// ============================================================================================================

type NanoTDFConfig struct {
keyPair ocrypto.ECKeyPair
kasPublicKey *ecdh.PublicKey
attributes []autoconfigure.AttributeValueFQN
cipher CipherMode
kasURL ResourceLocator
sigCfg signatureConfig
policy policyInfo
bindCfg bindingConfig
keyPair ocrypto.ECKeyPair
kasPublicKey *ecdh.PublicKey
kasPublicKeyID string
attributes []autoconfigure.AttributeValueFQN
cipher CipherMode
kasURL ResourceLocator
sigCfg signatureConfig
policy policyInfo
bindCfg bindingConfig
}

type NanoTDFOption func(*NanoTDFConfig) error
Expand Down
11 changes: 9 additions & 2 deletions sdk/tdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,11 @@ func (s SDK) prepareManifest(ctx context.Context, t *TDFObject, tdfConfig TDFCon

// create policy object
func createPolicyObject(attributes []autoconfigure.AttributeValueFQN) (PolicyObject, error) {
return createPolicyObjectKid(attributes, "")
}

// create policy object with kid
func createPolicyObjectKid(attributes []autoconfigure.AttributeValueFQN, kid string) (PolicyObject, error) {
uuidObj, err := uuid.NewUUID()
if err != nil {
return PolicyObject{}, fmt.Errorf("uuid.NewUUID failed: %w", err)
Expand All @@ -452,9 +457,11 @@ func createPolicyObject(attributes []autoconfigure.AttributeValueFQN) (PolicyObj
attributeObj := attributeObject{}
attributeObj.Attribute = attribute.String()
policyObj.Body.DataAttributes = append(policyObj.Body.DataAttributes, attributeObj)
policyObj.Body.Dissem = make([]string, 0)
}

policyObj.Body.Dissem = make([]string, 0)
if kid != "" {
policyObj.Body.KeyIdentifier = kid
}
return policyObj, nil
}

Expand Down
1 change: 1 addition & 0 deletions service/kas/access/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Policy struct {
type PolicyBody struct {
DataAttributes []Attribute `json:"dataAttributes"`
Dissem []string `json:"dissem"`
KeyIdentifier string `json:"kid"`
}

// Audit helper methods
Expand Down
14 changes: 6 additions & 8 deletions service/kas/access/rewrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,13 +369,6 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, body *RequestBody, entity *en
}

func (p *Provider) nanoTDFRewrap(ctx context.Context, body *RequestBody, entity *entityInfo) (*kaspb.RewrapResponse, error) {
// TODO Lookup KID from request content
// Should this be in the locator or somewhere else?
kid, err := p.lookupKid(ctx, security.AlgorithmECP256R1)
if err != nil {
p.Logger.WarnContext(ctx, "failure to find default kid for ec", "err", err)
return nil, err400("bad request")
}
headerReader := bytes.NewReader(body.KeyAccess.Header)

header, _, err := sdk.NewNanoTDFHeaderFromReader(headerReader)
Expand All @@ -388,16 +381,21 @@ func (p *Provider) nanoTDFRewrap(ctx context.Context, body *RequestBody, entity
return nil, fmt.Errorf("ECCurve failed: %w", err)
}

// FIXME add support for Embedded Policy (Encrypted w/Policy Key Access)
// https://github.com/opentdf/spec/blob/main/schema/nanotdf/README.md#342323-optional-policy-key-access
kid := "e0"
symmetricKey, err := p.CryptoProvider.GenerateNanoTDFSymmetricKey(kid, header.EphemeralKey, ecCurve)
if err != nil {
return nil, fmt.Errorf("failed to generate symmetric key: %w", err)
}

// extract the policy
// extract the Encrypted policy
policy, err := extractNanoPolicy(symmetricKey, header)
if err != nil {
return nil, fmt.Errorf("Error extracting policy: %w", err)
}
// TODO Lookup KID from policy
// policy.Body.KeyIdentifier

// check the policy binding
verify, err := header.VerifyPolicyBinding()
Expand Down
Loading