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.

pkcs7.go 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. import (
  49. "crypto/x509"
  50. "crypto/x509/pkix"
  51. "encoding/asn1"
  52. "errors"
  53. cferr "github.com/cloudflare/cfssl/errors"
  54. )
  55. // Types used for asn1 Unmarshaling.
  56. type signedData struct {
  57. Version int
  58. DigestAlgorithms asn1.RawValue
  59. ContentInfo asn1.RawValue
  60. Certificates asn1.RawValue `asn1:"optional" asn1:"tag:0"`
  61. Crls asn1.RawValue `asn1:"optional"`
  62. SignerInfos asn1.RawValue
  63. }
  64. type initPKCS7 struct {
  65. Raw asn1.RawContent
  66. ContentType asn1.ObjectIdentifier
  67. Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
  68. }
  69. // Object identifier strings of the three implemented PKCS7 types.
  70. const (
  71. ObjIDData = "1.2.840.113549.1.7.1"
  72. ObjIDSignedData = "1.2.840.113549.1.7.2"
  73. ObjIDEncryptedData = "1.2.840.113549.1.7.6"
  74. )
  75. // PKCS7 represents the ASN1 PKCS #7 Content type. It contains one of three
  76. // possible types of Content objects, as denoted by the object identifier in
  77. // the ContentInfo field, the other two being nil. SignedData
  78. // is the degenerate SignedData Content info without signature used
  79. // to hold certificates and crls. Data is raw bytes, and EncryptedData
  80. // is as defined in PKCS #7 standard.
  81. type PKCS7 struct {
  82. Raw asn1.RawContent
  83. ContentInfo string
  84. Content Content
  85. }
  86. // Content implements three of the six possible PKCS7 data types. Only one is non-nil.
  87. type Content struct {
  88. Data []byte
  89. SignedData SignedData
  90. EncryptedData EncryptedData
  91. }
  92. // SignedData defines the typical carrier of certificates and crls.
  93. type SignedData struct {
  94. Raw asn1.RawContent
  95. Version int
  96. Certificates []*x509.Certificate
  97. Crl *pkix.CertificateList
  98. }
  99. // Data contains raw bytes. Used as a subtype in PKCS12.
  100. type Data struct {
  101. Bytes []byte
  102. }
  103. // EncryptedData contains encrypted data. Used as a subtype in PKCS12.
  104. type EncryptedData struct {
  105. Raw asn1.RawContent
  106. Version int
  107. EncryptedContentInfo EncryptedContentInfo
  108. }
  109. // EncryptedContentInfo is a subtype of PKCS7EncryptedData.
  110. type EncryptedContentInfo struct {
  111. Raw asn1.RawContent
  112. ContentType asn1.ObjectIdentifier
  113. ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
  114. EncryptedContent []byte `asn1:"tag:0,optional"`
  115. }
  116. // ParsePKCS7 attempts to parse the DER encoded bytes of a
  117. // PKCS7 structure.
  118. func ParsePKCS7(raw []byte) (msg *PKCS7, err error) {
  119. var pkcs7 initPKCS7
  120. _, err = asn1.Unmarshal(raw, &pkcs7)
  121. if err != nil {
  122. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
  123. }
  124. msg = new(PKCS7)
  125. msg.Raw = pkcs7.Raw
  126. msg.ContentInfo = pkcs7.ContentType.String()
  127. switch {
  128. case msg.ContentInfo == ObjIDData:
  129. msg.ContentInfo = "Data"
  130. _, err = asn1.Unmarshal(pkcs7.Content.Bytes, &msg.Content.Data)
  131. if err != nil {
  132. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
  133. }
  134. case msg.ContentInfo == ObjIDSignedData:
  135. msg.ContentInfo = "SignedData"
  136. var signedData signedData
  137. _, err = asn1.Unmarshal(pkcs7.Content.Bytes, &signedData)
  138. if err != nil {
  139. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
  140. }
  141. if len(signedData.Certificates.Bytes) != 0 {
  142. msg.Content.SignedData.Certificates, err = x509.ParseCertificates(signedData.Certificates.Bytes)
  143. if err != nil {
  144. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
  145. }
  146. }
  147. if len(signedData.Crls.Bytes) != 0 {
  148. msg.Content.SignedData.Crl, err = x509.ParseDERCRL(signedData.Crls.Bytes)
  149. if err != nil {
  150. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
  151. }
  152. }
  153. msg.Content.SignedData.Version = signedData.Version
  154. msg.Content.SignedData.Raw = pkcs7.Content.Bytes
  155. case msg.ContentInfo == ObjIDEncryptedData:
  156. msg.ContentInfo = "EncryptedData"
  157. var encryptedData EncryptedData
  158. _, err = asn1.Unmarshal(pkcs7.Content.Bytes, &encryptedData)
  159. if err != nil {
  160. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
  161. }
  162. if encryptedData.Version != 0 {
  163. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for PKCS #7 encryptedData version 0"))
  164. }
  165. msg.Content.EncryptedData = encryptedData
  166. default:
  167. 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"))
  168. }
  169. return msg, nil
  170. }