...

Source file src/github.com/sassoftware/relic/lib/appmanifest/verify.go

Documentation: github.com/sassoftware/relic/lib/appmanifest

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package appmanifest
    18  
    19  import (
    20  	"crypto"
    21  	"crypto/x509"
    22  	"encoding/base64"
    23  	"errors"
    24  	"fmt"
    25  
    26  	"github.com/beevik/etree"
    27  	"github.com/sassoftware/relic/lib/pkcs7"
    28  	"github.com/sassoftware/relic/lib/pkcs9"
    29  	"github.com/sassoftware/relic/lib/x509tools"
    30  	"github.com/sassoftware/relic/lib/xmldsig"
    31  	"github.com/sassoftware/relic/signers/sigerrors"
    32  )
    33  
    34  type ManifestSignature struct {
    35  	Signature       *pkcs9.TimestampedSignature
    36  	Hash            crypto.Hash
    37  	AssemblyName    string
    38  	AssemblyVersion string
    39  	PublicKeyToken  string
    40  }
    41  
    42  // Extract and verify signature on an application manifest. Does not verify X509 chains.
    43  func Verify(manifest []byte) (*ManifestSignature, error) {
    44  	doc := etree.NewDocument()
    45  	if err := doc.ReadFromString(string(manifest)); err != nil {
    46  		return nil, err
    47  	}
    48  	root := doc.Root()
    49  	primary, err := xmldsig.Verify(root, "Signature", nil)
    50  	if err != nil {
    51  		if _, ok := err.(sigerrors.NotSignedError); ok {
    52  			return nil, err
    53  		}
    54  		return nil, fmt.Errorf("invalid primary signature: %s", err)
    55  	}
    56  	license := root.FindElement("Signature/KeyInfo/msrel:RelData/r:license")
    57  	if license == nil {
    58  		return nil, sigerrors.NotSignedError{Type: "application manifest"}
    59  	}
    60  	secondary, err := xmldsig.Verify(license, "issuer/Signature", nil)
    61  	if err != nil {
    62  		if _, ok := err.(sigerrors.NotSignedError); ok {
    63  			return nil, err
    64  		}
    65  		return nil, fmt.Errorf("invalid authenticode signature: %s", err)
    66  	}
    67  	if !x509tools.SameKey(primary.PublicKey, secondary.PublicKey) {
    68  		return nil, errors.New("signatures were made with different keys")
    69  	}
    70  	asi := root.SelectElement("assemblyIdentity")
    71  	if asi == nil {
    72  		return nil, errors.New("missing assemblyIdentity")
    73  	}
    74  	token, err := PublicKeyToken(primary.PublicKey)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	if token2 := asi.SelectAttrValue("publicKeyToken", ""); token2 != token {
    79  		return nil, fmt.Errorf("publicKeyToken mismatch: expected %s, got %s", token, token2)
    80  	}
    81  	sig := pkcs7.Signature{Intermediates: secondary.Certificates, Certificate: secondary.Leaf()}
    82  	if sig.Certificate == nil {
    83  		return nil, errors.New("leaf x509 certificate not found")
    84  	}
    85  	ts := &pkcs9.TimestampedSignature{Signature: sig}
    86  	if tse := license.FindElement("r:issuer/Signature/Object/as:Timestamp"); tse != nil {
    87  		blob, err := base64.StdEncoding.DecodeString(tse.Text())
    88  		if err != nil {
    89  			return nil, fmt.Errorf("invalid timestamp: %s", err)
    90  		}
    91  		timestamp, err := pkcs7.Unmarshal(blob)
    92  		if err != nil {
    93  			return nil, fmt.Errorf("invalid timestamp: %s", err)
    94  		}
    95  
    96  		cs, err := VerifyTimestamp(timestamp, secondary.EncryptedDigest, secondary.Certificates)
    97  		if err != nil {
    98  			return nil, fmt.Errorf("invalid timestamp: %s", err)
    99  		}
   100  		ts.CounterSignature = cs
   101  	}
   102  	return &ManifestSignature{
   103  		Signature:       ts,
   104  		AssemblyName:    asi.SelectAttrValue("name", ""),
   105  		AssemblyVersion: asi.SelectAttrValue("version", ""),
   106  		Hash:            primary.Hash,
   107  		PublicKeyToken:  token,
   108  	}, nil
   109  }
   110  
   111  func VerifyTimestamp(timestamp *pkcs7.ContentInfoSignedData, encryptedDigest []byte, extraCerts []*x509.Certificate) (*pkcs9.CounterSignature, error) {
   112  	var cs *pkcs9.CounterSignature
   113  	var err error
   114  
   115  	if timestamp.Content.ContentInfo.ContentType.Equal(pkcs9.OidTSTInfo) {
   116  		// pkcs9 timestamp
   117  		cs, err = pkcs9.Verify(timestamp, encryptedDigest, extraCerts)
   118  	} else {
   119  		// legacy timestamp
   120  		cs, err = pkcs9.VerifyMicrosoftToken(timestamp, encryptedDigest)
   121  	}
   122  
   123  	return cs, err
   124  }
   125  

View as plain text