You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/internal/cms/fixtures_test.go

86 lines
2.3 KiB

Tests of the CMS reader: certificates field by field, every check, fuzzing The builder of the tests, cmstest: - NewCert writes a certificate from the DER of its tbsCertificate, field by field: names of any string type with any bytes (UTF8String, PrintableString with an underscore or an at sign, IA5String, TeletexString, BMPString of odd length or with a surrogate, VisibleString, NumericString), an attribute twice or none, no version, times with a fraction, an extension twice, a compressed EC key, an even modulus, and any signature. A Signer made so serves Signature and Token. - Options for the version of a SignerInfo, the hashAlgorithm and the certHash of an ESSCertIDv2, a signatureAlgorithm other than the one of the key, a certificate twice, two content-type attributes, an attribute with an arc of 2^31, a SignerInfo twice, BER, signerInfos out of order, two signature-time-stamp attributes, and edits of the SignedData and of each SignerInfo. - Token options for any accuracy, a genTime of free text, ordering FALSE, a field after the last, an imprint of any length, no message-digest, a CRL in crls and the certificate of the authority twice. - Edits of the DER after signing: Edit, Retag, Withdraw (a SignerInfo removed), WithoutTimeStamp (a CAdES-T removed), Merge (a co-signature) and Indefinite. The tests of internal/cms and internal/der fail for each check of cms.go, cert.go, verify.go and der.go. A mutation run, which replaces each leaf of each condition by false and by true, one at a time, kills every mutant that is not equivalent to the code it mutates. FuzzParseSignature, FuzzParseToken, FuzzParseCert and FuzzDERCheck, seeded with security_cms.json and with what cmstest builds: no panic, what Check accepts Split reads, and the parsers fail only with ErrForm or ErrAlgorithm. capsule: the case of a seal outside the validity of the certificate gave an invalid seal; it now tests a certificate that expired before a valid seal (out of validity) apart from an authority that was not valid at its time (invalid seal). SIGNERS out of order, empty, too long, with 31 bytes or with a hash twice are F1 beside a CMS signature that is valid for the AUTHOR_MESSAGE of those SIGNERS, and the names of certificates show as spec v0.12 §29.7 says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
package cms_test
import (
"crypto/elliptic"
"crypto/sha1"
"errors"
"testing"
"g.activething.com/go/DateKeys/internal/cms"
"g.activething.com/go/DateKeys/internal/cms/cmstest"
"g.activething.com/go/DateKeys/internal/der"
)
// The keys and the certificates of the tests of the reader, made once: an
// RSA key takes time to generate. The certificates are made field by field,
// with the profile of spec §29.10, and are valid from 2020 to 2040.
var (
ecKey = cmstest.ECKey(elliptic.P256())
ecKey2 = cmstest.ECKey(elliptic.P256())
rsaKey = cmstest.RSAKey(2048)
ana = cmstest.NewCert(cmstest.CertSpec{CN: "Ana López"}, ecKey)
luis = cmstest.NewCert(cmstest.CertSpec{CN: "Luis Gómez"}, rsaKey)
tsa = cmstest.NewCert(cmstest.CertSpec{CN: "TSA de prueba"}, ecKey2)
)
// path joins paths of cmstest.Edit.
func path(parts ...any) []int {
var out []int
for _, p := range parts {
switch x := p.(type) {
case int:
out = append(out, x)
case []int:
out = append(out, x...)
}
}
return out
}
// firstSignerInfo is the path of the first SignerInfo of a signature.
func firstSignerInfo(b []byte) []int { return path(cmstest.SignerInfosPath(b), 0) }
// wantForm checks that the signature b breaks the profile (F1).
func wantForm(t *testing.T, name string, b []byte) {
t.Helper()
if _, err := cms.ParseSignature(b); !errors.Is(err, cms.ErrForm) {
t.Errorf("%s: %v, want a form error", name, err)
}
}
// signerOf parses the signature b, which must meet the profile, and returns
// its only SignerInfo.
func signerOf(t *testing.T, name string, b []byte) *cms.SignerInfo {
t.Helper()
sd, err := cms.ParseSignature(b)
if err != nil || len(sd.Signers) != 1 {
t.Fatalf("%s: %v", name, err)
}
return sd.Signers[0]
}
// resultOf is the result of the only SignerInfo of the signature b over msg.
func resultOf(t *testing.T, name string, b []byte) cms.Result {
t.Helper()
return signerOf(t, name, b).Check(msg)
}
func isForm(err error) bool { return errors.Is(err, cms.ErrForm) }
func isAlgorithm(err error) bool { return errors.Is(err, cms.ErrAlgorithm) }
// contentOf returns the content octets of the DER element b.
func contentOf(b []byte) []byte {
c, err := der.Content(b)
if err != nil {
panic(err)
}
return c
}
func sha1Sum(b []byte) []byte {
s := sha1.Sum(b)
return s[:]
}

Powered by TurnKey Linux.