Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
105301: pgcryptocipher: add helper function for parsing cipher method r=rafiss a=andyyang890

**pgcryptocipher: create new package for pgcrypto cipher functions**

This patch creates a new package that will contain the implementation
of pgcrypto cipher functions, along with related helpers.

Release note: None

----

**pgcryptocipher: add helper function for parsing cipher method**

This patch adds a helper function for parsing the cipher method string
passed to pgcrypto cipher functions.

Release note: None

----

Informs #21001

105559: testccl/sqlccl: unskip TestExplainRedactDDL r=mgartner a=michae2

`TestExplainRedactDDL` is a randomized SQL test which runs variants of `EXPLAIN (REDACT)` on random SQL statements and checks that an injected poison string is always redacted in the output. It is very similar to another randomized test, `TestExplainRedact`, but also includes DDL in the random statements.

During development of v23.1 this test was skipped because the random DDL statements were running into other bugs unrelated to redaction. Now that things are more stable, let's unskip this test.

Fixes: #99005

Epic: None

Release note: None

Co-authored-by: Andy Yang <[email protected]>
Co-authored-by: Michael Erickson <[email protected]>
  • Loading branch information
3 people committed Jun 26, 2023
3 parents b2e9215 + 776fd52 + 9cf423f commit 284efee
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 35 deletions.
6 changes: 3 additions & 3 deletions pkg/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ ALL_TESTS = [
"//pkg/sql/schemachanger/screl:screl_test",
"//pkg/sql/schemachanger/scrun:scrun_test",
"//pkg/sql/schemachanger:schemachanger_test",
"//pkg/sql/sem/builtins/pgcrypto:pgcrypto_test",
"//pkg/sql/sem/builtins/pgcrypto/pgcryptocipher:pgcryptocipher_test",
"//pkg/sql/sem/builtins/pgformat:pgformat_test",
"//pkg/sql/sem/builtins:builtins_disallowed_imports_test",
"//pkg/sql/sem/builtins:builtins_test",
Expand Down Expand Up @@ -1983,8 +1983,8 @@ GO_TARGETS = [
"//pkg/sql/sem/asof:asof",
"//pkg/sql/sem/builtins/builtinconstants:builtinconstants",
"//pkg/sql/sem/builtins/builtinsregistry:builtinsregistry",
"//pkg/sql/sem/builtins/pgcrypto:pgcrypto",
"//pkg/sql/sem/builtins/pgcrypto:pgcrypto_test",
"//pkg/sql/sem/builtins/pgcrypto/pgcryptocipher:pgcryptocipher",
"//pkg/sql/sem/builtins/pgcrypto/pgcryptocipher:pgcryptocipher_test",
"//pkg/sql/sem/builtins/pgformat:pgformat",
"//pkg/sql/sem/builtins/pgformat:pgformat_test",
"//pkg/sql/sem/builtins:builtins",
Expand Down
4 changes: 0 additions & 4 deletions pkg/ccl/testccl/sqlccl/explain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/lexbase"
"github.com/cockroachdb/cockroach/pkg/sql/tests"
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
"github.com/cockroachdb/cockroach/pkg/testutils/skip"
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/randutil"
Expand All @@ -33,9 +32,6 @@ func TestExplainRedactDDL(t *testing.T) {
defer leaktest.AfterTest(t)()
defer log.Scope(t).Close(t)

skip.WithIssue(t, 99005)
skip.UnderStressWithIssue(t, 99005)

const numStatements = 10

ctx := context.Background()
Expand Down
20 changes: 0 additions & 20 deletions pkg/sql/sem/builtins/pgcrypto/BUILD.bazel

This file was deleted.

32 changes: 32 additions & 0 deletions pkg/sql/sem/builtins/pgcrypto/pgcryptocipher/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "pgcryptocipher",
srcs = [
"cipher_method.go",
"doc.go",
"padding.go",
],
importpath = "github.com/cockroachdb/cockroach/pkg/sql/sem/builtins/pgcrypto/pgcryptocipher",
visibility = ["//visibility:public"],
deps = [
"//pkg/sql/pgwire/pgcode",
"//pkg/sql/pgwire/pgerror",
"//pkg/util/errorutil/unimplemented",
"@com_github_cockroachdb_errors//:errors",
],
)

go_test(
name = "pgcryptocipher_test",
srcs = [
"cipher_method_test.go",
"padding_test.go",
],
args = ["-test.timeout=295s"],
embed = [":pgcryptocipher"],
deps = [
"//pkg/util/leaktest",
"@com_github_stretchr_testify//require",
],
)
84 changes: 84 additions & 0 deletions pkg/sql/sem/builtins/pgcrypto/pgcryptocipher/cipher_method.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package pgcryptocipher

import (
"regexp"
"strings"

"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
)

type cipherAlgorithm int

const (
_ cipherAlgorithm = iota
aesCipher
)

type cipherMode int

const (
cbcMode cipherMode = iota
)

type cipherPadding int

const (
pkcsPadding cipherPadding = iota
noPadding
)

type cipherMethod struct {
algorithm cipherAlgorithm
mode cipherMode
padding cipherPadding
}

func parseCipherMethod(s string) (cipherMethod, error) {
cipherMethodRE := regexp.MustCompile("^(?P<algorithm>[[:alpha:]]+)(?:-(?P<mode>[[:alpha:]]+))?(?:/pad:(?P<padding>[[:alpha:]]+))?$")

submatches := cipherMethodRE.FindStringSubmatch(s)
if submatches == nil {
return cipherMethod{}, pgerror.Newf(pgcode.InvalidParameterValue, `cipher method has wrong format: "%s"`, s)
}

ret := cipherMethod{}

switch algorithm := submatches[cipherMethodRE.SubexpIndex("algorithm")]; strings.ToLower(algorithm) {
case "aes":
ret.algorithm = aesCipher
case "bf":
return cipherMethod{}, unimplemented.NewWithIssue(105466, "Blowfish is insecure and not supported")
default:
return cipherMethod{}, pgerror.Newf(pgcode.InvalidParameterValue, `cipher method has unsupported algorithm: "%s"`, algorithm)
}

switch mode := submatches[cipherMethodRE.SubexpIndex("mode")]; strings.ToLower(mode) {
case "", "cbc":
case "ecb":
return cipherMethod{}, unimplemented.NewWithIssue(105466, "ECB mode is insecure and not supported")
default:
return cipherMethod{}, pgerror.Newf(pgcode.InvalidParameterValue, `cipher method has unsupported mode: "%s"`, mode)
}

switch padding := submatches[cipherMethodRE.SubexpIndex("padding")]; strings.ToLower(padding) {
case "", "pkcs":
case "none":
ret.padding = noPadding
default:
return cipherMethod{}, pgerror.Newf(pgcode.InvalidParameterValue, `cipher method has unsupported padding: "%s"`, padding)
}

return ret, nil
}
80 changes: 80 additions & 0 deletions pkg/sql/sem/builtins/pgcrypto/pgcryptocipher/cipher_method_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package pgcryptocipher

import (
"testing"

"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/stretchr/testify/require"
)

func TestParseCipherMethod(t *testing.T) {
defer leaktest.AfterTest(t)()

// Positive tests
for input, expected := range map[string]cipherMethod{
"aes": {
algorithm: aesCipher,
mode: cbcMode,
padding: pkcsPadding,
},
"aes/pad:pkcs": {
algorithm: aesCipher,
mode: cbcMode,
padding: pkcsPadding,
},
"aes/pad:none": {
algorithm: aesCipher,
mode: cbcMode,
padding: noPadding,
},
"aes-cbc": {
algorithm: aesCipher,
mode: cbcMode,
padding: pkcsPadding,
},
"aes-cbc/pad:pkcs": {
algorithm: aesCipher,
mode: cbcMode,
padding: pkcsPadding,
},
"aes-cbc/pad:none": {
algorithm: aesCipher,
mode: cbcMode,
padding: noPadding,
},
} {
t.Run(input, func(t *testing.T) {
ct, err := parseCipherMethod(input)
require.NoError(t, err)
require.Equal(t, expected, ct)
})
}

// Negative tests
for input, expectedErr := range map[string]string{
// Unsupported algorithms and modes
"aes-ecb": `unimplemented: ECB mode is insecure and not supported`,
"bf": `unimplemented: Blowfish is insecure and not supported`,

// Invalid values
"aes/pad=pkcs": `cipher method has wrong format: "aes/pad=pkcs"`,
"aescbc": `cipher method has unsupported algorithm: "aescbc"`,
"aes-ctr": `cipher method has unsupported mode: "ctr"`,
"aes/pad:zero": `cipher method has unsupported padding: "zero"`,
} {
t.Run(input, func(t *testing.T) {
_, err := parseCipherMethod(input)
require.EqualError(t, err, expectedErr)
})
}
}
13 changes: 13 additions & 0 deletions pkg/sql/sem/builtins/pgcrypto/pgcryptocipher/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

// Package pgcryptocipher contains the implementation of pgcrypto
// cipher functions.
package pgcryptocipher
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package pgcrypto
package pgcryptocipher

import (
"bytes"
Expand All @@ -17,10 +17,10 @@ import (
"github.com/cockroachdb/errors"
)

// PKCSPad pads a slice of bytes to a multiple of the given block size
// pkcsPad pads a slice of bytes to a multiple of the given block size
// using the process specified in
// https://datatracker.ietf.org/doc/html/rfc5652#section-6.3.
func PKCSPad(data []byte, blockSize int) ([]byte, error) {
func pkcsPad(data []byte, blockSize int) ([]byte, error) {
if blockSize <= 0 || blockSize > math.MaxUint8 {
return nil, errors.Newf("invalid block size for PKCS padding: %d", blockSize)
}
Expand All @@ -31,8 +31,8 @@ func PKCSPad(data []byte, blockSize int) ([]byte, error) {
return append(data, padding...), nil
}

// PKCSUnpad removes the padding added by PKCSPad.
func PKCSUnpad(data []byte) ([]byte, error) {
// pkcsUnpad removes the padding added by pkcsPad.
func pkcsUnpad(data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, errors.New("PKCS-padded data is empty")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package pgcrypto
package pgcryptocipher

import (
"testing"
Expand Down Expand Up @@ -53,7 +53,7 @@ func TestPKCSPad(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
actual, err := PKCSPad(tc.data, tc.blockSize)
actual, err := pkcsPad(tc.data, tc.blockSize)
if tc.expectedErr != "" {
require.EqualError(t, err, tc.expectedErr)
return
Expand Down Expand Up @@ -102,7 +102,7 @@ func TestPKCSUnpad(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
actual, err := PKCSUnpad(tc.data)
actual, err := pkcsUnpad(tc.data)
if tc.expectedErr != "" {
require.EqualError(t, err, tc.expectedErr)
return
Expand Down

0 comments on commit 284efee

Please sign in to comment.