1// Package pkcs7 implements parsing and generation of some PKCS#7 structures.
2package pkcs7
3
4import (
5	"bytes"
6	"crypto"
7	"crypto/aes"
8	"crypto/cipher"
9	"crypto/des"
10	"crypto/hmac"
11	"crypto/rand"
12	"crypto/rsa"
13	"crypto/x509"
14	"crypto/x509/pkix"
15	"encoding/asn1"
16	"errors"
17	"fmt"
18	"math/big"
19	"sort"
20	"time"
21
22	_ "crypto/sha1" // for crypto.SHA1
23)
24
25// PKCS7 Represents a PKCS7 structure
26type PKCS7 struct {
27	Content      []byte
28	Certificates []*x509.Certificate
29	CRLs         []pkix.CertificateList
30	Signers      []signerInfo
31	raw          interface{}
32}
33
34type contentInfo struct {
35	ContentType asn1.ObjectIdentifier
36	Content     asn1.RawValue `asn1:"explicit,optional,tag:0"`
37}
38
39// ErrUnsupportedContentType is returned when a PKCS7 content is not supported.
40// Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2),
41// and Enveloped Data are supported (1.2.840.113549.1.7.3)
42var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")
43
44type unsignedData []byte
45
46var (
47	oidData                   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
48	oidSignedData             = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
49	oidEnvelopedData          = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3}
50	oidSignedAndEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 4}
51	oidDigestedData           = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 5}
52	oidEncryptedData          = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}
53	oidAttributeContentType   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3}
54	oidAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4}
55	oidAttributeSigningTime   = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5}
56)
57
58type signedData struct {
59	Version                    int                        `asn1:"default:1"`
60	DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"`
61	ContentInfo                contentInfo
62	Certificates               rawCertificates        `asn1:"optional,tag:0"`
63	CRLs                       []pkix.CertificateList `asn1:"optional,tag:1"`
64	SignerInfos                []signerInfo           `asn1:"set"`
65}
66
67type rawCertificates struct {
68	Raw asn1.RawContent
69}
70
71type envelopedData struct {
72	Version              int
73	RecipientInfos       []recipientInfo `asn1:"set"`
74	EncryptedContentInfo encryptedContentInfo
75}
76
77type recipientInfo struct {
78	Version                int
79	IssuerAndSerialNumber  issuerAndSerial
80	KeyEncryptionAlgorithm pkix.AlgorithmIdentifier
81	EncryptedKey           []byte
82}
83
84type encryptedContentInfo struct {
85	ContentType                asn1.ObjectIdentifier
86	ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
87	EncryptedContent           asn1.RawValue `asn1:"tag:0,optional"`
88}
89
90type attribute struct {
91	Type  asn1.ObjectIdentifier
92	Value asn1.RawValue `asn1:"set"`
93}
94
95type issuerAndSerial struct {
96	IssuerName   asn1.RawValue
97	SerialNumber *big.Int
98}
99
100// MessageDigestMismatchError is returned when the signer data digest does not
101// match the computed digest for the contained content
102type MessageDigestMismatchError struct {
103	ExpectedDigest []byte
104	ActualDigest   []byte
105}
106
107func (err *MessageDigestMismatchError) Error() string {
108	return fmt.Sprintf("pkcs7: Message digest mismatch\n\tExpected: %X\n\tActual  : %X", err.ExpectedDigest, err.ActualDigest)
109}
110
111type signerInfo struct {
112	Version                   int `asn1:"default:1"`
113	IssuerAndSerialNumber     issuerAndSerial
114	DigestAlgorithm           pkix.AlgorithmIdentifier
115	AuthenticatedAttributes   []attribute `asn1:"optional,tag:0"`
116	DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
117	EncryptedDigest           []byte
118	UnauthenticatedAttributes []attribute `asn1:"optional,tag:1"`
119}
120
121// Parse decodes a DER encoded PKCS7 package
122func Parse(data []byte) (p7 *PKCS7, err error) {
123	if len(data) == 0 {
124		return nil, errors.New("pkcs7: input data is empty")
125	}
126	var info contentInfo
127	der, err := ber2der(data)
128	if err != nil {
129		return nil, err
130	}
131	rest, err := asn1.Unmarshal(der, &info)
132	if len(rest) > 0 {
133		err = asn1.SyntaxError{Msg: "trailing data"}
134		return
135	}
136	if err != nil {
137		return
138	}
139
140	// fmt.Printf("--> Content Type: %s", info.ContentType)
141	switch {
142	case info.ContentType.Equal(oidSignedData):
143		return parseSignedData(info.Content.Bytes)
144	case info.ContentType.Equal(oidEnvelopedData):
145		return parseEnvelopedData(info.Content.Bytes)
146	}
147	return nil, ErrUnsupportedContentType
148}
149
150func parseSignedData(data []byte) (*PKCS7, error) {
151	var sd signedData
152	asn1.Unmarshal(data, &sd)
153	certs, err := sd.Certificates.Parse()
154	if err != nil {
155		return nil, err
156	}
157	// fmt.Printf("--> Signed Data Version %d\n", sd.Version)
158
159	var compound asn1.RawValue
160	var content unsignedData
161
162	// The Content.Bytes maybe empty on PKI responses.
163	if len(sd.ContentInfo.Content.Bytes) > 0 {
164		if _, err := asn1.Unmarshal(sd.ContentInfo.Content.Bytes, &compound); err != nil {
165			return nil, err
166		}
167	}
168	// Compound octet string
169	if compound.IsCompound {
170		if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil {
171			return nil, err
172		}
173	} else {
174		// assuming this is tag 04
175		content = compound.Bytes
176	}
177	return &PKCS7{
178		Content:      content,
179		Certificates: certs,
180		CRLs:         sd.CRLs,
181		Signers:      sd.SignerInfos,
182		raw:          sd}, nil
183}
184
185func (raw rawCertificates) Parse() ([]*x509.Certificate, error) {
186	if len(raw.Raw) == 0 {
187		return nil, nil
188	}
189
190	var val asn1.RawValue
191	if _, err := asn1.Unmarshal(raw.Raw, &val); err != nil {
192		return nil, err
193	}
194
195	return x509.ParseCertificates(val.Bytes)
196}
197
198func parseEnvelopedData(data []byte) (*PKCS7, error) {
199	var ed envelopedData
200	if _, err := asn1.Unmarshal(data, &ed); err != nil {
201		return nil, err
202	}
203	return &PKCS7{
204		raw: ed,
205	}, nil
206}
207
208// Verify checks the signatures of a PKCS7 object
209// WARNING: Verify does not check signing time or verify certificate chains at
210// this time.
211func (p7 *PKCS7) Verify() (err error) {
212	if len(p7.Signers) == 0 {
213		return errors.New("pkcs7: Message has no signers")
214	}
215	for _, signer := range p7.Signers {
216		if err := verifySignature(p7, signer); err != nil {
217			return err
218		}
219	}
220	return nil
221}
222
223func verifySignature(p7 *PKCS7, signer signerInfo) error {
224	signedData := p7.Content
225	hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
226	if err != nil {
227		return err
228	}
229	if len(signer.AuthenticatedAttributes) > 0 {
230		// TODO(fullsailor): First check the content type match
231		var digest []byte
232		err := unmarshalAttribute(signer.AuthenticatedAttributes, oidAttributeMessageDigest, &digest)
233		if err != nil {
234			return err
235		}
236		h := hash.New()
237		h.Write(p7.Content)
238		computed := h.Sum(nil)
239		if !hmac.Equal(digest, computed) {
240			return &MessageDigestMismatchError{
241				ExpectedDigest: digest,
242				ActualDigest:   computed,
243			}
244		}
245		// TODO(fullsailor): Optionally verify certificate chain
246		// TODO(fullsailor): Optionally verify signingTime against certificate NotAfter/NotBefore
247		signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
248		if err != nil {
249			return err
250		}
251	}
252	cert := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
253	if cert == nil {
254		return errors.New("pkcs7: No certificate for signer")
255	}
256
257	algo := getSignatureAlgorithmFromAI(signer.DigestEncryptionAlgorithm)
258	if algo == x509.UnknownSignatureAlgorithm {
259		// I'm not sure what the spec here is, and the openssl sources were not
260		// helpful. But, this is what App Store receipts appear to do.
261		// The DigestEncryptionAlgorithm is just "rsaEncryption (PKCS #1)"
262		// But we're expecting a digest + encryption algorithm. So... we're going
263		// to determine an algorithm based on the DigestAlgorithm and this
264		// encryption algorithm.
265		if signer.DigestEncryptionAlgorithm.Algorithm.Equal(oidEncryptionAlgorithmRSA) {
266			algo = getRSASignatureAlgorithmForDigestAlgorithm(hash)
267		}
268	}
269	return cert.CheckSignature(algo, signedData, signer.EncryptedDigest)
270}
271
272func marshalAttributes(attrs []attribute) ([]byte, error) {
273	encodedAttributes, err := asn1.Marshal(struct {
274		A []attribute `asn1:"set"`
275	}{A: attrs})
276	if err != nil {
277		return nil, err
278	}
279
280	// Remove the leading sequence octets
281	var raw asn1.RawValue
282	asn1.Unmarshal(encodedAttributes, &raw)
283	return raw.Bytes, nil
284}
285
286var (
287	oidDigestAlgorithmSHA1    = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
288	oidEncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
289)
290
291func getCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate {
292	for _, cert := range certs {
293		if isCertMatchForIssuerAndSerial(cert, ias) {
294			return cert
295		}
296	}
297	return nil
298}
299
300func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) {
301	switch {
302	case oid.Equal(oidDigestAlgorithmSHA1):
303		return crypto.SHA1, nil
304  case oid.Equal(oidSHA256):
305    return crypto.SHA256, nil
306	}
307	return crypto.Hash(0), ErrUnsupportedAlgorithm
308}
309
310func getRSASignatureAlgorithmForDigestAlgorithm(hash crypto.Hash) x509.SignatureAlgorithm {
311	for _, details := range signatureAlgorithmDetails {
312		if details.pubKeyAlgo == x509.RSA && details.hash == hash {
313			return details.algo
314		}
315	}
316	return x509.UnknownSignatureAlgorithm
317}
318
319// GetOnlySigner returns an x509.Certificate for the first signer of the signed
320// data payload. If there are more or less than one signer, nil is returned
321func (p7 *PKCS7) GetOnlySigner() *x509.Certificate {
322	if len(p7.Signers) != 1 {
323		return nil
324	}
325	signer := p7.Signers[0]
326	return getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
327}
328
329// ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed
330var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported")
331
332// ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data
333var ErrNotEncryptedContent = errors.New("pkcs7: content data is a decryptable data type")
334
335// Decrypt decrypts encrypted content info for recipient cert and private key
336func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pk crypto.PrivateKey) ([]byte, error) {
337	data, ok := p7.raw.(envelopedData)
338	if !ok {
339		return nil, ErrNotEncryptedContent
340	}
341	recipient := selectRecipientForCertificate(data.RecipientInfos, cert)
342	if recipient.EncryptedKey == nil {
343		return nil, errors.New("pkcs7: no enveloped recipient for provided certificate")
344	}
345	if priv := pk.(*rsa.PrivateKey); priv != nil {
346		var contentKey []byte
347		contentKey, err := rsa.DecryptPKCS1v15(rand.Reader, priv, recipient.EncryptedKey)
348		if err != nil {
349			return nil, err
350		}
351		return data.EncryptedContentInfo.decrypt(contentKey)
352	}
353	fmt.Printf("Unsupported Private Key: %v\n", pk)
354	return nil, ErrUnsupportedAlgorithm
355}
356
357var oidEncryptionAlgorithmDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7}
358var oidEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}
359var oidEncryptionAlgorithmAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
360var oidEncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6}
361var oidEncryptionAlgorithmAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
362
363func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
364	alg := eci.ContentEncryptionAlgorithm.Algorithm
365	if !alg.Equal(oidEncryptionAlgorithmDESCBC) &&
366		!alg.Equal(oidEncryptionAlgorithmDESEDE3CBC) &&
367		!alg.Equal(oidEncryptionAlgorithmAES256CBC) &&
368		!alg.Equal(oidEncryptionAlgorithmAES128CBC) &&
369		!alg.Equal(oidEncryptionAlgorithmAES128GCM) {
370		fmt.Printf("Unsupported Content Encryption Algorithm: %s\n", alg)
371		return nil, ErrUnsupportedAlgorithm
372	}
373
374	// EncryptedContent can either be constructed of multple OCTET STRINGs
375	// or _be_ a tagged OCTET STRING
376	var cyphertext []byte
377	if eci.EncryptedContent.IsCompound {
378		// Complex case to concat all of the children OCTET STRINGs
379		var buf bytes.Buffer
380		cypherbytes := eci.EncryptedContent.Bytes
381		for {
382			var part []byte
383			cypherbytes, _ = asn1.Unmarshal(cypherbytes, &part)
384			buf.Write(part)
385			if cypherbytes == nil {
386				break
387			}
388		}
389		cyphertext = buf.Bytes()
390	} else {
391		// Simple case, the bytes _are_ the cyphertext
392		cyphertext = eci.EncryptedContent.Bytes
393	}
394
395	var block cipher.Block
396	var err error
397
398	switch {
399	case alg.Equal(oidEncryptionAlgorithmDESCBC):
400		block, err = des.NewCipher(key)
401	case alg.Equal(oidEncryptionAlgorithmDESEDE3CBC):
402		block, err = des.NewTripleDESCipher(key)
403	case alg.Equal(oidEncryptionAlgorithmAES256CBC):
404		fallthrough
405	case alg.Equal(oidEncryptionAlgorithmAES128GCM), alg.Equal(oidEncryptionAlgorithmAES128CBC):
406		block, err = aes.NewCipher(key)
407	}
408
409	if err != nil {
410		return nil, err
411	}
412
413	if alg.Equal(oidEncryptionAlgorithmAES128GCM) {
414		params := aesGCMParameters{}
415		paramBytes := eci.ContentEncryptionAlgorithm.Parameters.Bytes
416
417		_, err := asn1.Unmarshal(paramBytes, &params)
418		if err != nil {
419			return nil, err
420		}
421
422		gcm, err := cipher.NewGCM(block)
423		if err != nil {
424			return nil, err
425		}
426
427		if len(params.Nonce) != gcm.NonceSize() {
428			return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
429		}
430		if params.ICVLen != gcm.Overhead() {
431			return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
432		}
433
434		plaintext, err := gcm.Open(nil, params.Nonce, cyphertext, nil)
435		if err != nil {
436			return nil, err
437		}
438
439		return plaintext, nil
440	}
441
442	iv := eci.ContentEncryptionAlgorithm.Parameters.Bytes
443	if len(iv) != block.BlockSize() {
444		return nil, errors.New("pkcs7: encryption algorithm parameters are malformed")
445	}
446	mode := cipher.NewCBCDecrypter(block, iv)
447	plaintext := make([]byte, len(cyphertext))
448	mode.CryptBlocks(plaintext, cyphertext)
449	if plaintext, err = unpad(plaintext, mode.BlockSize()); err != nil {
450		return nil, err
451	}
452	return plaintext, nil
453}
454
455func selectRecipientForCertificate(recipients []recipientInfo, cert *x509.Certificate) recipientInfo {
456	for _, recp := range recipients {
457		if isCertMatchForIssuerAndSerial(cert, recp.IssuerAndSerialNumber) {
458			return recp
459		}
460	}
461	return recipientInfo{}
462}
463
464func isCertMatchForIssuerAndSerial(cert *x509.Certificate, ias issuerAndSerial) bool {
465	return cert.SerialNumber.Cmp(ias.SerialNumber) == 0 && bytes.Compare(cert.RawIssuer, ias.IssuerName.FullBytes) == 0
466}
467
468func pad(data []byte, blocklen int) ([]byte, error) {
469	if blocklen < 1 {
470		return nil, fmt.Errorf("invalid blocklen %d", blocklen)
471	}
472	padlen := blocklen - (len(data) % blocklen)
473	if padlen == 0 {
474		padlen = blocklen
475	}
476	pad := bytes.Repeat([]byte{byte(padlen)}, padlen)
477	return append(data, pad...), nil
478}
479
480func unpad(data []byte, blocklen int) ([]byte, error) {
481	if blocklen < 1 {
482		return nil, fmt.Errorf("invalid blocklen %d", blocklen)
483	}
484	if len(data)%blocklen != 0 || len(data) == 0 {
485		return nil, fmt.Errorf("invalid data len %d", len(data))
486	}
487
488	// the last byte is the length of padding
489	padlen := int(data[len(data)-1])
490
491	// check padding integrity, all bytes should be the same
492	pad := data[len(data)-padlen:]
493	for _, padbyte := range pad {
494		if padbyte != byte(padlen) {
495			return nil, errors.New("invalid padding")
496		}
497	}
498
499	return data[:len(data)-padlen], nil
500}
501
502func unmarshalAttribute(attrs []attribute, attributeType asn1.ObjectIdentifier, out interface{}) error {
503	for _, attr := range attrs {
504		if attr.Type.Equal(attributeType) {
505			_, err := asn1.Unmarshal(attr.Value.Bytes, out)
506			return err
507		}
508	}
509	return errors.New("pkcs7: attribute type not in attributes")
510}
511
512// UnmarshalSignedAttribute decodes a single attribute from the signer info
513func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error {
514	sd, ok := p7.raw.(signedData)
515	if !ok {
516		return errors.New("pkcs7: payload is not signedData content")
517	}
518	if len(sd.SignerInfos) < 1 {
519		return errors.New("pkcs7: payload has no signers")
520	}
521	attributes := sd.SignerInfos[0].AuthenticatedAttributes
522	return unmarshalAttribute(attributes, attributeType, out)
523}
524
525// SignedData is an opaque data structure for creating signed data payloads
526type SignedData struct {
527	sd            signedData
528	certs         []*x509.Certificate
529	messageDigest []byte
530}
531
532// Attribute represents a key value pair attribute. Value must be marshalable byte
533// `encoding/asn1`
534type Attribute struct {
535	Type  asn1.ObjectIdentifier
536	Value interface{}
537}
538
539// SignerInfoConfig are optional values to include when adding a signer
540type SignerInfoConfig struct {
541	ExtraSignedAttributes []Attribute
542}
543
544// NewSignedData initializes a SignedData with content
545func NewSignedData(data []byte) (*SignedData, error) {
546	content, err := asn1.Marshal(data)
547	if err != nil {
548		return nil, err
549	}
550	ci := contentInfo{
551		ContentType: oidData,
552		Content:     asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
553	}
554	digAlg := pkix.AlgorithmIdentifier{
555		Algorithm: oidDigestAlgorithmSHA1,
556	}
557	h := crypto.SHA1.New()
558	h.Write(data)
559	md := h.Sum(nil)
560	sd := signedData{
561		ContentInfo:                ci,
562		Version:                    1,
563		DigestAlgorithmIdentifiers: []pkix.AlgorithmIdentifier{digAlg},
564	}
565	return &SignedData{sd: sd, messageDigest: md}, nil
566}
567
568type attributes struct {
569	types  []asn1.ObjectIdentifier
570	values []interface{}
571}
572
573// Add adds the attribute, maintaining insertion order
574func (attrs *attributes) Add(attrType asn1.ObjectIdentifier, value interface{}) {
575	attrs.types = append(attrs.types, attrType)
576	attrs.values = append(attrs.values, value)
577}
578
579type sortableAttribute struct {
580	SortKey   []byte
581	Attribute attribute
582}
583
584type attributeSet []sortableAttribute
585
586func (sa attributeSet) Len() int {
587	return len(sa)
588}
589
590func (sa attributeSet) Less(i, j int) bool {
591	return bytes.Compare(sa[i].SortKey, sa[j].SortKey) < 0
592}
593
594func (sa attributeSet) Swap(i, j int) {
595	sa[i], sa[j] = sa[j], sa[i]
596}
597
598func (sa attributeSet) Attributes() []attribute {
599	attrs := make([]attribute, len(sa))
600	for i, attr := range sa {
601		attrs[i] = attr.Attribute
602	}
603	return attrs
604}
605
606func (attrs *attributes) ForMarshaling() ([]attribute, error) {
607	sortables := make(attributeSet, len(attrs.types))
608	for i := range sortables {
609		attrType := attrs.types[i]
610		attrValue := attrs.values[i]
611		asn1Value, err := asn1.Marshal(attrValue)
612		if err != nil {
613			return nil, err
614		}
615		attr := attribute{
616			Type:  attrType,
617			Value: asn1.RawValue{Tag: 17, IsCompound: true, Bytes: asn1Value}, // 17 == SET tag
618		}
619		encoded, err := asn1.Marshal(attr)
620		if err != nil {
621			return nil, err
622		}
623		sortables[i] = sortableAttribute{
624			SortKey:   encoded,
625			Attribute: attr,
626		}
627	}
628	sort.Sort(sortables)
629	return sortables.Attributes(), nil
630}
631
632// AddSigner signs attributes about the content and adds certificate to payload
633func (sd *SignedData) AddSigner(cert *x509.Certificate, pkey crypto.PrivateKey, config SignerInfoConfig) error {
634	attrs := &attributes{}
635	attrs.Add(oidAttributeContentType, sd.sd.ContentInfo.ContentType)
636	attrs.Add(oidAttributeMessageDigest, sd.messageDigest)
637	attrs.Add(oidAttributeSigningTime, time.Now())
638	for _, attr := range config.ExtraSignedAttributes {
639		attrs.Add(attr.Type, attr.Value)
640	}
641	finalAttrs, err := attrs.ForMarshaling()
642	if err != nil {
643		return err
644	}
645	signature, err := signAttributes(finalAttrs, pkey, crypto.SHA1)
646	if err != nil {
647		return err
648	}
649
650	ias, err := cert2issuerAndSerial(cert)
651	if err != nil {
652		return err
653	}
654
655	signer := signerInfo{
656		AuthenticatedAttributes:   finalAttrs,
657		DigestAlgorithm:           pkix.AlgorithmIdentifier{Algorithm: oidDigestAlgorithmSHA1},
658		DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSignatureSHA1WithRSA},
659		IssuerAndSerialNumber:     ias,
660		EncryptedDigest:           signature,
661		Version:                   1,
662	}
663	// create signature of signed attributes
664	sd.certs = append(sd.certs, cert)
665	sd.sd.SignerInfos = append(sd.sd.SignerInfos, signer)
666	return nil
667}
668
669// AddCertificate adds the certificate to the payload. Useful for parent certificates
670func (sd *SignedData) AddCertificate(cert *x509.Certificate) {
671	sd.certs = append(sd.certs, cert)
672}
673
674// Detach removes content from the signed data struct to make it a detached signature.
675// This must be called right before Finish()
676func (sd *SignedData) Detach() {
677	sd.sd.ContentInfo = contentInfo{ContentType: oidData}
678}
679
680// Finish marshals the content and its signers
681func (sd *SignedData) Finish() ([]byte, error) {
682	sd.sd.Certificates = marshalCertificates(sd.certs)
683	inner, err := asn1.Marshal(sd.sd)
684	if err != nil {
685		return nil, err
686	}
687	outer := contentInfo{
688		ContentType: oidSignedData,
689		Content:     asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
690	}
691	return asn1.Marshal(outer)
692}
693
694func cert2issuerAndSerial(cert *x509.Certificate) (issuerAndSerial, error) {
695	var ias issuerAndSerial
696	// The issuer RDNSequence has to match exactly the sequence in the certificate
697	// We cannot use cert.Issuer.ToRDNSequence() here since it mangles the sequence
698	ias.IssuerName = asn1.RawValue{FullBytes: cert.RawIssuer}
699	ias.SerialNumber = cert.SerialNumber
700
701	return ias, nil
702}
703
704// signs the DER encoded form of the attributes with the private key
705func signAttributes(attrs []attribute, pkey crypto.PrivateKey, hash crypto.Hash) ([]byte, error) {
706	attrBytes, err := marshalAttributes(attrs)
707	if err != nil {
708		return nil, err
709	}
710	h := hash.New()
711	h.Write(attrBytes)
712	hashed := h.Sum(nil)
713	switch priv := pkey.(type) {
714	case *rsa.PrivateKey:
715		return rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA1, hashed)
716	}
717	return nil, ErrUnsupportedAlgorithm
718}
719
720// concats and wraps the certificates in the RawValue structure
721func marshalCertificates(certs []*x509.Certificate) rawCertificates {
722	var buf bytes.Buffer
723	for _, cert := range certs {
724		buf.Write(cert.Raw)
725	}
726	rawCerts, _ := marshalCertificateBytes(buf.Bytes())
727	return rawCerts
728}
729
730// Even though, the tag & length are stripped out during marshalling the
731// RawContent, we have to encode it into the RawContent. If its missing,
732// then `asn1.Marshal()` will strip out the certificate wrapper instead.
733func marshalCertificateBytes(certs []byte) (rawCertificates, error) {
734	var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true}
735	b, err := asn1.Marshal(val)
736	if err != nil {
737		return rawCertificates{}, err
738	}
739	return rawCertificates{Raw: b}, nil
740}
741
742// DegenerateCertificate creates a signed data structure containing only the
743// provided certificate or certificate chain.
744func DegenerateCertificate(cert []byte) ([]byte, error) {
745	rawCert, err := marshalCertificateBytes(cert)
746	if err != nil {
747		return nil, err
748	}
749	emptyContent := contentInfo{ContentType: oidData}
750	sd := signedData{
751		Version:      1,
752		ContentInfo:  emptyContent,
753		Certificates: rawCert,
754		CRLs:         []pkix.CertificateList{},
755	}
756	content, err := asn1.Marshal(sd)
757	if err != nil {
758		return nil, err
759	}
760	signedContent := contentInfo{
761		ContentType: oidSignedData,
762		Content:     asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
763	}
764	return asn1.Marshal(signedContent)
765}
766
767const (
768	EncryptionAlgorithmDESCBC = iota
769	EncryptionAlgorithmAES128GCM
770)
771
772// ContentEncryptionAlgorithm determines the algorithm used to encrypt the
773// plaintext message. Change the value of this variable to change which
774// algorithm is used in the Encrypt() function.
775var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
776
777// ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt
778// content with an unsupported algorithm.
779var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC and AES-128-GCM supported")
780
781const nonceSize = 12
782
783type aesGCMParameters struct {
784	Nonce  []byte `asn1:"tag:4"`
785	ICVLen int
786}
787
788func encryptAES128GCM(content []byte) ([]byte, *encryptedContentInfo, error) {
789	// Create AES key and nonce
790	key := make([]byte, 16)
791	nonce := make([]byte, nonceSize)
792
793	_, err := rand.Read(key)
794	if err != nil {
795		return nil, nil, err
796	}
797
798	_, err = rand.Read(nonce)
799	if err != nil {
800		return nil, nil, err
801	}
802
803	// Encrypt content
804	block, err := aes.NewCipher(key)
805	if err != nil {
806		return nil, nil, err
807	}
808
809	gcm, err := cipher.NewGCM(block)
810	if err != nil {
811		return nil, nil, err
812	}
813
814	ciphertext := gcm.Seal(nil, nonce, content, nil)
815
816	// Prepare ASN.1 Encrypted Content Info
817	paramSeq := aesGCMParameters{
818		Nonce:  nonce,
819		ICVLen: gcm.Overhead(),
820	}
821
822	paramBytes, err := asn1.Marshal(paramSeq)
823	if err != nil {
824		return nil, nil, err
825	}
826
827	eci := encryptedContentInfo{
828		ContentType: oidData,
829		ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
830			Algorithm: oidEncryptionAlgorithmAES128GCM,
831			Parameters: asn1.RawValue{
832				Tag:   asn1.TagSequence,
833				Bytes: paramBytes,
834			},
835		},
836		EncryptedContent: marshalEncryptedContent(ciphertext),
837	}
838
839	return key, &eci, nil
840}
841
842func encryptDESCBC(content []byte) ([]byte, *encryptedContentInfo, error) {
843	// Create DES key & CBC IV
844	key := make([]byte, 8)
845	iv := make([]byte, des.BlockSize)
846	_, err := rand.Read(key)
847	if err != nil {
848		return nil, nil, err
849	}
850	_, err = rand.Read(iv)
851	if err != nil {
852		return nil, nil, err
853	}
854
855	// Encrypt padded content
856	block, err := des.NewCipher(key)
857	if err != nil {
858		return nil, nil, err
859	}
860	mode := cipher.NewCBCEncrypter(block, iv)
861	plaintext, err := pad(content, mode.BlockSize())
862	cyphertext := make([]byte, len(plaintext))
863	mode.CryptBlocks(cyphertext, plaintext)
864
865	// Prepare ASN.1 Encrypted Content Info
866	eci := encryptedContentInfo{
867		ContentType: oidData,
868		ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
869			Algorithm:  oidEncryptionAlgorithmDESCBC,
870			Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
871		},
872		EncryptedContent: marshalEncryptedContent(cyphertext),
873	}
874
875	return key, &eci, nil
876}
877
878// Encrypt creates and returns an envelope data PKCS7 structure with encrypted
879// recipient keys for each recipient public key.
880//
881// The algorithm used to perform encryption is determined by the current value
882// of the global ContentEncryptionAlgorithm package variable. By default, the
883// value is EncryptionAlgorithmDESCBC. To use a different algorithm, change the
884// value before calling Encrypt(). For example:
885//
886//     ContentEncryptionAlgorithm = EncryptionAlgorithmAES128GCM
887//
888// TODO(fullsailor): Add support for encrypting content with other algorithms
889func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
890	var eci *encryptedContentInfo
891	var key []byte
892	var err error
893
894	// Apply chosen symmetric encryption method
895	switch ContentEncryptionAlgorithm {
896	case EncryptionAlgorithmDESCBC:
897		key, eci, err = encryptDESCBC(content)
898
899	case EncryptionAlgorithmAES128GCM:
900		key, eci, err = encryptAES128GCM(content)
901
902	default:
903		return nil, ErrUnsupportedEncryptionAlgorithm
904	}
905
906	if err != nil {
907		return nil, err
908	}
909
910	// Prepare each recipient's encrypted cipher key
911	recipientInfos := make([]recipientInfo, len(recipients))
912	for i, recipient := range recipients {
913		encrypted, err := encryptKey(key, recipient)
914		if err != nil {
915			return nil, err
916		}
917		ias, err := cert2issuerAndSerial(recipient)
918		if err != nil {
919			return nil, err
920		}
921		info := recipientInfo{
922			Version:               0,
923			IssuerAndSerialNumber: ias,
924			KeyEncryptionAlgorithm: pkix.AlgorithmIdentifier{
925				Algorithm: oidEncryptionAlgorithmRSA,
926			},
927			EncryptedKey: encrypted,
928		}
929		recipientInfos[i] = info
930	}
931
932	// Prepare envelope content
933	envelope := envelopedData{
934		EncryptedContentInfo: *eci,
935		Version:              0,
936		RecipientInfos:       recipientInfos,
937	}
938	innerContent, err := asn1.Marshal(envelope)
939	if err != nil {
940		return nil, err
941	}
942
943	// Prepare outer payload structure
944	wrapper := contentInfo{
945		ContentType: oidEnvelopedData,
946		Content:     asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
947	}
948
949	return asn1.Marshal(wrapper)
950}
951
952func marshalEncryptedContent(content []byte) asn1.RawValue {
953	asn1Content, _ := asn1.Marshal(content)
954	return asn1.RawValue{Tag: 0, Class: 2, Bytes: asn1Content, IsCompound: true}
955}
956
957func encryptKey(key []byte, recipient *x509.Certificate) ([]byte, error) {
958	if pub := recipient.PublicKey.(*rsa.PublicKey); pub != nil {
959		return rsa.EncryptPKCS1v15(rand.Reader, pub, key)
960	}
961	return nil, ErrUnsupportedAlgorithm
962}
963