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 }