Skip to content
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# same token (exclusive PC/SC access; pick one owner). Pass the YubiKey CCID
# interface in with --device; see docs/docker-usb.md for finding it safely.

FROM golang:1.25.7@sha256:5a79b94c34c299ac0361fbb7c7fca6dc552e166b42341050323fa3ab137d7be9 AS build
FROM golang:1.27.0@sha256:65b6f280bf050ec5af12716857e8ea8439d694dbba8f31ceeb7630670071f2bb AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
Expand Down
64 changes: 63 additions & 1 deletion backends/backends_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package backends_test
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
Expand All @@ -28,8 +29,39 @@ func (f *fakeRunner) run(_ context.Context, command string, args ...string) ([]b
defer f.mu.Unlock()

f.calls = append(f.calls, append([]string{command}, args...))
if f.err != nil {
return f.output, f.err
}

// osslsigncode writes -out itself. Mimic that so publishSigned can rename.
for i, arg := range args {
if arg == "-out" && i+1 < len(args) {
err := writeFakeOut(args[i+1])
if err != nil {
return f.output, err
}
}
}

return f.output, f.err
return f.output, nil
}

func writeFakeOut(path string) error {
_, err := os.Stat(path)
if err == nil {
return nil
}

if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("checking staging -out: %w", err)
}

err = os.WriteFile(path, []byte("signed"), 0o600)
if err != nil {
return fmt.Errorf("writing staging -out: %w", err)
}

return nil
}

func TestOSSLSigncodeSign(t *testing.T) {
Expand Down Expand Up @@ -83,6 +115,36 @@ func TestOSSLSigncodeSign(t *testing.T) {
assert.NotContains(t, got, "123456", "PIN must not appear in argv")
}

func TestOSSLSigncodeOutDoesNotExist(t *testing.T) {
t.Parallel()

dir := t.TempDir()
input := filepath.Join(dir, "in.exe")
output := filepath.Join(dir, "out.exe")

require.NoError(t, os.WriteFile(input, []byte("MZ"), 0o600))

var sawOut string

backend := backends.NewOSSLSigncode(&backends.OSSLConfig{
PKCS11Module: "/usr/lib/libykcs11.so",
CertFile: "/etc/signerd/chain.pem",
Run: func(_ context.Context, _ string, args ...string) ([]byte, error) {
sawOut = args[len(args)-1]
_, err := os.Stat(sawOut)
require.ErrorIs(t, err, os.ErrNotExist, "osslsigncode 2.5 cannot overwrite -out")
require.NoError(t, os.WriteFile(sawOut, []byte("signed"), 0o600))

return nil, nil
},
})

err := backend.Sign(t.Context(), &signer.Request{InputPath: input, OutputPath: output})
require.NoError(t, err)
require.FileExists(t, output)
assert.NotEqual(t, output, sawOut)
}

func TestOSSLSigncodeDefaults(t *testing.T) {
t.Parallel()

Expand Down
11 changes: 10 additions & 1 deletion backends/osslsigncode.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package backends
import (
"context"
"fmt"
"os"

"golift.io/codesign/signer"
)
Expand Down Expand Up @@ -101,6 +102,14 @@ func (s *OSSLSigncode) Sign(ctx context.Context, req *signer.Request) error {

return withPINFile(s.config.PIN, func(pinPath string) error {
return publishSigned(req.OutputPath, func(staging string) error {
// osslsigncode 2.5 refuses to overwrite -out ("Failed to create
// file"). publishSigned's CreateTemp reserves a unique name by
// creating an empty file; remove it so the tool can write.
err := os.Remove(staging)
if err != nil {
return fmt.Errorf("osslsigncode sign: clearing staging file: %w", err)
}

args := []string{
"sign",
"-pkcs11module", s.config.PKCS11Module,
Expand All @@ -124,7 +133,7 @@ func (s *OSSLSigncode) Sign(ctx context.Context, req *signer.Request) error {

args = append(args, "-in", req.InputPath, "-out", staging)

_, err := s.config.Run(ctx, s.config.Command, args...)
_, err = s.config.Run(ctx, s.config.Command, args...)
if err != nil {
return fmt.Errorf("osslsigncode sign: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module golift.io/codesign

go 1.25.7
go 1.27.0

require (
github.com/golang-jwt/jwt/v5 v5.3.1
Expand Down