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

Fail timestamp verification if no root is provided #3224

Merged
merged 5 commits into from
Sep 8, 2023
Merged
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
24 changes: 13 additions & 11 deletions pkg/cosign/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,14 +648,12 @@ func verifyInternal(ctx context.Context, sig oci.Signature, h v1.Hash,
bundleVerified bool, err error) {
var acceptableRFC3161Time, acceptableRekorBundleTime *time.Time // Timestamps for the signature we accept, or nil if not applicable.

if co.TSARootCertificates != nil {
acceptableRFC3161Timestamp, err := VerifyRFC3161Timestamp(sig, co)
if err != nil {
return false, fmt.Errorf("unable to verify RFC3161 timestamp bundle: %w", err)
}
if acceptableRFC3161Timestamp != nil {
acceptableRFC3161Time = &acceptableRFC3161Timestamp.Time
}
acceptableRFC3161Timestamp, err := VerifyRFC3161Timestamp(sig, co)
if err != nil {
return false, fmt.Errorf("unable to verify RFC3161 timestamp bundle: %w", err)
}
if acceptableRFC3161Timestamp != nil {
acceptableRFC3161Time = &acceptableRFC3161Timestamp.Time
}

if !co.IgnoreTlog {
Expand Down Expand Up @@ -1099,13 +1097,17 @@ func VerifyBundle(sig oci.Signature, co *CheckOpts) (bool, error) {

// VerifyRFC3161Timestamp verifies that the timestamp in sig is correctly signed, and if so,
// returns the timestamp value.
// It returns (nil, nil) if there is no timestamp, or (nil, err) if there is an invalid timestamp.
// It returns (nil, nil) if there is no timestamp, or (nil, err) if there is an invalid timestamp or if
// no root is provided with a timestamp.
func VerifyRFC3161Timestamp(sig oci.Signature, co *CheckOpts) (*timestamp.Timestamp, error) {
ts, err := sig.RFC3161Timestamp()
if err != nil {
switch {
case err != nil:
return nil, err
} else if ts == nil {
case ts == nil:
return nil, nil
case co.TSARootCertificates == nil:
return nil, errors.New("no TSA root certificate(s) provided to verify timestamp")
}

b64Sig, err := sig.Base64Signature()
Expand Down
9 changes: 9 additions & 0 deletions pkg/cosign/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1420,4 +1420,13 @@ func TestVerifyRFC3161Timestamp(t *testing.T) {
if err == nil || !strings.Contains(err.Error(), "hashed messages don't match") {
t.Fatalf("expected error verifying mismatched signatures, got: %v", err)
}

// failure without root certificate
_, err = VerifyRFC3161Timestamp(ociSig, &CheckOpts{
TSACertificate: leaves[0],
TSAIntermediateCertificates: intermediates,
})
if err == nil || !strings.Contains(err.Error(), "no TSA root certificate(s) provided to verify timestamp") {
t.Fatalf("expected error verifying without a root certificate, got: %v", err)
}
}
12 changes: 9 additions & 3 deletions test/e2e_tsa_mtls.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ TIMESTAMP_SERVER_CERT=$CERT_BASE/tsa-mtls-server.crt
TIMESTAMP_SERVER_KEY=$CERT_BASE/tsa-mtls-server.key
TIMESTAMP_SERVER_NAME="server.example.com"
TIMESTAMP_SERVER_URL=https://localhost:3000/api/v1/timestamp
TIMESTAMP_CHAIN_FILE="timestamp-chain"

set +e
COSIGN_CLI=./cosign
Expand All @@ -50,6 +51,12 @@ timestamp-server serve --disable-ntp-monitoring --tls-host 0.0.0.0 --tls-port 30
--scheme https --tls-ca $TIMESTAMP_CACERT --tls-key $TIMESTAMP_SERVER_KEY \
--tls-certificate $TIMESTAMP_SERVER_CERT &

sleep 1
curl -k -s --key test/testdata/tsa-mtls-client.key \
--cert test/testdata/tsa-mtls-client.crt \
--cacert test/testdata/tsa-mtls-ca.crt https://localhost:3000/api/v1/timestamp/certchain \
> $TIMESTAMP_CHAIN_FILE
echo "DONE: $(ls -l $TIMESTAMP_CHAIN_FILE)"

IMG=${IMAGE_URI_DIGEST:-}
if [[ "$#" -ge 1 ]]; then
Expand All @@ -67,7 +74,6 @@ echo "IMG (IMAGE_URI_DIGEST): $IMG, TIMESTAMP_SERVER_URL: $TIMESTAMP_SERVER_URL"

rm -f *.pem import-cosign.* key.pem


# use gencert to generate CA, keys and certificates
echo "generate keys and certificates with gencert"

Expand All @@ -85,8 +91,8 @@ rm -f key.pem import-cosign.*
echo "cosign verify:"
$COSIGN_CLI verify --insecure-ignore-tlog --insecure-ignore-sct --check-claims=true \
--certificate-identity-regexp '[email protected]' --certificate-oidc-issuer-regexp '.*' \
--certificate-chain cacert.pem $IMG
--certificate-chain cacert.pem --timestamp-certificate-chain $TIMESTAMP_CHAIN_FILE $IMG

# cleanup
rm -fr ca-key.pem cacert.pem cert.pem /tmp/timestamp-authority
rm -fr ca-key.pem cacert.pem cert.pem timestamp-chain /tmp/timestamp-authority
pkill -f 'timestamp-server'
Loading