diff --git a/examples/cmd/benchmark.go b/examples/cmd/benchmark.go index 4a39e339c0..96904d9da2 100644 --- a/examples/cmd/benchmark.go +++ b/examples/cmd/benchmark.go @@ -21,6 +21,13 @@ const ( NanoTDF TDFFormat = "nanotdf" ) +func gfmCellEscape(s string) string { + // Escape pipe characters for GitHub Flavored Markdown tables + pipes := strings.ReplaceAll(s, "|", "\\|") + brs := strings.ReplaceAll(pipes, "\n", "
") + return brs +} + func (f *TDFFormat) String() string { return string(*f) } @@ -232,7 +239,7 @@ func runBenchmark(cmd *cobra.Command, args []string) error { fmt.Printf("| Error Message | Occurrences |\n") fmt.Printf("|-----------------------|---------------------------|\n") for errMsg, count := range errorMsgs { - fmt.Printf("| %s | %d occurrences |\n", errMsg, count) + fmt.Printf("| %s | %d occurrences |\n", gfmCellEscape(errMsg), count) } } return nil diff --git a/sdk/kas_client.go b/sdk/kas_client.go index 090ad0eea7..ae6dcde964 100644 --- a/sdk/kas_client.go +++ b/sdk/kas_client.go @@ -21,6 +21,7 @@ import ( const ( secondsPerMinute = 60 + statusFail = "fail" statusPermit = "permit" ) @@ -74,7 +75,7 @@ func (k *KASClient) makeRewrapRequest(ctx context.Context, requests []*kas.Unsig response, err := serviceClient.Rewrap(ctx, rewrapRequest) if err != nil { - return nil, fmt.Errorf("error making rewrap request: %w", err) + return upgradeRewrapErrorV1(err, requests) } upgradeRewrapResponseV1(response, requests) @@ -109,6 +110,30 @@ func upgradeRewrapResponseV1(response *kas.RewrapResponse, requests []*kas.Unsig } } +// convert v1 errors to v2 responses +func upgradeRewrapErrorV1(err error, requests []*kas.UnsignedRewrapRequest_WithPolicyRequest) (*kas.RewrapResponse, error) { + if len(requests) != 1 { + return nil, fmt.Errorf("error making rewrap request: %w", err) + } + + return &kas.RewrapResponse{ + Responses: []*kas.PolicyRewrapResult{ + { + PolicyId: requests[0].GetPolicy().GetId(), + Results: []*kas.KeyAccessRewrapResult{ + { + KeyAccessObjectId: requests[0].GetKeyAccessObjects()[0].GetKeyAccessObjectId(), + Status: statusFail, + Result: &kas.KeyAccessRewrapResult_Error{ + Error: err.Error(), + }, + }, + }, + }, + }, + }, nil +} + func (k *KASClient) nanoUnwrap(ctx context.Context, requests ...*kas.UnsignedRewrapRequest_WithPolicyRequest) (map[string][]kaoResult, error) { keypair, err := ocrypto.NewECKeyPair(ocrypto.ECCModeSecp256r1) if err != nil { @@ -129,19 +154,39 @@ func (k *KASClient) nanoUnwrap(ctx context.Context, requests ...*kas.UnsignedRew return nil, err } - sessionKey, err := ocrypto.ComputeECDHKey([]byte(privateKeyAsPem), []byte(response.GetSessionPublicKey())) + // If the session key is empty, all responses are errors + spk := response.GetSessionPublicKey() + if spk == "" { + policyResults := make(map[string][]kaoResult) + err = errors.New("nanoUnwrap: session public key is empty") + for _, results := range response.GetResponses() { + var kaoKeys []kaoResult + for _, kao := range results.GetResults() { + if kao.GetStatus() == statusPermit { + kaoKeys = append(kaoKeys, kaoResult{KeyAccessObjectID: kao.GetKeyAccessObjectId(), Error: err}) + } else { + kaoKeys = append(kaoKeys, kaoResult{KeyAccessObjectID: kao.GetKeyAccessObjectId(), Error: errors.New(kao.GetError())}) + } + } + policyResults[results.GetPolicyId()] = kaoKeys + } + + return policyResults, nil + } + + sessionKey, err := ocrypto.ComputeECDHKey([]byte(privateKeyAsPem), []byte(spk)) if err != nil { - return nil, fmt.Errorf("ocrypto.ComputeECDHKey failed :%w", err) + return nil, fmt.Errorf("nanoUnwrap: ocrypto.ComputeECDHKey failed :%w", err) } sessionKey, err = ocrypto.CalculateHKDF(versionSalt(), sessionKey) if err != nil { - return nil, fmt.Errorf("ocrypto.CalculateHKDF failed:%w", err) + return nil, fmt.Errorf("nanoUnwrap: ocrypto.CalculateHKDF failed:%w", err) } aesGcm, err := ocrypto.NewAESGcm(sessionKey) if err != nil { - return nil, fmt.Errorf("ocrypto.NewAESGcm failed:%w", err) + return nil, fmt.Errorf("nanoUnwrap: ocrypto.NewAESGcm failed:%w", err) } policyResults := make(map[string][]kaoResult) diff --git a/sdk/nanotdf.go b/sdk/nanotdf.go index 94cbbe14d6..b15442e708 100644 --- a/sdk/nanotdf.go +++ b/sdk/nanotdf.go @@ -1061,7 +1061,7 @@ func (s SDK) ReadNanoTDFContext(ctx context.Context, writer io.Writer, reader io symmetricKey, err := s.getNanoRewrapKey(ctx, handler) if err != nil { - return 0, err + return 0, fmt.Errorf("getNanoRewrapKey: %w", err) } return handler.Decrypt(ctx, []kaoResult{{SymmetricKey: symmetricKey}}) } @@ -1069,7 +1069,7 @@ func (s SDK) ReadNanoTDFContext(ctx context.Context, writer io.Writer, reader io func (s SDK) getNanoRewrapKey(ctx context.Context, decryptor *NanoTDFDecryptHandler) ([]byte, error) { req, err := decryptor.CreateRewrapRequest(ctx) if err != nil { - return nil, err + return nil, fmt.Errorf("CreateRewrapRequest: %w", err) } if s.collectionStore != nil { @@ -1081,7 +1081,7 @@ func (s SDK) getNanoRewrapKey(ctx context.Context, decryptor *NanoTDFDecryptHand client := newKASClient(s.dialOptions, s.tokenSource, nil) kasURL, err := decryptor.header.kasURL.GetURL() if err != nil { - return nil, err + return nil, fmt.Errorf("nano header kasUrl: %w", err) } policyResult, err := client.nanoUnwrap(ctx, req[kasURL]) @@ -1093,7 +1093,7 @@ func (s SDK) getNanoRewrapKey(ctx context.Context, decryptor *NanoTDFDecryptHand return nil, errors.New("policy was not found in rewrap response") } if result[0].Error != nil { - return nil, result[0].Error + return nil, fmt.Errorf("rewrapError: %w", result[0].Error) } if s.collectionStore != nil { diff --git a/sdk/tdf.go b/sdk/tdf.go index 664d1740a1..8aa8e8cbe0 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -585,33 +585,33 @@ func generateWrapKeyWithEC(mode ocrypto.ECCMode, kasPublicKey string, symKey []b emphermalPublicKey, err := ecKeyPair.PublicKeyInPemFormat() if err != nil { - return ecKeyWrappedKeyInfo{}, fmt.Errorf("failed to get EC public key: %w", err) + return ecKeyWrappedKeyInfo{}, fmt.Errorf("generateWrapKeyWithEC: failed to get EC public key: %w", err) } emphermalPrivateKey, err := ecKeyPair.PrivateKeyInPemFormat() if err != nil { - return ecKeyWrappedKeyInfo{}, fmt.Errorf("failed to get EC private key: %w", err) + return ecKeyWrappedKeyInfo{}, fmt.Errorf("generateWrapKeyWithEC: failed to get EC private key: %w", err) } ecdhKey, err := ocrypto.ComputeECDHKey([]byte(emphermalPrivateKey), []byte(kasPublicKey)) if err != nil { - return ecKeyWrappedKeyInfo{}, fmt.Errorf("ocrypto.ComputeECDHKey failed:%w", err) + return ecKeyWrappedKeyInfo{}, fmt.Errorf("generateWrapKeyWithEC: ocrypto.ComputeECDHKey failed:%w", err) } salt := tdfSalt() sessionKey, err := ocrypto.CalculateHKDF(salt, ecdhKey) if err != nil { - return ecKeyWrappedKeyInfo{}, fmt.Errorf("ocrypto.CalculateHKDF failed:%w", err) + return ecKeyWrappedKeyInfo{}, fmt.Errorf("generateWrapKeyWithEC: ocrypto.CalculateHKDF failed:%w", err) } gcm, err := ocrypto.NewAESGcm(sessionKey) if err != nil { - return ecKeyWrappedKeyInfo{}, fmt.Errorf("ocrypto.NewAESGcm failed:%w", err) + return ecKeyWrappedKeyInfo{}, fmt.Errorf("generateWrapKeyWithEC: ocrypto.NewAESGcm failed:%w", err) } wrappedKey, err := gcm.Encrypt(symKey) if err != nil { - return ecKeyWrappedKeyInfo{}, fmt.Errorf("ocrypto.AESGcm.Encrypt failed:%w", err) + return ecKeyWrappedKeyInfo{}, fmt.Errorf("generateWrapKeyWithEC: ocrypto.AESGcm.Encrypt failed:%w", err) } return ecKeyWrappedKeyInfo{ @@ -623,12 +623,12 @@ func generateWrapKeyWithEC(mode ocrypto.ECCMode, kasPublicKey string, symKey []b func generateWrapKeyWithRSA(publicKey string, symKey []byte) (string, error) { asymEncrypt, err := ocrypto.NewAsymEncryption(publicKey) if err != nil { - return "", fmt.Errorf("ocrypto.NewAsymEncryption failed:%w", err) + return "", fmt.Errorf("generateWrapKeyWithRSA: ocrypto.NewAsymEncryption failed:%w", err) } wrappedKey, err := asymEncrypt.Encrypt(symKey) if err != nil { - return "", fmt.Errorf("ocrypto.AsymEncryption.encrypt failed:%w", err) + return "", fmt.Errorf("generateWrapKeyWithRSA: ocrypto.AsymEncryption.encrypt failed:%w", err) } return string(ocrypto.Base64Encode(wrappedKey)), nil diff --git a/service/kas/access/rewrap.go b/service/kas/access/rewrap.go index 7a3112ba1b..e507a34473 100644 --- a/service/kas/access/rewrap.go +++ b/service/kas/access/rewrap.go @@ -606,7 +606,7 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*kaspb.UnsignedRew pdpAccessResults, accessErr := p.canAccess(ctx, tok, policies) if accessErr != nil { p.Logger.DebugContext(ctx, "tdf3rewrap: cannot access policy", "err", accessErr, "policies", policies) - failAllKaos(requests, results, err403("could not perform access")) + failAllKaos(requests, results, err500("could not perform access")) return "", results } @@ -716,7 +716,7 @@ func (p *Provider) nanoTDFRewrap(ctx context.Context, requests []*kaspb.Unsigned pdpAccessResults, accessErr := p.canAccess(ctx, tok, policies) if accessErr != nil { - failAllKaos(requests, results, err403("could not perform access")) + failAllKaos(requests, results, err500("could not perform access")) return "", results }