Skip to content

Commit b2b28b0

Browse files
committed
image/internal: validate blob against digest
`validateBlobAgainstDigest` verifies that the provided blob matches the exepcted digest. If expected digest itself is invalid or unusable, it rejects the blob. Callers don't need to pre-validate the expected digest. This enables `skopeo copy` to work with sha512-digested images. Signed-off-by: Lokesh Mandvekar <[email protected]>
1 parent 397182c commit b2b28b0

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package image
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/opencontainers/go-digest"
7+
)
8+
9+
func validateBlobAgainstDigest(blob []byte, expectedDigest digest.Digest) error {
10+
if expectedDigest == "" {
11+
return fmt.Errorf("expected digest is empty")
12+
}
13+
err := expectedDigest.Validate()
14+
if err != nil {
15+
return fmt.Errorf("invalid digest format: %q", expectedDigest)
16+
}
17+
digestAlgorithm := expectedDigest.Algorithm()
18+
if !digestAlgorithm.Available() {
19+
return fmt.Errorf("unsupported digest algorithm: %s", digestAlgorithm)
20+
}
21+
computedDigest := digestAlgorithm.FromBytes(blob)
22+
if computedDigest != expectedDigest {
23+
return fmt.Errorf("Download config.json digest %s does not match expected %s", computedDigest, expectedDigest)
24+
}
25+
return nil
26+
}

image/internal/image/docker_schema2.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ func (m *manifestSchema2) ConfigBlob(ctx context.Context) ([]byte, error) {
110110
if err != nil {
111111
return nil, err
112112
}
113-
computedDigest := digest.FromBytes(blob)
114-
if computedDigest != m.m.ConfigDescriptor.Digest {
115-
return nil, fmt.Errorf("Download config.json digest %s does not match expected %s", computedDigest, m.m.ConfigDescriptor.Digest)
113+
expectedDigest := m.m.ConfigDescriptor.Digest
114+
if err := validateBlobAgainstDigest(blob, expectedDigest); err != nil {
115+
return nil, fmt.Errorf("config descriptor validation failed: %w", err)
116116
}
117117
m.configBlob = blob
118118
}

image/internal/image/oci.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"slices"
99

1010
ociencspec "github.com/containers/ocicrypt/spec"
11-
"github.com/opencontainers/go-digest"
1211
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
1312
"go.podman.io/image/v5/docker/reference"
1413
"go.podman.io/image/v5/internal/iolimits"
@@ -74,9 +73,9 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) {
7473
if err != nil {
7574
return nil, err
7675
}
77-
computedDigest := digest.FromBytes(blob)
78-
if computedDigest != m.m.Config.Digest {
79-
return nil, fmt.Errorf("Download config.json digest %s does not match expected %s", computedDigest, m.m.Config.Digest)
76+
expectedDigest := m.m.Config.Digest
77+
if err := validateBlobAgainstDigest(blob, expectedDigest); err != nil {
78+
return nil, fmt.Errorf("config validation failed: %w", err)
8079
}
8180
m.configBlob = blob
8281
}

0 commit comments

Comments
 (0)