github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/smime/signeddata.go (about)

     1  package smime
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/x509"
     6  	"crypto/x509/pkix"
     7  	"encoding/asn1"
     8  	"errors"
     9  	"fmt"
    10  	"math/big"
    11  
    12  	"github.com/egonelbre/exp/smime/ber"
    13  )
    14  
    15  const panictodo = false
    16  
    17  type SignedData struct {
    18  	Version          int
    19  	DigestAlgorithms []pkix.AlgorithmIdentifier
    20  
    21  	ContentType asn1.ObjectIdentifier
    22  	Content     []byte
    23  
    24  	Certificates []*x509.Certificate
    25  	CRLs         []*pkix.CertificateList
    26  
    27  	Signers []*Signer
    28  }
    29  
    30  func (s *SignedData) findCertFor(signer *Signer) (*x509.Certificate, error) {
    31  	for _, cert := range s.Certificates {
    32  		if signer.Id.Matches(cert) {
    33  			return cert, nil
    34  		}
    35  	}
    36  	return nil, fmt.Errorf("did not find certificate for signer %v", s)
    37  }
    38  
    39  func (s *SignedData) CheckSignature() (err error) {
    40  	if len(s.Signers) == 0 {
    41  		return fmt.Errorf("no signature found")
    42  	}
    43  
    44  	for _, signer := range s.Signers {
    45  		var cert *x509.Certificate
    46  		if cert, err = s.findCertFor(signer); err != nil {
    47  			return
    48  		}
    49  
    50  		// check the revocation lists
    51  		revoked := false
    52  		for _, crl := range s.CRLs {
    53  			if revokeerr := cert.CheckCRLSignature(crl); revokeerr != nil {
    54  				revoked = true
    55  			}
    56  		}
    57  
    58  		if revoked {
    59  			if panictodo {
    60  				panic("TODO: check counter signature")
    61  			}
    62  			// return fmt.Errorf("smime: certificate has been revoked")
    63  		}
    64  
    65  		data := s.Content
    66  		if signer.RawSignedAttributes != nil {
    67  			var attrvalue []byte
    68  			if attrvalue, err = findSingleAttribute(signer.SignedAttributes, oidMessageDigest); err != nil {
    69  				return errors.New("smime: message digest not found")
    70  			}
    71  
    72  			var digest []byte
    73  
    74  			// the single message digest attribute should be OCTET STRING
    75  			if _, err = asn1.Unmarshal(attrvalue, &digest); err != nil {
    76  				return
    77  			}
    78  
    79  			calculated := data
    80  			if hash := getDigestHashType(signer.DigestAlgorithm.Algorithm); hash.Available() {
    81  				h := hash.New()
    82  				h.Write(data)
    83  				calculated = h.Sum(nil)
    84  			}
    85  
    86  			if !bytes.Equal(digest, calculated) {
    87  				return errors.New("smime: message digest does not match content")
    88  			}
    89  
    90  			data = signer.RawSignedAttributes
    91  		}
    92  
    93  		algo := getSignatureAlgorithmFromOID(signer.SignatureAlgorithm.Algorithm)
    94  		err = cert.CheckSignature(algo, data, signer.Signature)
    95  		if err != nil {
    96  			return
    97  		}
    98  	}
    99  	return
   100  }
   101  
   102  type Signer struct {
   103  	Id SignerId
   104  
   105  	RawSignedAttributes []byte
   106  	SignedAttributes    []Attribute
   107  	UnsignedAttributes  []Attribute
   108  
   109  	DigestAlgorithm    pkix.AlgorithmIdentifier
   110  	SignatureAlgorithm pkix.AlgorithmIdentifier
   111  
   112  	Signature []byte
   113  }
   114  
   115  // Either IssuerAndSerialNumber or SubjectKeyIdentifier
   116  type SignerId interface {
   117  	Matches(*x509.Certificate) bool
   118  }
   119  
   120  type IssuerAndSerialNumber struct {
   121  	Issuer       pkix.Name
   122  	SerialNumber *big.Int
   123  }
   124  
   125  func (sid IssuerAndSerialNumber) Matches(cert *x509.Certificate) bool {
   126  	if panictodo {
   127  		panic("issuer comparison")
   128  	}
   129  	return (sid.Issuer.CommonName == cert.Issuer.CommonName) &&
   130  		(sid.SerialNumber.Cmp(cert.SerialNumber) == 0)
   131  }
   132  
   133  type SubjectKeyIdentifier []byte
   134  
   135  func (sid SubjectKeyIdentifier) Matches(cert *x509.Certificate) bool {
   136  	return bytes.Equal(cert.SubjectKeyId, sid)
   137  }
   138  
   139  type Attribute struct {
   140  	Type   asn1.ObjectIdentifier
   141  	Values [][]byte
   142  }
   143  
   144  func findSingleAttribute(attributes []Attribute, oid asn1.ObjectIdentifier) ([]byte, error) {
   145  	for _, attr := range attributes {
   146  		if attr.Type.Equal(oid) {
   147  			if len(attr.Values) != 1 {
   148  				return nil, errors.New("smime: attribute had improper amount of values")
   149  			}
   150  			return attr.Values[0], nil
   151  		}
   152  	}
   153  	return nil, errors.New("smime: did not find required attribute")
   154  }
   155  
   156  func convertAttributeSet(attrs asnAttributeSet) (ret []Attribute) {
   157  	for _, attr := range attrs.Attrs {
   158  		a := Attribute{attr.Type, nil}
   159  		for _, val := range attr.Values {
   160  			data, _ := ber.EncodeTree(val)
   161  			a.Values = append(a.Values, data)
   162  		}
   163  		ret = append(ret, a)
   164  	}
   165  	return
   166  }
   167  
   168  /*
   169  	SignedData ::= SEQUENCE {
   170  		version CMSVersion,
   171  		digestAlgorithms DigestAlgorithmIdentifiers,
   172  		encapContentInfo EncapsulatedContentInfo,
   173  		certificates [0] IMPLICIT CertificateSet OPTIONAL,
   174  		crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
   175  		signerInfos SignerInfos }
   176  
   177  	SignerInfos ::= SET OF SignerInfo
   178  */
   179  type asnSignedData struct {
   180  	Version      int64
   181  	Algorithms   asnDigestAlgorithms
   182  	EncapContent asnEncapsulatedContentInfo
   183  	Certificates asnCertificateSet
   184  	Crls         asnRevocationInfoChoices
   185  	SignerInfos  asnSignerInfos
   186  }
   187  
   188  type crl struct{}
   189  
   190  func (d *asnSignedData) marshaler() ber.Marshaler {
   191  	return ber.Sequence{
   192  		ber.Check{ber.Universal, ber.TagInteger, ber.Int64{&d.Version}},
   193  		ber.Check{ber.Universal, ber.TagSet, &d.Algorithms},
   194  		ber.Check{ber.Universal, ber.TagSequence, &d.EncapContent},
   195  		ber.Optional{ber.Check{ber.Context, 0, &d.Certificates}},
   196  		ber.Optional{ber.Check{ber.Context, 1, &d.Crls}},
   197  		ber.Check{ber.Universal, ber.TagSet, &d.SignerInfos},
   198  	}
   199  }
   200  
   201  func (d *asnSignedData) Unmarshal(tree *ber.Tree) error {
   202  	return d.marshaler().Unmarshal(tree)
   203  }
   204  
   205  func (d *asnSignedData) Marshal() (*ber.Tree, error) {
   206  	return d.marshaler().Marshal()
   207  }
   208  
   209  func parseSignedData(tree *ber.Tree) (*SignedData, error) {
   210  	var data asnSignedData
   211  	err := data.Unmarshal(tree)
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  
   216  	signeddata := &SignedData{
   217  		Version:          int(data.Version),
   218  		DigestAlgorithms: data.Algorithms,
   219  
   220  		ContentType: data.EncapContent.ContentType,
   221  		Content:     data.EncapContent.Data,
   222  
   223  		Certificates: data.Certificates,
   224  		CRLs:         data.Crls,
   225  	}
   226  
   227  	for _, si := range data.SignerInfos {
   228  		var sid SignerId
   229  		if si.Issuer.SerialNumber != nil {
   230  			sid = IssuerAndSerialNumber{si.Issuer.Issuer, si.Issuer.SerialNumber}
   231  		} else {
   232  			sid = SubjectKeyIdentifier(si.SubjectKeyId)
   233  		}
   234  
   235  		signer := &Signer{
   236  			Id: sid,
   237  
   238  			RawSignedAttributes: si.SignedAttrs.Raw,
   239  			SignedAttributes:    convertAttributeSet(si.SignedAttrs),
   240  			UnsignedAttributes:  convertAttributeSet(si.UnsignedAttrs),
   241  
   242  			DigestAlgorithm:    si.DigestAlgorithm,
   243  			SignatureAlgorithm: si.SignatureAlgorithm,
   244  			Signature:          si.Signature,
   245  		}
   246  		signeddata.Signers = append(signeddata.Signers, signer)
   247  	}
   248  
   249  	return signeddata, nil
   250  }
   251  
   252  /*
   253  	EncapsulatedContentInfo ::= SEQUENCE {
   254  		eContentType ContentType,
   255  		eContent [0] EXPLICIT OCTET STRING OPTIONAL }
   256  
   257  	ContentType ::= OBJECT IDENTIFIER
   258  */
   259  type asnEncapsulatedContentInfo struct {
   260  	ContentType asn1.ObjectIdentifier
   261  	Data        []byte
   262  }
   263  
   264  func (d *asnEncapsulatedContentInfo) marshaler() ber.Marshaler {
   265  	return ber.Sequence{
   266  		ber.Check{ber.Universal, ber.TagObjectIdentifier, ber.ObjectIdentifier{&d.ContentType}},
   267  		ber.Optional{ber.Check{ber.Context, 0,
   268  			ber.Explicit{
   269  				ber.Check{ber.Universal, ber.TagOctetString, ber.OctetString{&d.Data}},
   270  			},
   271  		}},
   272  	}
   273  }
   274  
   275  func (d *asnEncapsulatedContentInfo) Unmarshal(tree *ber.Tree) error {
   276  	return d.marshaler().Unmarshal(tree)
   277  }
   278  
   279  func (d *asnEncapsulatedContentInfo) Marshal() (*ber.Tree, error) {
   280  	return d.marshaler().Marshal()
   281  }
   282  
   283  /*
   284  	DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
   285  	DigestAlgorithmIdentifier ::= AlgorithmIdentifier
   286  */
   287  type asnDigestAlgorithms []pkix.AlgorithmIdentifier
   288  
   289  func (d *asnDigestAlgorithms) Unmarshal(tree *ber.Tree) (err error) {
   290  	algorithms := make([]pkix.AlgorithmIdentifier, len(tree.Children))
   291  
   292  	for i, child := range tree.Children {
   293  		id := (*asnAlgorithmIdentifier)(&algorithms[i])
   294  		if err = id.Unmarshal(child); err != nil {
   295  			return
   296  		}
   297  	}
   298  	*d = algorithms
   299  	return
   300  }
   301  
   302  func (d *asnDigestAlgorithms) Marshal() (tree *ber.Tree, err error) {
   303  	if tree, err = ber.ASN1Tree(d); err != nil {
   304  		return
   305  	}
   306  	tree.Tag = ber.TagSet
   307  	return tree, err
   308  }
   309  
   310  /*
   311     AlgorithmIdentifier ::= SEQUENCE {
   312          algorithm          OBJECT IDENTIFIER,
   313          parameters         ANY
   314     }
   315  */
   316  type asnAlgorithmIdentifier pkix.AlgorithmIdentifier
   317  
   318  func (d *asnAlgorithmIdentifier) Unmarshal(tree *ber.Tree) error {
   319  	return ber.Sequence{
   320  		ber.Check{ber.Universal, ber.TagObjectIdentifier, ber.ObjectIdentifier{&d.Algorithm}},
   321  		ber.Optional{ber.ASN1RawValue{&d.Parameters}},
   322  	}.Unmarshal(tree)
   323  }
   324  
   325  func (d *asnAlgorithmIdentifier) Marshal() (*ber.Tree, error) {
   326  	panic("unimplemented")
   327  	return nil, nil
   328  }
   329  
   330  /*
   331  CertificateSet	::=	 SET OF CertificateChoices
   332  CertificateChoices	::=	CHOICE {
   333  	certificate	Certificate,
   334  	extendedCertificate	[0] IMPLICIT ExtendedCertificate, -- Obsolete
   335  	v1AttrCert	 	[1] IMPLICIT AttributeCertificateV1, -- Obsolete
   336  	v2AttrCert	 	[2] IMPLICIT AttributeCertificateV2,
   337  	other	 		[3] IMPLICIT OtherCertificateFormat
   338  }
   339  AttributeCertificateV2	::=	 SET OF AttributeCertificate
   340  OtherCertificateFormat	::=	SEQUENCE {
   341  	otherCertFormat	 OBJECT IDENTIFIER,
   342  	otherCert	 ANY DEFINED BY otherCertFormat
   343  }
   344  */
   345  type asnCertificateSet []*x509.Certificate
   346  
   347  func (d *asnCertificateSet) Unmarshal(tree *ber.Tree) (err error) {
   348  	var cert *x509.Certificate
   349  	var bytes []byte
   350  
   351  	ret := make([]*x509.Certificate, 0, len(tree.Children))
   352  
   353  	for _, child := range tree.Children {
   354  		if bytes, err = ber.EncodeTree(child); err != nil {
   355  			return
   356  		}
   357  		if cert, err = x509.ParseCertificate(bytes); err != nil {
   358  			return
   359  		}
   360  		ret = append(ret, cert)
   361  	}
   362  	*d = ret
   363  	return
   364  }
   365  
   366  func (d *asnCertificateSet) Marshal() (tree *ber.Tree, err error) {
   367  	tree = &ber.Tree{
   368  		Token: &ber.Token{
   369  			Kind:  ber.Constructed,
   370  			Class: ber.Universal,
   371  			Tag:   ber.TagSet,
   372  		},
   373  	}
   374  
   375  	var sub *ber.Tree
   376  	for _, cert := range *d {
   377  		if sub, err = ber.DecodeTree(cert.Raw); err != nil {
   378  			return nil, err
   379  		}
   380  		tree.Children = append(tree.Children, sub)
   381  	}
   382  	return
   383  }
   384  
   385  /*
   386     RevocationInfoChoices ::= SET OF RevocationInfoChoice
   387  
   388     RevocationInfoChoice ::= CHOICE {
   389       crl CertificateList,
   390       other [1] IMPLICIT OtherRevocationInfoFormat }
   391  
   392     OtherRevocationInfoFormat ::= SEQUENCE {
   393       otherRevInfoFormat OBJECT IDENTIFIER,
   394       otherRevInfo ANY DEFINED BY otherRevInfoFormat }
   395  */
   396  type asnRevocationInfoChoices []*pkix.CertificateList
   397  
   398  func (d *asnRevocationInfoChoices) Unmarshal(tree *ber.Tree) (err error) {
   399  	var crl *pkix.CertificateList
   400  	var bytes []byte
   401  
   402  	ret := make([]*pkix.CertificateList, 0, len(tree.Children))
   403  	for _, child := range tree.Children {
   404  		if bytes, err = ber.EncodeTree(child); err != nil {
   405  			return
   406  		}
   407  
   408  		if crl, err = x509.ParseCRL(bytes); err != nil {
   409  			return
   410  		}
   411  		ret = append(ret, crl)
   412  	}
   413  	*d = ret
   414  	return
   415  }
   416  
   417  func (d *asnRevocationInfoChoices) Marshal() (tree *ber.Tree, err error) {
   418  	return ber.ASN1Tree(*d)
   419  }
   420  
   421  /*
   422    SignerInfos ::= SET OF SignerInfo
   423  */
   424  type asnSignerInfos []*asnSignerInfo
   425  
   426  func (d *asnSignerInfos) Unmarshal(tree *ber.Tree) (err error) {
   427  	ret := make([]*asnSignerInfo, len(tree.Children))
   428  	for i, child := range tree.Children {
   429  		v := &asnSignerInfo{}
   430  		if err = v.Unmarshal(child); err != nil {
   431  			return
   432  		}
   433  		ret[i] = v
   434  	}
   435  	*d = ret
   436  	return
   437  }
   438  
   439  func (d *asnSignerInfos) Marshal() (tree *ber.Tree, err error) {
   440  	tree = &ber.Tree{
   441  		Token: &ber.Token{
   442  			Kind:  ber.Constructed,
   443  			Class: ber.Universal,
   444  			Tag:   ber.TagSet,
   445  		},
   446  	}
   447  
   448  	var sub *ber.Tree
   449  	for _, info := range *d {
   450  		if sub, err = info.Marshal(); err != nil {
   451  			return
   452  		}
   453  		tree.Children = append(tree.Children, sub)
   454  	}
   455  
   456  	return
   457  }
   458  
   459  /*
   460  
   461    SignerInfo ::= SEQUENCE {
   462       version CMSVersion,
   463       sid SignerIdentifier,
   464       digestAlgorithm DigestAlgorithmIdentifier,
   465       signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
   466       signatureAlgorithm SignatureAlgorithmIdentifier,
   467       signature SignatureValue,
   468       unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
   469  
   470     SignerIdentifier ::= CHOICE {
   471       issuerAndSerialNumber IssuerAndSerialNumber,
   472       subjectKeyIdentifier [0] SubjectKeyIdentifier }
   473  
   474     SignatureValue ::= OCTET STRING
   475  */
   476  type asnSignerInfo struct {
   477  	Version            int64
   478  	Issuer             asnIssuerAndSerialNumber
   479  	SubjectKeyId       []byte
   480  	DigestAlgorithm    pkix.AlgorithmIdentifier
   481  	SignedAttrs        asnAttributeSet
   482  	SignatureAlgorithm pkix.AlgorithmIdentifier
   483  	Signature          []byte
   484  	UnsignedAttrs      asnAttributeSet
   485  }
   486  
   487  func (d *asnSignerInfo) marshaler() ber.Marshaler {
   488  	return ber.Sequence{
   489  		ber.Check{ber.Universal, ber.TagInteger, ber.Int64{&d.Version}},
   490  		ber.Choice{
   491  			ber.Check{ber.Universal, ber.TagSequence, &d.Issuer},
   492  			ber.Check{ber.Context, 0, ber.OctetString{&d.SubjectKeyId}},
   493  		},
   494  		ber.Check{ber.Universal, ber.TagSequence, (*asnAlgorithmIdentifier)(&d.DigestAlgorithm)},
   495  		ber.Optional{ber.Check{ber.Context, 0, &d.SignedAttrs}},
   496  		ber.Check{ber.Universal, ber.TagSequence, (*asnAlgorithmIdentifier)(&d.SignatureAlgorithm)},
   497  		ber.Check{ber.Universal, ber.TagOctetString, ber.OctetString{&d.Signature}},
   498  		ber.Optional{ber.Check{ber.Context, 1, &d.UnsignedAttrs}},
   499  	}
   500  }
   501  
   502  func (d *asnSignerInfo) Unmarshal(tree *ber.Tree) error {
   503  	return d.marshaler().Unmarshal(tree)
   504  }
   505  
   506  func (d *asnSignerInfo) Marshal() (*ber.Tree, error) {
   507  	return d.marshaler().Marshal()
   508  }
   509  
   510  /*
   511    IssuerAndSerialNumber ::= SEQUENCE {
   512      issuer Name,
   513      serialNumber CertificateSerialNumber }
   514  
   515    CertificateSerialNumber ::= INTEGER
   516  */
   517  type asnIssuerAndSerialNumber struct {
   518  	Issuer       pkix.Name
   519  	SerialNumber *big.Int
   520  }
   521  
   522  func (d *asnIssuerAndSerialNumber) marshaler() ber.Marshaler {
   523  	return ber.Sequence{
   524  		ber.Check{ber.Universal, ber.TagSequence, (*asnName)(&d.Issuer)},
   525  		ber.Check{ber.Universal, ber.TagInteger, ber.BigInt{&d.SerialNumber}},
   526  	}
   527  }
   528  
   529  func (d *asnIssuerAndSerialNumber) Unmarshal(tree *ber.Tree) (err error) {
   530  	return d.marshaler().Unmarshal(tree)
   531  }
   532  
   533  func (d *asnIssuerAndSerialNumber) Marshal() (*ber.Tree, error) {
   534  	return d.marshaler().Marshal()
   535  }
   536  
   537  type asnName pkix.Name
   538  
   539  func (d *asnName) Unmarshal(tree *ber.Tree) (err error) {
   540  	var bytes []byte
   541  	if bytes, err = ber.EncodeTree(tree); err != nil {
   542  		return
   543  	}
   544  
   545  	var rdns pkix.RDNSequence
   546  	if _, err = asn1.Unmarshal(bytes, &rdns); err != nil {
   547  		return
   548  	}
   549  	(*pkix.Name)(d).FillFromRDNSequence(&rdns)
   550  
   551  	return
   552  }
   553  
   554  func (d *asnName) Marshal() (*ber.Tree, error) {
   555  	panic("unimplemented")
   556  	return nil, nil
   557  }
   558  
   559  type asnAttributeSet struct {
   560  	Raw   []byte
   561  	Attrs []asnAttribute
   562  }
   563  
   564  func (d *asnAttributeSet) Unmarshal(tree *ber.Tree) (err error) {
   565  	ret := make([]asnAttribute, len(tree.Children))
   566  	for i, child := range tree.Children {
   567  		err = (&ret[i]).Unmarshal(child)
   568  		if err != nil {
   569  			return
   570  		}
   571  	}
   572  
   573  	d.Attrs = ret
   574  	temp := &ber.Tree{
   575  		Token: &ber.Token{
   576  			Kind:  ber.Constructed,
   577  			Class: ber.Universal,
   578  			Tag:   ber.TagSet,
   579  		},
   580  		Children: tree.Children,
   581  	}
   582  	d.Raw, err = ber.EncodeTree(temp)
   583  	return
   584  }
   585  
   586  func (d *asnAttributeSet) Marshal() (*ber.Tree, error) {
   587  	panic("unimplemented")
   588  	return nil, nil
   589  }
   590  
   591  type asnAttribute struct {
   592  	Type   asn1.ObjectIdentifier
   593  	Values []*ber.Tree
   594  }
   595  
   596  func (d *asnAttribute) Unmarshal(tree *ber.Tree) (err error) {
   597  	var temp *ber.Tree
   598  
   599  	err = ber.Sequence{
   600  		ber.Check{ber.Universal, ber.TagObjectIdentifier, ber.ObjectIdentifier{&d.Type}},
   601  		ber.Check{ber.Universal, ber.TagSet, ber.RawTree{&temp}},
   602  	}.Unmarshal(tree)
   603  
   604  	if err != nil {
   605  		return
   606  	}
   607  
   608  	d.Values = temp.Children
   609  	return
   610  }
   611  
   612  func (d *asnAttribute) Marshal() (*ber.Tree, error) {
   613  	panic("unimplemented")
   614  	return nil, nil
   615  }