Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ber.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
}

func isIndefiniteTermination(ber []byte, offset int) (bool, error) {
if len(ber) - offset < 2 {
if len(ber)-offset < 2 {
return false, errors.New("ber2der: Invalid BER format")
}

Expand Down
26 changes: 26 additions & 0 deletions internal/x509util/x509util.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ func SignatureAlgorithmDetailsForOid(oid asn1.ObjectIdentifier) (x509.SignatureA
fmt.Errorf("could not find SignatureAlgorithm details for oid: %s", oid)
}

// SignatureAlgorithmDetailsForOid returns a matching SignatureAlgorithm and
// crypto.Hash function from a provided oid.
func SignatureAlgorithmDetailsForOidPair(oidSig, oidEnc asn1.ObjectIdentifier) (x509.SignatureAlgorithm, crypto.Hash, error) {
algo, hash, err := SignatureAlgorithmDetailsForOid(oidSig)
if err == nil {
return algo, hash, err
}

switch {
case oidEnc.Equal(oidRSA):
switch {
case oidSig.Equal(oidSHA256):
return x509.SHA256WithRSA, crypto.SHA256, nil
case oidSig.Equal(oidSHA384):
return x509.SHA384WithRSA, crypto.SHA384, nil
case oidSig.Equal(oidSHA512):
return x509.SHA512WithRSA, crypto.SHA512, nil
}
}

return x509.UnknownSignatureAlgorithm, crypto.Hash(0),
fmt.Errorf("could not find SignatureAlgorithm details for oids: %s, %s", oidSig, oidEnc)
}

// SigningParamsForPublicKey returns the parameters to use for signing.
// If requestedSigAlgo is not zero then it overrides the default
// signature algorithm.
Expand Down Expand Up @@ -139,6 +163,8 @@ var (
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}

oidRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}

oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
Expand Down
37 changes: 21 additions & 16 deletions pkcs7.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ type signerInfo struct {
UnauthenticatedAttributes []attribute `asn1:"optional,tag:1"`
}

func (si *signerInfo) SignatureAlgorithmDetails() (x509.SignatureAlgorithm, crypto.Hash, error) {
return x509util.SignatureAlgorithmDetailsForOidPair(si.DigestAlgorithm.Algorithm, si.DigestEncryptionAlgorithm.Algorithm)
}

// Parse decodes a DER encoded PKCS7 package
func Parse(data []byte) (p7 *PKCS7, err error) {
if len(data) == 0 {
Expand Down Expand Up @@ -225,17 +229,29 @@ func (p7 *PKCS7) Verify() (err error) {

func verifySignature(p7 *PKCS7, signer signerInfo) error {
signedData := p7.Content

var algo x509.SignatureAlgorithm
var hash crypto.Hash
var err error

oid := signer.DigestAlgorithm.Algorithm
if oid.Equal(oidDigestAlgorithmSHA1) || oid.Equal(oidISOSignatureSHA1WithRSA) {
algo = x509.SHA1WithRSA
hash = crypto.SHA1
} else {
algo, hash, err = signer.SignatureAlgorithmDetails()
if err != nil {
return err
}
}

if len(signer.AuthenticatedAttributes) > 0 {
// TODO(fullsailor): First check the content type match
var digest []byte
err := unmarshalAttribute(signer.AuthenticatedAttributes, oidAttributeMessageDigest, &digest)
if err != nil {
return err
}
hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
if err != nil {
return err
}
h := hash.New()
if _, err := h.Write(p7.Content); err != nil {
return err
Expand All @@ -254,23 +270,12 @@ func verifySignature(p7 *PKCS7, signer signerInfo) error {
return err
}
}

cert := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
if cert == nil {
return errors.New("pkcs7: No certificate for signer")
}

oid := signer.DigestAlgorithm.Algorithm
var algo x509.SignatureAlgorithm
switch {
case oid.Equal(oidDigestAlgorithmSHA1):
algo = x509.SHA1WithRSA
default:
var err error
algo, _, err = x509util.SignatureAlgorithmDetailsForOid(oid)
if err != nil {
return err
}
}
return cert.CheckSignature(algo, signedData, signer.EncryptedDigest)
}

Expand Down