Skip to content

Commit

Permalink
Merge pull request #174 from edytuk/v2.10.0
Browse files Browse the repository at this point in the history
Merge sylabs/sif through v2.10.0
  • Loading branch information
DrDaveD authored Mar 7, 2023
2 parents 240e57d + 41b1b5e commit 5c7094f
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 41 deletions.
7 changes: 4 additions & 3 deletions pkg/integrity/clearsign.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Apptainer a Series of LF Projects LLC.
// For website terms of use, trademark policy, privacy policy and other
// project policies see https://lfprojects.org/policies
// Copyright (c) 2020-2022, Sylabs Inc. All rights reserved.
// Copyright (c) 2020-2023, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the LICENSE.md file
// distributed with the sources of this project regarding your rights to use or distribute this
// software.
Expand All @@ -11,6 +11,7 @@ package integrity

import (
"bytes"
"context"
"crypto"
"errors"
"io"
Expand Down Expand Up @@ -41,7 +42,7 @@ func newClearsignEncoder(e *openpgp.Entity, timeFunc func() time.Time) *clearsig

// signMessage signs the message from r in clear-sign format, and writes the result to w. On
// success, the hash function is returned.
func (en *clearsignEncoder) signMessage(w io.Writer, r io.Reader) (crypto.Hash, error) {
func (en *clearsignEncoder) signMessage(ctx context.Context, w io.Writer, r io.Reader) (crypto.Hash, error) {
plaintext, err := clearsign.Encode(w, en.e.PrivateKey, en.config)
if err != nil {
return 0, err
Expand All @@ -66,7 +67,7 @@ func newClearsignDecoder(kr openpgp.KeyRing) *clearsignDecoder {

// verifyMessage reads a message from r, verifies its signature, and returns the message contents.
// On success, the signing entity is set in vr.
func (de *clearsignDecoder) verifyMessage(r io.Reader, h crypto.Hash, vr *VerifyResult) ([]byte, error) {
func (de *clearsignDecoder) verifyMessage(ctx context.Context, r io.Reader, h crypto.Hash, vr *VerifyResult) ([]byte, error) { //nolint:lll
data, err := io.ReadAll(r)
if err != nil {
return nil, err
Expand Down
7 changes: 4 additions & 3 deletions pkg/integrity/clearsign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package integrity
import (
"bufio"
"bytes"
"context"
"crypto"
"errors"
"io"
Expand Down Expand Up @@ -57,7 +58,7 @@ func Test_clearsignEncoder_signMessage(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
b := bytes.Buffer{}

ht, err := tt.en.signMessage(&b, strings.NewReader(testMessage))
ht, err := tt.en.signMessage(context.Background(), &b, strings.NewReader(testMessage))
if got, want := err, tt.wantErr; (got != nil) != want {
t.Fatalf("got error %v, wantErr %v", got, want)
}
Expand Down Expand Up @@ -177,7 +178,7 @@ func Test_clearsignDecoder_verifyMessage(t *testing.T) {
Time: fixedTime,
},
}
h, err := en.signMessage(&b, strings.NewReader(testMessage))
h, err := en.signMessage(context.Background(), &b, strings.NewReader(testMessage))
if err != nil {
t.Fatal(err)
}
Expand All @@ -193,7 +194,7 @@ func Test_clearsignDecoder_verifyMessage(t *testing.T) {

// Decode and verify message.
var vr VerifyResult
message, err := tt.de.verifyMessage(bytes.NewReader(b.Bytes()), h, &vr)
message, err := tt.de.verifyMessage(context.Background(), bytes.NewReader(b.Bytes()), h, &vr)

if got, want := err, tt.wantErr; !errors.Is(got, want) {
t.Fatalf("got error %v, want %v", got, want)
Expand Down
6 changes: 4 additions & 2 deletions pkg/integrity/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ func (d digest) MarshalJSON() ([]byte, error) {
func (d *digest) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return fmt.Errorf("%w: %w", errDigestMalformed, err)
//nolint:errorlint // Go 1.19 compatibility
return fmt.Errorf("%w: %v", errDigestMalformed, err)
}

parts := strings.Split(s, ":")
Expand All @@ -133,7 +134,8 @@ func (d *digest) UnmarshalJSON(data []byte) error {

v, err := hex.DecodeString(value)
if err != nil {
return fmt.Errorf("%w: %w", errDigestMalformed, err)
//nolint:errorlint // Go 1.19 compatibility
return fmt.Errorf("%w: %v", errDigestMalformed, err)
}

for h, n := range supportedDigestAlgorithms {
Expand Down
11 changes: 6 additions & 5 deletions pkg/integrity/dsse.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ func newDSSEEncoder(ss []signature.Signer, opts ...signature.SignOption) (*dsseE

// signMessage signs the message from r in DSSE format, and writes the result to w. On success, the
// hash function is returned.
func (en *dsseEncoder) signMessage(w io.Writer, r io.Reader) (crypto.Hash, error) {
func (en *dsseEncoder) signMessage(ctx context.Context, w io.Writer, r io.Reader) (crypto.Hash, error) {
body, err := io.ReadAll(r)
if err != nil {
return 0, err
}

e, err := en.es.SignPayload(context.TODO(), en.payloadType, body)
e, err := en.es.SignPayload(ctx, en.payloadType, body)
if err != nil {
return 0, err
}
Expand Down Expand Up @@ -106,7 +106,7 @@ var (

// verifyMessage reads a message from r, verifies its signature(s), and returns the message
// contents. On success, the accepted public keys are set in vr.
func (de *dsseDecoder) verifyMessage(r io.Reader, h crypto.Hash, vr *VerifyResult) ([]byte, error) {
func (de *dsseDecoder) verifyMessage(ctx context.Context, r io.Reader, h crypto.Hash, vr *VerifyResult) ([]byte, error) { //nolint:lll
vs := make([]dsse.Verifier, 0, len(de.vs))
for _, v := range de.vs {
dv, err := newDSSEVerifier(v, options.WithCryptoSignerOpts(h))
Expand All @@ -127,9 +127,10 @@ func (de *dsseDecoder) verifyMessage(r io.Reader, h crypto.Hash, vr *VerifyResul
return nil, err
}

vr.aks, err = v.Verify(context.TODO(), &e)
vr.aks, err = v.Verify(ctx, &e)
if err != nil {
return nil, fmt.Errorf("%w: %w", errDSSEVerifyEnvelopeFailed, err)
//nolint:errorlint // Go 1.19 compatibility
return nil, fmt.Errorf("%w: %v", errDSSEVerifyEnvelopeFailed, err)
}

if e.PayloadType != de.payloadType {
Expand Down
6 changes: 3 additions & 3 deletions pkg/integrity/dsse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func Test_dsseEncoder_signMessage(t *testing.T) {
t.Fatal(err)
}

ht, err := en.signMessage(&b, strings.NewReader(testMessage))
ht, err := en.signMessage(context.Background(), &b, strings.NewReader(testMessage))
if got, want := err, tt.wantErr; (got != nil) != want {
t.Fatalf("got error %v, wantErr %v", got, want)
}
Expand Down Expand Up @@ -327,7 +327,7 @@ func Test_dsseDecoder_verifyMessage(t *testing.T) {
}

// Sign and encode message.
h, err := en.signMessage(&b, strings.NewReader(testMessage))
h, err := en.signMessage(context.Background(), &b, strings.NewReader(testMessage))
if err != nil {
t.Fatal(err)
}
Expand All @@ -349,7 +349,7 @@ func Test_dsseDecoder_verifyMessage(t *testing.T) {

// Decode and verify message.
var vr VerifyResult
message, err := tt.de.verifyMessage(bytes.NewReader(b.Bytes()), h, &vr)
message, err := tt.de.verifyMessage(context.Background(), bytes.NewReader(b.Bytes()), h, &vr)

if got, want := err, tt.wantErr; !errors.Is(got, want) {
t.Errorf("got error %v, want %v", got, want)
Expand Down
21 changes: 16 additions & 5 deletions pkg/integrity/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Apptainer a Series of LF Projects LLC.
// For website terms of use, trademark policy, privacy policy and other
// project policies see https://lfprojects.org/policies
// Copyright (c) 2020-2022, Sylabs Inc. All rights reserved.
// Copyright (c) 2020-2023, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the LICENSE.md file
// distributed with the sources of this project regarding your rights to use or distribute this
// software.
Expand All @@ -11,6 +11,7 @@ package integrity

import (
"bytes"
"context"
"crypto"
"encoding/json"
"errors"
Expand All @@ -36,7 +37,7 @@ var ErrNoKeyMaterial = errors.New("key material not provided")
type encoder interface {
// signMessage signs the message from r, and writes the result to w. On success, the signature
// hash function is returned.
signMessage(w io.Writer, r io.Reader) (ht crypto.Hash, err error)
signMessage(ctx context.Context, w io.Writer, r io.Reader) (ht crypto.Hash, err error)
}

type groupSigner struct {
Expand Down Expand Up @@ -153,7 +154,7 @@ func (gs *groupSigner) addObject(od sif.Descriptor) error {
}

// sign creates a digital signature as specified by gs.
func (gs *groupSigner) sign() (sif.DescriptorInput, error) {
func (gs *groupSigner) sign(ctx context.Context) (sif.DescriptorInput, error) {
// Get minimum object ID in group. Object IDs in the image metadata will be relative to this.
minID, err := getGroupMinObjectID(gs.f, gs.id)
if err != nil {
Expand All @@ -174,7 +175,7 @@ func (gs *groupSigner) sign() (sif.DescriptorInput, error) {

// Sign image metadata.
b := bytes.Buffer{}
ht, err := gs.en.signMessage(&b, bytes.NewReader(enc))
ht, err := gs.en.signMessage(ctx, &b, bytes.NewReader(enc))
if err != nil {
return sif.DescriptorInput{}, fmt.Errorf("failed to sign message: %w", err)
}
Expand All @@ -194,6 +195,7 @@ type signOpts struct {
objectIDs [][]uint32
timeFunc func() time.Time
deterministic bool
ctx context.Context //nolint:containedctx
}

// SignerOpt are used to configure so.
Expand Down Expand Up @@ -257,6 +259,14 @@ func OptSignDeterministic() SignerOpt {
}
}

// OptSignWithContext specifies that the given context should be used in RPC to external services.
func OptSignWithContext(ctx context.Context) SignerOpt {
return func(so *signOpts) error {
so.ctx = ctx
return nil
}
}

// withGroupedObjects splits the objects represented by ids into object groups, and calls fn once
// per object group.
func withGroupedObjects(f *sif.FileImage, ids []uint32, fn func(uint32, []uint32) error) error {
Expand Down Expand Up @@ -313,6 +323,7 @@ func NewSigner(f *sif.FileImage, opts ...SignerOpt) (*Signer, error) {

so := signOpts{
timeFunc: time.Now,
ctx: context.Background(),
}

// Apply options.
Expand Down Expand Up @@ -395,7 +406,7 @@ func NewSigner(f *sif.FileImage, opts ...SignerOpt) (*Signer, error) {
// Sign adds digital signatures as specified by s.
func (s *Signer) Sign() error {
for _, gs := range s.signers {
di, err := gs.sign()
di, err := gs.sign(s.opts.ctx)
if err != nil {
return fmt.Errorf("integrity: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/integrity/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package integrity

import (
"bytes"
"context"
"crypto"
"errors"
"os"
Expand Down Expand Up @@ -345,7 +346,7 @@ func TestGroupSigner_Sign(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
di, err := tt.gs.sign()
di, err := tt.gs.sign(context.Background())
if (err != nil) != tt.wantErr {
t.Fatalf("got error %v, want %v", err, tt.wantErr)
}
Expand Down
Loading

0 comments on commit 5c7094f

Please sign in to comment.