// Package cms reads the CMS signatures (RFC 5652) and the RFC 3161 time-stamp // tokens that spec §29.10 and §29.11 define, with the CAdES profile that // AutoFirma and other signing applications produce, and checks them with a // closed table of algorithms. It uses the standard library only. // // It checks the signature and the dates, never who issued a certificate or // whether it was revoked: a validator of the country that corresponds does // that (spec §29.10). Object identifiers are compared by the bytes of their // DER, so that an arc of any size is only an identifier that the table does // not have. package cms import ( "bytes" "crypto/sha1" "crypto/sha256" "crypto/sha512" "errors" "fmt" "hash" "strconv" "strings" "g.activething.com/go/DateKeys/internal/der" ) // ErrForm is the error of a signature or a token whose form breaks the // profile of spec §29.10 or §29.11: the verdicts F1 and S2. var ErrForm = errors.New("cms: the form breaks the profile") // ErrAlgorithm is the error of a token that uses an algorithm outside the // table of spec §29.10: the verdict S1. var ErrAlgorithm = errors.New("cms: an algorithm outside the table") func formErr(format string, args ...any) error { return fmt.Errorf("%w: %s", ErrForm, fmt.Sprintf(format, args...)) } // oid returns the content of the DER of the object identifier s, written // with dots: the bytes that this package compares. func oid(s string) []byte { parts := strings.Split(s, ".") arcs := make([]uint64, len(parts)) for i, p := range parts { n, err := strconv.ParseUint(p, 10, 64) if err != nil || len(parts) < 2 { panic("cms: a bad object identifier " + s) } arcs[i] = n } out := base128(nil, arcs[0]*40+arcs[1]) for _, a := range arcs[2:] { out = base128(out, a) } return out } func base128(out []byte, v uint64) []byte { var tmp [10]byte i := len(tmp) - 1 tmp[i] = byte(v & 0x7f) for v >>= 7; v > 0; v >>= 7 { i-- tmp[i] = byte(v&0x7f) | 0x80 } return append(out, tmp[i:]...) } // oidOf returns the content of the object identifier element b. func oidOf(b []byte) ([]byte, bool) { if len(b) == 0 || b[0] != 0x06 { return nil, false } c, err := der.Content(b) return c, err == nil } // The object identifiers of the profile. var ( oidData = oid("1.2.840.113549.1.7.1") oidSignedData = oid("1.2.840.113549.1.7.2") oidContentType = oid("1.2.840.113549.1.9.3") oidMessageDig = oid("1.2.840.113549.1.9.4") oidSigCertV1 = oid("1.2.840.113549.1.9.16.2.12") oidSigCertV2 = oid("1.2.840.113549.1.9.16.2.47") oidSigTimeStamp = oid("1.2.840.113549.1.9.16.2.14") oidTSTInfo = oid("1.2.840.113549.1.9.16.1.4") oidRIOCSP = oid("1.3.6.1.5.5.7.16.2") oidSHA256 = oid("2.16.840.1.101.3.4.2.1") oidSHA384 = oid("2.16.840.1.101.3.4.2.2") oidSHA512 = oid("2.16.840.1.101.3.4.2.3") ) // SignedData is the part of a CMS SignedData that the profile uses. type SignedData struct { // Certs are the certificates that meet the profile of §29.10, each once: // another one decides nothing, unless a SignerInfo names it. Certs []*Cert // OCSP are the OCSP responses of crls. OCSP [][]byte // Signers are the SignerInfo, in the order of the encoding. Signers []*SignerInfo // EContent is the content of a token, nil in a detached signature. EContent []byte } // SignerInfo is a SignerInfo with the certificate that its sid names. type SignerInfo struct { Cert *Cert // DigestAlg and SigAlg are the algorithm identifiers as written. DigestAlg, SigAlg algID // SignedAttrs is the DER of the signedAttrs as stored, with the // context tag [0]; the signature covers it with the tag of a SET. SignedAttrs []byte MessageDigest []byte Signature []byte // Token is the signature-time-stamp attribute, the DER of its // ContentInfo, nil when there is none. Token []byte } type algID struct { OID []byte // the content of the object identifier Params []byte // the DER of the parameters, nil when absent } func parseAlgID(b []byte) (algID, error) { id, kids, err := der.Split(b) if err != nil || id != 0x30 || len(kids) < 1 || len(kids) > 2 { return algID{}, formErr("an AlgorithmIdentifier") } var a algID var ok bool if a.OID, ok = oidOf(kids[0]); !ok { return algID{}, formErr("an AlgorithmIdentifier without an object identifier") } if len(kids) == 2 { a.Params = kids[1] } return a, nil } // hashOf returns the hash that an identifier of the table names, and false // for any other. func (a algID) hashOf() (func() hash.Hash, bool) { if a.Params != nil && !bytes.Equal(a.Params, []byte{5, 0}) { return nil, false } switch { case bytes.Equal(a.OID, oidSHA256): return sha256.New, true case bytes.Equal(a.OID, oidSHA384): return sha512.New384, true case bytes.Equal(a.OID, oidSHA512): return sha512.New, true } return nil, false } // ParseSignature reads the detached CMS signature of an author-signature of // alg 2 (spec §29.10), checking its form in the order of the spec. func ParseSignature(b []byte) (*SignedData, error) { return parse(b, false) } func parse(b []byte, token bool) (*SignedData, error) { if err := der.Check(b); err != nil { return nil, formErr("%v", err) } id, ci, err := der.Split(b) if err != nil || id != 0x30 || len(ci) != 2 || ci[1][0] != 0xa0 { return nil, formErr("a ContentInfo") } if ct, ok := oidOf(ci[0]); !ok || !bytes.Equal(ct, oidSignedData) { return nil, formErr("the content type is not id-signedData") } _, inner, err := der.Split(ci[1]) if err != nil || len(inner) != 1 || inner[0][0] != 0x30 { return nil, formErr("a SignedData") } _, sd, err := der.Split(inner[0]) if err != nil || len(sd) < 4 || sd[0][0] != 0x02 || sd[1][0] != 0x31 || sd[2][0] != 0x30 { return nil, formErr("a SignedData") } // digestAlgorithms: a SET OF in order. _, algs, err := der.Split(sd[1]) if err != nil || !der.SetOfSorted(algs) { return nil, formErr("digestAlgorithms is not a SET OF in DER order") } for _, a := range algs { if _, err := parseAlgID(a); err != nil { return nil, err } } out := &SignedData{} if err := parseEncap(sd[2], token, out); err != nil { return nil, err } rest := sd[3:] if len(rest) > 0 && rest[0][0] == 0xa0 { if err := parseCerts(rest[0], out); err != nil { return nil, err } rest = rest[1:] } if len(rest) > 0 && rest[0][0] == 0xa1 { if err := parseCRLs(rest[0], token, out); err != nil { return nil, err } rest = rest[1:] } if len(rest) != 1 || rest[0][0] != 0x31 { return nil, formErr("signerInfos") } _, infos, err := der.Split(rest[0]) if err != nil || len(infos) == 0 || !der.SetOfSorted(infos) { return nil, formErr("signerInfos is not a SET OF in DER order, or is empty") } if token && len(infos) != 1 { return nil, formErr("a token has one SignerInfo, not %d", len(infos)) } used := map[*Cert]bool{} for _, si := range infos { s, err := parseSignerInfo(si, out, token) if err != nil { return nil, err } if used[s.Cert] { return nil, formErr("two SignerInfo for one certificate") } used[s.Cert] = true out.Signers = append(out.Signers, s) } return out, nil } // parseEncap checks encapContentInfo: id-data without content in a detached // signature, and id-ct-TSTInfo with its content in a token. func parseEncap(b []byte, token bool, out *SignedData) error { _, kids, err := der.Split(b) if err != nil || len(kids) < 1 || len(kids) > 2 { return formErr("encapContentInfo") } ct, ok := oidOf(kids[0]) if !ok { return formErr("encapContentInfo") } if !token { if !bytes.Equal(ct, oidData) || len(kids) != 1 { return formErr("a signature is detached: id-data and no eContent") } return nil } if !bytes.Equal(ct, oidTSTInfo) || len(kids) != 2 || kids[1][0] != 0xa0 { return formErr("a token holds a TSTInfo") } _, e, err := der.Split(kids[1]) if err != nil || len(e) != 1 || e[0][0] != 0x04 { return formErr("eContent") } if out.EContent, err = der.Content(e[0]); err != nil { return formErr("eContent") } return nil } // parseCerts reads certificates. A certificate that breaks the profile of // §29.10 decides nothing, as one that no SignerInfo names: an intermediate of // another form is not a reason to refuse a signature, and the sid of a signer // whose certificate breaks it names none. Two copies of a certificate are one. func parseCerts(b []byte, out *SignedData) error { _, kids, err := der.Split(b) if err != nil || !der.SetOfSorted(kids) { return formErr("certificates is not a SET OF in DER order") } for i, k := range kids { if k[0] >= 0xa0 && k[0] <= 0xa3 { // another choice of CertificateChoices: it decides nothing continue } if k[0] != 0x30 { return formErr("a CertificateChoice that is neither a certificate nor one of the other four choices") } if i > 0 && bytes.Equal(kids[i-1], k) { continue } if c, err := ParseCert(k); err == nil { out.Certs = append(out.Certs, c) } } return nil } // parseCRLs reads crls: in a signature, only OCSP responses (spec §29.10 rule // 3); in a token, whatever it holds decides nothing (§29.11). func parseCRLs(b []byte, token bool, out *SignedData) error { _, kids, err := der.Split(b) if err != nil || !der.SetOfSorted(kids) { return formErr("crls is not a SET OF in DER order") } if token { return nil } for _, k := range kids { if k[0] != 0xa1 { return formErr("crls holds only OCSP responses") } _, f, err := der.Split(k) if err != nil || len(f) != 2 { return formErr("an OtherRevocationInfoFormat") } if o, ok := oidOf(f[0]); !ok || !bytes.Equal(o, oidRIOCSP) { return formErr("crls holds only OCSP responses") } out.OCSP = append(out.OCSP, f[1]) } return nil } func parseSignerInfo(b []byte, sd *SignedData, token bool) (*SignerInfo, error) { id, f, err := der.Split(b) if err != nil || id != 0x30 || len(f) < 6 || f[0][0] != 0x02 || f[2][0] != 0x30 || f[3][0] != 0xa0 || f[4][0] != 0x30 || f[5][0] != 0x04 { return nil, formErr("a SignerInfo with signedAttrs") } // RFC 5652 5.3: version 1 with issuerAndSerialNumber, version 3 with // subjectKeyIdentifier. if v, _ := der.Content(f[0]); !(len(v) == 1 && (v[0] == 1 && f[1][0] == 0x30 || v[0] == 3 && f[1][0] == 0x80)) { return nil, formErr("the version of a SignerInfo does not match its sid") } s := &SignerInfo{SignedAttrs: f[3]} if s.Cert, err = findSigner(f[1], sd.Certs); err != nil { return nil, err } if s.DigestAlg, err = parseAlgID(f[2]); err != nil { return nil, err } if s.SigAlg, err = parseAlgID(f[4]); err != nil { return nil, err } if s.Signature, err = der.Content(f[5]); err != nil { return nil, formErr("signature") } if len(f) > 7 || len(f) == 7 && f[6][0] != 0xa1 { return nil, formErr("a SignerInfo with something after its signature") } if err := parseSignedAttrs(s, token); err != nil { return nil, err } if len(f) == 7 { if err := parseUnsignedAttrs(s, f[6]); err != nil { return nil, err } } return s, nil } // findSigner returns the one certificate that the sid names, comparing the // DER of the issuer and the content of the serial number, or the // keyIdentifier. func findSigner(sid []byte, certs []*Cert) (*Cert, error) { var found *Cert n := 0 switch sid[0] { case 0x30: // issuerAndSerialNumber _, p, err := der.Split(sid) if err != nil || len(p) != 2 || p[0][0] != 0x30 || p[1][0] != 0x02 { return nil, formErr("issuerAndSerialNumber") } serial, _ := der.Content(p[1]) for _, c := range certs { if c.hasSID(p[0], serial) { found, n = c, n+1 } } case 0x80: // subjectKeyIdentifier ski, err := der.Content(sid) if err != nil { return nil, formErr("subjectKeyIdentifier") } for _, c := range certs { if c.SKI != nil && bytes.Equal(c.SKI, ski) { found, n = c, n+1 } } default: return nil, formErr("a SignerIdentifier") } if n != 1 { return nil, formErr("a sid that names %d certificates of the profile, not one", n) } return found, nil } // attrSet holds the attributes of a SET OF Attribute: the values of each type // and the number of attributes of each type, which is not the number of // values. Both are kept by the bytes of the object identifier. type attrSet struct { vals map[string][][]byte count map[string]int } func (a attrSet) get(o []byte) ([][]byte, int) { return a.vals[string(o)], a.count[string(o)] } // attrs reads the SET OF Attribute b. An attribute needs at least one value // (RFC 5652 5.3), so that two attributes of one type never hide behind an empty // set of values. func attrs(b []byte) (attrSet, error) { _, kids, err := der.Split(b) if err != nil || !der.SetOfSorted(kids) { return attrSet{}, formErr("attributes are not a SET OF in DER order") } out := attrSet{vals: map[string][][]byte{}, count: map[string]int{}} for _, a := range kids { _, p, err := der.Split(a) if err != nil || len(p) != 2 || a[0] != 0x30 || p[1][0] != 0x31 { return attrSet{}, formErr("an Attribute") } o, ok := oidOf(p[0]) if !ok { return attrSet{}, formErr("an Attribute") } _, vals, err := der.Split(p[1]) if err != nil || len(vals) == 0 || !der.SetOfSorted(vals) { return attrSet{}, formErr("the values of an attribute are not a non-empty SET OF in DER order") } out.vals[string(o)] = append(out.vals[string(o)], vals...) out.count[string(o)]++ } return out, nil } // one returns the only value of the only attribute of the type. func one(m attrSet, o []byte, name string) ([]byte, error) { v, n := m.get(o) if n != 1 || len(v) != 1 { return nil, formErr("%s: %d attributes with %d values, not one with one", name, n, len(v)) } return v[0], nil } // parseSignedAttrs checks the signedAttrs of the profile (spec §29.10 rule 4, // §29.11): content-type, message-digest and the signing certificate. func parseSignedAttrs(s *SignerInfo, token bool) error { m, err := attrs(s.SignedAttrs) if err != nil { return err } // Each of the three is one attribute with one value. ct, err := one(m, oidContentType, "content-type") if err != nil { return err } want, name := oidData, "id-data" if token { want, name = oidTSTInfo, "id-ct-TSTInfo" } if got, ok := oidOf(ct); !ok || !bytes.Equal(got, want) { return formErr("content-type is not %s", name) } md, err := one(m, oidMessageDig, "message-digest") if err != nil { return err } if md[0] != 0x04 { return formErr("message-digest is not an OCTET STRING") } if s.MessageDigest, err = der.Content(md); err != nil { return formErr("message-digest") } // signing-certificate-v2 is the one that counts: a signature has it, and a // token has it or, failing that, signing-certificate. The other attributes // decide nothing, a signing-certificate beside the v2 among them. v2, n2 := m.get(oidSigCertV2) v1, n1 := m.get(oidSigCertV1) switch { case n2 == 1 && len(v2) == 1: return checkESSCert(s.Cert, v2[0], true) case token && n2 == 0 && n1 == 1 && len(v1) == 1: return checkESSCert(s.Cert, v1[0], false) } return formErr("signing-certificate: one attribute of one value is required") } // checkESSCert checks that the first ESSCertID of a signing-certificate or // signing-certificate-v2 (RFC 2634, RFC 5035) is the hash of the certificate. func checkESSCert(c *Cert, v []byte, v2 bool) error { id, sc, err := der.Split(v) if err != nil || id != 0x30 || len(sc) < 1 || sc[0][0] != 0x30 { return formErr("a SigningCertificate") } _, ids, err := der.Split(sc[0]) if err != nil || len(ids) < 1 || ids[0][0] != 0x30 { return formErr("an ESSCertID") } _, f, err := der.Split(ids[0]) if err != nil || len(f) < 1 { return formErr("an ESSCertID") } newHash := sha1.New if v2 { newHash = sha256.New if f[0][0] == 0x30 { // hashAlgorithm, which defaults to SHA-256 a, err := parseAlgID(f[0]) if err != nil { return err } h, ok := a.hashOf() if !ok { return formErr("the hash of the ESSCertIDv2 is outside the table") } newHash, f = h, f[1:] } } if len(f) < 1 || f[0][0] != 0x04 { return formErr("certHash") } hv, err := der.Content(f[0]) if err != nil { return formErr("certHash") } h := newHash() h.Write(c.Raw) if !bytes.Equal(h.Sum(nil), hv) { return formErr("the certHash is not that of the certificate of the signer") } return nil } // parseUnsignedAttrs reads the signature-time-stamp, at most one with one // value (spec §29.10 rule 4); the other attributes decide nothing. func parseUnsignedAttrs(s *SignerInfo, b []byte) error { m, err := attrs(b) if err != nil { return err } switch v, n := m.get(oidSigTimeStamp); { case n == 0: case n == 1 && len(v) == 1: s.Token = v[0] default: return formErr("signature-time-stamp: %d attributes with %d values, not one with one", n, len(v)) } return nil }