123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- *
- * Copyright 2022 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- // Package remotesigner offloads private key operations to S2Av2.
- package remotesigner
- import (
- "crypto"
- "crypto/rsa"
- "crypto/x509"
- "fmt"
- "io"
- "github.com/google/s2a-go/stream"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/grpclog"
- s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto"
- )
- // remoteSigner implementes the crypto.Signer interface.
- type remoteSigner struct {
- leafCert *x509.Certificate
- s2AStream stream.S2AStream
- }
- // New returns an instance of RemoteSigner, an implementation of the
- // crypto.Signer interface.
- func New(leafCert *x509.Certificate, s2AStream stream.S2AStream) crypto.Signer {
- return &remoteSigner{leafCert, s2AStream}
- }
- func (s *remoteSigner) Public() crypto.PublicKey {
- return s.leafCert.PublicKey
- }
- func (s *remoteSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
- signatureAlgorithm, err := getSignatureAlgorithm(opts, s.leafCert)
- if err != nil {
- return nil, err
- }
- req, err := getSignReq(signatureAlgorithm, digest)
- if err != nil {
- return nil, err
- }
- if grpclog.V(1) {
- grpclog.Infof("Sending request to S2Av2 for signing operation.")
- }
- if err := s.s2AStream.Send(&s2av2pb.SessionReq{
- ReqOneof: &s2av2pb.SessionReq_OffloadPrivateKeyOperationReq{
- OffloadPrivateKeyOperationReq: req,
- },
- }); err != nil {
- grpclog.Infof("Failed to send request to S2Av2 for signing operation.")
- return nil, err
- }
- resp, err := s.s2AStream.Recv()
- if err != nil {
- grpclog.Infof("Failed to receive signing operation response from S2Av2.")
- return nil, err
- }
- if (resp.GetStatus() != nil) && (resp.GetStatus().Code != uint32(codes.OK)) {
- return nil, fmt.Errorf("failed to offload signing with private key to S2A: %d, %v", resp.GetStatus().Code, resp.GetStatus().Details)
- }
- return resp.GetOffloadPrivateKeyOperationResp().GetOutBytes(), nil
- }
- // getCert returns the leafCert field in s.
- func (s *remoteSigner) getCert() *x509.Certificate {
- return s.leafCert
- }
- // getStream returns the s2AStream field in s.
- func (s *remoteSigner) getStream() stream.S2AStream {
- return s.s2AStream
- }
- func getSignReq(signatureAlgorithm s2av2pb.SignatureAlgorithm, digest []byte) (*s2av2pb.OffloadPrivateKeyOperationReq, error) {
- 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) {
- return &s2av2pb.OffloadPrivateKeyOperationReq{
- Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
- SignatureAlgorithm: signatureAlgorithm,
- InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{
- Sha256Digest: digest,
- },
- }, nil
- } 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) {
- return &s2av2pb.OffloadPrivateKeyOperationReq{
- Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
- SignatureAlgorithm: signatureAlgorithm,
- InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{
- Sha384Digest: digest,
- },
- }, nil
- } 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) {
- return &s2av2pb.OffloadPrivateKeyOperationReq{
- Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
- SignatureAlgorithm: signatureAlgorithm,
- InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{
- Sha512Digest: digest,
- },
- }, nil
- } else {
- return nil, fmt.Errorf("unknown signature algorithm: %v", signatureAlgorithm)
- }
- }
- // getSignatureAlgorithm returns the signature algorithm that S2A must use when
- // performing a signing operation that has been offloaded by an application
- // using the crypto/tls libraries.
- func getSignatureAlgorithm(opts crypto.SignerOpts, leafCert *x509.Certificate) (s2av2pb.SignatureAlgorithm, error) {
- if opts == nil || leafCert == nil {
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
- }
- switch leafCert.PublicKeyAlgorithm {
- case x509.RSA:
- if rsaPSSOpts, ok := opts.(*rsa.PSSOptions); ok {
- return rsaPSSAlgorithm(rsaPSSOpts)
- }
- return rsaPPKCS1Algorithm(opts)
- case x509.ECDSA:
- return ecdsaAlgorithm(opts)
- case x509.Ed25519:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519, nil
- default:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm: %q", leafCert.PublicKeyAlgorithm)
- }
- }
- func rsaPSSAlgorithm(opts *rsa.PSSOptions) (s2av2pb.SignatureAlgorithm, error) {
- switch opts.HashFunc() {
- case crypto.SHA256:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256, nil
- case crypto.SHA384:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384, nil
- case crypto.SHA512:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512, nil
- default:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
- }
- }
- func rsaPPKCS1Algorithm(opts crypto.SignerOpts) (s2av2pb.SignatureAlgorithm, error) {
- switch opts.HashFunc() {
- case crypto.SHA256:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, nil
- case crypto.SHA384:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384, nil
- case crypto.SHA512:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512, nil
- default:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
- }
- }
- func ecdsaAlgorithm(opts crypto.SignerOpts) (s2av2pb.SignatureAlgorithm, error) {
- switch opts.HashFunc() {
- case crypto.SHA256:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256, nil
- case crypto.SHA384:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384, nil
- case crypto.SHA512:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512, nil
- default:
- return s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, fmt.Errorf("unknown signature algorithm")
- }
- }
|