github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/cloudflare/cfssl/crypto/pkcs7/pkcs7.go (about)

     1  // Package pkcs7 implements the subset of the CMS PKCS #7 datatype that is typically
     2  // used to package certificates and CRLs.  Using openssl, every certificate converted
     3  // to PKCS #7 format from another encoding such as PEM conforms to this implementation.
     4  // reference: https://www.openssl.org/docs/man1.1.0/apps/crl2pkcs7.html
     5  //
     6  //			PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315
     7  //
     8  // The full pkcs#7 cryptographic message syntax allows for cryptographic enhancements,
     9  // for example data can be encrypted and signed and then packaged through pkcs#7 to be
    10  // sent over a network and then verified and decrypted.  It is asn1, and the type of
    11  // PKCS #7 ContentInfo, which comprises the PKCS #7 structure, is:
    12  //
    13  //			ContentInfo ::= SEQUENCE {
    14  //				contentType ContentType,
    15  //				content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
    16  //			}
    17  //
    18  // There are 6 possible ContentTypes, data, signedData, envelopedData,
    19  // signedAndEnvelopedData, digestedData, and encryptedData.  Here signedData, Data, and encrypted
    20  // Data are implemented, as the degenerate case of signedData without a signature is the typical
    21  // format for transferring certificates and CRLS, and Data and encryptedData are used in PKCS #12
    22  // formats.
    23  // The ContentType signedData has the form:
    24  //
    25  //
    26  //			signedData ::= SEQUENCE {
    27  //				version Version,
    28  //				digestAlgorithms DigestAlgorithmIdentifiers,
    29  //				contentInfo ContentInfo,
    30  //				certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL
    31  //				crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
    32  //				signerInfos SignerInfos
    33  //			}
    34  //
    35  // As of yet signerInfos and digestAlgorithms are not parsed, as they are not relevant to
    36  // this system's use of PKCS #7 data.  Version is an integer type, note that PKCS #7 is
    37  // recursive, this second layer of ContentInfo is similar ignored for our degenerate
    38  // usage.  The ExtendedCertificatesAndCertificates type consists of a sequence of choices
    39  // between PKCS #6 extended certificates and x509 certificates.  Any sequence consisting
    40  // of any number of extended certificates is not yet supported in this implementation.
    41  //
    42  // The ContentType Data is simply a raw octet string and is parsed directly into a Go []byte slice.
    43  //
    44  // The ContentType encryptedData is the most complicated and its form can be gathered by
    45  // the go type below.  It essentially contains a raw octet string of encrypted data and an
    46  // algorithm identifier for use in decrypting this data.
    47  package pkcs7
    48  
    49  import (
    50  	"encoding/asn1"
    51  	"errors"
    52  	"github.com/hellobchain/newcryptosm/x509"
    53  	"github.com/hellobchain/newcryptosm/x509/pkix"
    54  
    55  	cferr "github.com/hellobchain/third_party/cloudflare/cfssl/errors"
    56  )
    57  
    58  // Types used for asn1 Unmarshaling.
    59  
    60  type signedData struct {
    61  	Version          int
    62  	DigestAlgorithms asn1.RawValue
    63  	ContentInfo      asn1.RawValue
    64  	Certificates     asn1.RawValue `asn1:"optional" asn1:"tag:0"`
    65  	Crls             asn1.RawValue `asn1:"optional"`
    66  	SignerInfos      asn1.RawValue
    67  }
    68  
    69  type initPKCS7 struct {
    70  	Raw         asn1.RawContent
    71  	ContentType asn1.ObjectIdentifier
    72  	Content     asn1.RawValue `asn1:"tag:0,explicit,optional"`
    73  }
    74  
    75  // Object identifier strings of the three implemented PKCS7 types.
    76  const (
    77  	ObjIDData          = "1.2.840.113549.1.7.1"
    78  	ObjIDSignedData    = "1.2.840.113549.1.7.2"
    79  	ObjIDEncryptedData = "1.2.840.113549.1.7.6"
    80  )
    81  
    82  // PKCS7 represents the ASN1 PKCS #7 Content type.  It contains one of three
    83  // possible types of Content objects, as denoted by the object identifier in
    84  // the ContentInfo field, the other two being nil.  SignedData
    85  // is the degenerate SignedData Content info without signature used
    86  // to hold certificates and crls.  Data is raw bytes, and EncryptedData
    87  // is as defined in PKCS #7 standard.
    88  type PKCS7 struct {
    89  	Raw         asn1.RawContent
    90  	ContentInfo string
    91  	Content     Content
    92  }
    93  
    94  // Content implements three of the six possible PKCS7 data types.  Only one is non-nil.
    95  type Content struct {
    96  	Data          []byte
    97  	SignedData    SignedData
    98  	EncryptedData EncryptedData
    99  }
   100  
   101  // SignedData defines the typical carrier of certificates and crls.
   102  type SignedData struct {
   103  	Raw          asn1.RawContent
   104  	Version      int
   105  	Certificates []*x509.Certificate
   106  	Crl          *pkix.CertificateList
   107  }
   108  
   109  // Data contains raw bytes.  Used as a subtype in PKCS12.
   110  type Data struct {
   111  	Bytes []byte
   112  }
   113  
   114  // EncryptedData contains encrypted data.  Used as a subtype in PKCS12.
   115  type EncryptedData struct {
   116  	Raw                  asn1.RawContent
   117  	Version              int
   118  	EncryptedContentInfo EncryptedContentInfo
   119  }
   120  
   121  // EncryptedContentInfo is a subtype of PKCS7EncryptedData.
   122  type EncryptedContentInfo struct {
   123  	Raw                        asn1.RawContent
   124  	ContentType                asn1.ObjectIdentifier
   125  	ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
   126  	EncryptedContent           []byte `asn1:"tag:0,optional"`
   127  }
   128  
   129  // ParsePKCS7 attempts to parse the DER encoded bytes of a
   130  // PKCS7 structure.
   131  func ParsePKCS7(raw []byte) (msg *PKCS7, err error) {
   132  
   133  	var pkcs7 initPKCS7
   134  	_, err = asn1.Unmarshal(raw, &pkcs7)
   135  	if err != nil {
   136  		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   137  	}
   138  
   139  	msg = new(PKCS7)
   140  	msg.Raw = pkcs7.Raw
   141  	msg.ContentInfo = pkcs7.ContentType.String()
   142  	switch {
   143  	case msg.ContentInfo == ObjIDData:
   144  		msg.ContentInfo = "Data"
   145  		_, err = asn1.Unmarshal(pkcs7.Content.Bytes, &msg.Content.Data)
   146  		if err != nil {
   147  			return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   148  		}
   149  	case msg.ContentInfo == ObjIDSignedData:
   150  		msg.ContentInfo = "SignedData"
   151  		var signedData signedData
   152  		_, err = asn1.Unmarshal(pkcs7.Content.Bytes, &signedData)
   153  		if err != nil {
   154  			return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   155  		}
   156  		if len(signedData.Certificates.Bytes) != 0 {
   157  			msg.Content.SignedData.Certificates, err = x509.ParseCertificates(signedData.Certificates.Bytes)
   158  			if err != nil {
   159  				return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   160  			}
   161  		}
   162  		if len(signedData.Crls.Bytes) != 0 {
   163  			msg.Content.SignedData.Crl, err = x509.ParseDERCRL(signedData.Crls.Bytes)
   164  			if err != nil {
   165  				return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   166  			}
   167  		}
   168  		msg.Content.SignedData.Version = signedData.Version
   169  		msg.Content.SignedData.Raw = pkcs7.Content.Bytes
   170  	case msg.ContentInfo == ObjIDEncryptedData:
   171  		msg.ContentInfo = "EncryptedData"
   172  		var encryptedData EncryptedData
   173  		_, err = asn1.Unmarshal(pkcs7.Content.Bytes, &encryptedData)
   174  		if err != nil {
   175  			return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   176  		}
   177  		if encryptedData.Version != 0 {
   178  			return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for PKCS #7 encryptedData version 0"))
   179  		}
   180  		msg.Content.EncryptedData = encryptedData
   181  
   182  	default:
   183  		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Attempt to parse PKCS# 7 Content not of type data, signed data or encrypted data"))
   184  	}
   185  
   186  	return msg, nil
   187  
   188  }