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/cms.go

547 lines
16 KiB

// 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
}

Powered by TurnKey Linux.