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
26 changes: 20 additions & 6 deletions cmd/sign1util/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,24 @@ func checkCoseSign1(inputFilename string, chainFilename string, didString string
fmt.Fprintf(os.Stdout, "pubcert: %s\n", unpacked.Pubcert)
fmt.Fprintf(os.Stdout, "payload:\n%s\n", string(unpacked.Payload[:]))
}

if len(chainPEMString) == 0 {
chainPEMString = unpacked.ChainPem
}
// Only resolve when the caller explicitly asked. Callers like `did-x509 -in`,
// `leaf -in`, `print -in` pass an empty didString and don't want DID
// resolution. The `check` command supplies its own fallback below.
if len(didString) > 0 {
if len(chainPEMString) == 0 {
chainPEMString = unpacked.ChainPem
}
didDoc, err := didx509resolver.Resolve(chainPEMString, didString, true)
var didDoc string
didDoc, err = didx509resolver.Resolve(chainPEMString, didString, true)
if err == nil {
fmt.Fprintf(os.Stdout, "DID resolvers passed:\n%s\n", didDoc)
} else {
// all the error paths return an empty string, so we can just print the error
fmt.Fprintf(os.Stdout, "DID resolvers failed: err: %s\n", err.Error())
}
}

return unpacked, err
}

Expand Down Expand Up @@ -173,15 +179,23 @@ var checkCmd = cli.Command{
},
},
Action: func(ctx *cli.Context) error {
_, err := checkCoseSign1(
didString := ctx.String("did")
unpacked, err := checkCoseSign1(
ctx.String("in"),
ctx.String("chain"),
ctx.String("did"),
didString,
ctx.Bool("verbose"),
)
if err != nil {
return fmt.Errorf("failed check: %w", err)
}
// If no explicit -did was given, validate the issuer embedded in the
// COSE document against the chain.
if len(didString) == 0 && len(unpacked.Issuer) > 0 {
if _, err := didx509resolver.Resolve(unpacked.ChainPem, unpacked.Issuer, true); err != nil {
return fmt.Errorf("failed check (issuer from cose %q): %w", unpacked.Issuer, err)
}
}
return nil
},
}
Expand Down
36 changes: 18 additions & 18 deletions pkg/cosesign1/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@
#


# note test-fail is expected to fail

AUTOPARSE_CHAIN:=0
# Opaque label written into the COSE `iss` header. It is NOT validated against
# the chain at create time; the Go unit test asserts the round-trip preserves
# this exact string, so don't change it without updating the test.
ISSUER_DID:="TestIssuer"
FEED:="TestFeed"
DID_FINGERPRINT:=""

all: chain.pem cose test-fail test-pass

Expand All @@ -38,11 +37,6 @@ cose: infra.rego.cose
%.pem:
$(MAKE) -f Makefile.certs chain.pem

ifeq "$(AUTOPARSE_CHAIN)" "1"
ISSUER_DID = $(shell ./sign1util did-x509 -chain chain.pem -policy cn)
DID_FINGERPRINT = $(shell ./sign1util did-x509 -chain chain.pem -policy cn | cut -d: -f5)
endif

# from these media types have to match containerd. The also need to change and the security policy one ought to be x-ms-ccepolicy-frag
# fragment atrifact type = application/x-ms-ccepolicy-frag
# fragment media type = application/cose-x509+rego
Expand Down Expand Up @@ -74,13 +68,13 @@ show: sign1util
didx509: chain.pem sign1util
./sign1util did-x509 -chain chain.pem -i 1 -policy "subject:CN:Test Leaf (DO NOT TRUST)" -verbose

info: chain.pem sign1util
@echo "ISSUER_DID: $(ISSUER_DID)"
@echo "DID_FINGERPRINT: $(DID_FINGERPRINT)"

# for this to pass the did:x509 fingerprint (RgpNsHOK5hPlCAfTtiGY_BcDhFRxQbJnhlxNDhxps6U here) needs to be the one output from make print
did-check: chain.pem infra.rego.cose sign1util info
./sign1util check -in infra.rego.cose -did $(ISSUER_DID)
# did-check derives the REAL did:x509 from chain.pem at run time and resolves
# it against the chain. Fails loudly if did-x509 returns empty.
did-check: chain.pem infra.rego.cose sign1util
@did="$$(./sign1util did-x509 -chain chain.pem -policy cn)"; \
test -n "$$did" || { echo "did-x509 returned empty - check chain.pem"; exit 1; }; \
echo "did-check: using did=$$did"; \
./sign1util check -in infra.rego.cose -did "$$did"

# For normal workflow start from the chain.pem, here we'd take the chain from inside the cose sign1 doc, eg to manually confirm it is
# as otherwise expected (ie that the issuer DID matches the chain) or to shortcut getting a DID from a cose document.
Expand All @@ -92,12 +86,18 @@ did-from-cose: sign1util infra.rego.cose
# note that since the infra.rego.cose is actually good the first part of the check will report a pass "checkCoseSign1 passed"

# expect "DID resolvers failed: err: DID verification failed: unexpected certificate fingerprint"
# The recipe is expected to fail at the tool level; invert the exit code so the make target succeeds.
did-fail-fingerprint: chain.pem sign1util infra.rego.cose
./sign1util check -in infra.rego.cose -did did:x509:0:sha256:XXXi_nuWegx4NiLaeGabiz36bDUhDDiHEFl8HXMA_4o::subject:CN:Test+Leaf+%28DO+NOT+TRUST%29
! ./sign1util check -in infra.rego.cose -did did:x509:0:sha256:XXXi_nuWegx4NiLaeGabiz36bDUhDDiHEFl8HXMA_4o::subject:CN:Test+Leaf+%28DO+NOT+TRUST%29

# expect "DID resolvers failed: err: DID verification failed: invalid subject value: CN=Test XXXX (DO NOT TRUST)"
# Builds a DID with the REAL fingerprint but a WRONG subject; recipe must still
# fail at the tool level - `!` inverts that into a make-level success.
did-fail-subject: chain.pem sign1util infra.rego.cose
./sign1util check -in infra.rego.cose -did did:x509:0:sha256:$(DID_FINGERPRINT)::subject:CN:Test+XXXX+%28DO+NOT+TRUST%29
@fp="$$(./sign1util did-x509 -chain chain.pem -policy cn | cut -d: -f5)"; \
test -n "$$fp" || { echo "could not derive fingerprint - check chain.pem"; exit 1; }; \
! ./sign1util check -in infra.rego.cose \
-did "did:x509:0:sha256:$$fp::subject:CN:Test+XXXX+%28DO+NOT+TRUST%29"

did-fail: did-fail-subject did-fail-fingerprint

Expand Down
4 changes: 2 additions & 2 deletions pkg/cosesign1/Makefile.certs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ all: chain.pem

root.cert.pem: root.private.pem
openssl req -new -key $< -out $@.tmp.csr -subj "/CN=Test Root CA (DO NOT TRUST)" -addext 'basicConstraints=critical,CA:TRUE' -addext 'keyUsage=digitalSignature,keyCertSign'
openssl x509 -req -days 365 -in $@.tmp.csr -signkey $< -out $@ -CAcreateserial -extfile cert.extensions.cfg
openssl x509 -req -days 3650 -in $@.tmp.csr -signkey $< -out $@ -CAcreateserial -extfile cert.extensions.cfg
rm -rf $@.tmp.csr

intermediate.cert.pem: intermediate.private.pem | root.private.pem
openssl req -new -key $< -out $@.tmp.csr -subj "/CN=Test Intermediate CA (DO NOT TRUST)" -addext 'basicConstraints=critical,CA:TRUE' -addext 'keyUsage=digitalSignature,keyCertSign'
openssl x509 -req -days 365 -in $@.tmp.csr -CA ${subst private,cert,$|} -CAkey $| -out $@ -CAcreateserial -extfile cert.extensions.cfg
openssl x509 -req -days 1825 -in $@.tmp.csr -CA ${subst private,cert,$|} -CAkey $| -out $@ -CAcreateserial -extfile cert.extensions.cfg
rm $@.tmp.csr

leaf.cert.pem: leaf.private.pem | intermediate.private.pem
Expand Down
Loading