github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/fleetspeak/src/server/internal/signatures/validation.go (about)

     1  // Copyright 2017 Google Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package signatures implements utility methods for checking
    16  // cryptographic signatures.
    17  package signatures
    18  
    19  import (
    20  	"crypto/x509"
    21  	"time"
    22  
    23  	log "github.com/golang/glog"
    24  	"golang.org/x/time/rate"
    25  
    26  	"github.com/google/fleetspeak/fleetspeak/src/common"
    27  	"github.com/google/fleetspeak/fleetspeak/src/server/authorizer"
    28  
    29  	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
    30  )
    31  
    32  var logLimiter = rate.NewLimiter(rate.Every(30*time.Second), 50)
    33  
    34  // ValidateWrappedContactData examines the extra signatures included
    35  // in WrappedContactData and attempts to validate them.
    36  func ValidateWrappedContactData(id common.ClientID, cd *fspb.WrappedContactData) ([]authorizer.SignatureInfo, error) {
    37  	if len(cd.Signatures) == 0 {
    38  		return nil, nil
    39  	}
    40  	res := make([]authorizer.SignatureInfo, 0, len(cd.Signatures))
    41  
    42  	for _, sig := range cd.Signatures {
    43  		certs := make([]*x509.Certificate, len(sig.Certificate))
    44  		var err error
    45  		for i, c := range sig.Certificate {
    46  			certs[i], err = x509.ParseCertificate(c)
    47  			if err != nil {
    48  				return nil, err
    49  			}
    50  		}
    51  
    52  		alg := x509.UnknownSignatureAlgorithm
    53  		if int(sig.Algorithm) > int(x509.UnknownSignatureAlgorithm) &&
    54  			int(sig.Algorithm) <= int(x509.SHA512WithRSAPSS) {
    55  			alg = x509.SignatureAlgorithm(sig.Algorithm)
    56  		} else {
    57  			if logLimiter.Allow() {
    58  				log.Warningf("Client [%v] provided signature with unknown algorithm enum: %d", id, sig.Algorithm)
    59  			}
    60  		}
    61  
    62  		var valid bool
    63  		if alg != x509.UnknownSignatureAlgorithm {
    64  			err := certs[0].CheckSignature(alg, cd.ContactData, sig.Signature)
    65  			if err != nil && logLimiter.Allow() {
    66  				log.Warningf("Client [%v] provided signature that could not be validated: %v", id, err)
    67  			}
    68  			valid = err == nil
    69  		}
    70  
    71  		res = append(res, authorizer.SignatureInfo{
    72  			Certificate: certs,
    73  			Algorithm:   alg,
    74  			Valid:       valid,
    75  		})
    76  	}
    77  	return res, nil
    78  }