remotesigner.go raw

   1  /*
   2   *
   3   * Copyright 2022 Google LLC
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     https://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   *
  17   */
  18  
  19  // Package remotesigner offloads private key operations to S2Av2.
  20  package remotesigner
  21  
  22  import (
  23  	"crypto"
  24  	"crypto/rsa"
  25  	"crypto/x509"
  26  	"fmt"
  27  	"io"
  28  
  29  	"github.com/google/s2a-go/stream"
  30  	"google.golang.org/grpc/codes"
  31  	"google.golang.org/grpc/grpclog"
  32  
  33  	s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto"
  34  )
  35  
  36  // remoteSigner implementes the crypto.Signer interface.
  37  type remoteSigner struct {
  38  	leafCert  *x509.Certificate
  39  	s2AStream stream.S2AStream
  40  }
  41  
  42  // New returns an instance of RemoteSigner, an implementation of the
  43  // crypto.Signer interface.
  44  func New(leafCert *x509.Certificate, s2AStream stream.S2AStream) crypto.Signer {
  45  	return &remoteSigner{leafCert, s2AStream}
  46  }
  47  
  48  func (s *remoteSigner) Public() crypto.PublicKey {
  49  	return s.leafCert.PublicKey
  50  }
  51  
  52  func (s *remoteSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
  53  	signatureAlgorithm, err := getSignatureAlgorithm(opts, s.leafCert)
  54  	if err != nil {
  55  		return nil, err
  56  	}
  57  
  58  	req, err := getSignReq(signatureAlgorithm, digest)
  59  	if err != nil {
  60  		return nil, err
  61  	}
  62  	if grpclog.V(1) {
  63  		grpclog.Infof("Sending request to S2Av2 for signing operation.")
  64  	}
  65  	if err := s.s2AStream.Send(&s2av2pb.SessionReq{
  66  		ReqOneof: &s2av2pb.SessionReq_OffloadPrivateKeyOperationReq{
  67  			OffloadPrivateKeyOperationReq: req,
  68  		},
  69  	}); err != nil {
  70  		grpclog.Infof("Failed to send request to S2Av2 for signing operation.")
  71  		return nil, err
  72  	}
  73  
  74  	resp, err := s.s2AStream.Recv()
  75  	if err != nil {
  76  		grpclog.Infof("Failed to receive signing operation response from S2Av2.")
  77  		return nil, err
  78  	}
  79  
  80  	if (resp.GetStatus() != nil) && (resp.GetStatus().Code != uint32(codes.OK)) {
  81  		return nil, fmt.Errorf("failed to offload signing with private key to S2A: %d, %v", resp.GetStatus().Code, resp.GetStatus().Details)
  82  	}
  83  
  84  	return resp.GetOffloadPrivateKeyOperationResp().GetOutBytes(), nil
  85  }
  86  
  87  // getCert returns the leafCert field in s.
  88  func (s *remoteSigner) getCert() *x509.Certificate {
  89  	return s.leafCert
  90  }
  91  
  92  // getStream returns the s2AStream field in s.
  93  func (s *remoteSigner) getStream() stream.S2AStream {
  94  	return s.s2AStream
  95  }
  96  
  97  func getSignReq(signatureAlgorithm s2av2pb.SignatureAlgorithm, digest []byte) (*s2av2pb.OffloadPrivateKeyOperationReq, error) {
  98  	if (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256) {
  99  		return &s2av2pb.OffloadPrivateKeyOperationReq{
 100  			Operation:          s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
 101  			SignatureAlgorithm: signatureAlgorithm,
 102  			InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{
 103  				Sha256Digest: digest,
 104  			},
 105  		}, nil
 106  	} else if (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384) {
 107  		return &s2av2pb.OffloadPrivateKeyOperationReq{
 108  			Operation:          s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
 109  			SignatureAlgorithm: signatureAlgorithm,
 110  			InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{
 111  				Sha384Digest: digest,
 112  			},
 113  		}, nil
 114  	} else if (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512) || (signatureAlgorithm == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519) {
 115  		return &s2av2pb.OffloadPrivateKeyOperationReq{
 116  			Operation:          s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
 117  			SignatureAlgorithm: signatureAlgorithm,
 118  			InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{
 119  				Sha512Digest: digest,
 120  			},
 121  		}, nil
 122  	} else {
 123  		return nil, fmt.Errorf("unknown signature algorithm: %v", signatureAlgorithm)
 124  	}
 125  }
 126  
 127  // getSignatureAlgorithm returns the signature algorithm that S2A must use when
 128  // performing a signing operation that has been offloaded by an application
 129  // using the crypto/tls libraries.
 130  func getSignatureAlgorithm(opts crypto.SignerOpts, leafCert *x509.Certificate) (s2av2pb.SignatureAlgorithm, error) {
 131  	if opts == nil || leafCert == nil {
 132  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
 133  	}
 134  	switch leafCert.PublicKeyAlgorithm {
 135  	case x509.RSA:
 136  		if rsaPSSOpts, ok := opts.(*rsa.PSSOptions); ok {
 137  			return rsaPSSAlgorithm(rsaPSSOpts)
 138  		}
 139  		return rsaPPKCS1Algorithm(opts)
 140  	case x509.ECDSA:
 141  		return ecdsaAlgorithm(opts)
 142  	case x509.Ed25519:
 143  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519, nil
 144  	default:
 145  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm: %q", leafCert.PublicKeyAlgorithm)
 146  	}
 147  }
 148  
 149  func rsaPSSAlgorithm(opts *rsa.PSSOptions) (s2av2pb.SignatureAlgorithm, error) {
 150  	switch opts.HashFunc() {
 151  	case crypto.SHA256:
 152  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256, nil
 153  	case crypto.SHA384:
 154  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384, nil
 155  	case crypto.SHA512:
 156  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512, nil
 157  	default:
 158  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
 159  	}
 160  }
 161  
 162  func rsaPPKCS1Algorithm(opts crypto.SignerOpts) (s2av2pb.SignatureAlgorithm, error) {
 163  	switch opts.HashFunc() {
 164  	case crypto.SHA256:
 165  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, nil
 166  	case crypto.SHA384:
 167  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384, nil
 168  	case crypto.SHA512:
 169  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512, nil
 170  	default:
 171  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
 172  	}
 173  }
 174  
 175  func ecdsaAlgorithm(opts crypto.SignerOpts) (s2av2pb.SignatureAlgorithm, error) {
 176  	switch opts.HashFunc() {
 177  	case crypto.SHA256:
 178  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256, nil
 179  	case crypto.SHA384:
 180  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384, nil
 181  	case crypto.SHA512:
 182  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512, nil
 183  	default:
 184  		return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
 185  	}
 186  }
 187