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.
20package remotesigner
21
22import (
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.
37type 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.
44func New(leafCert *x509.Certificate, s2AStream stream.S2AStream) crypto.Signer {
45 return &remoteSigner{leafCert, s2AStream}
46}
47
48func (s *remoteSigner) Public() crypto.PublicKey {
49 return s.leafCert.PublicKey
50}
51
52func (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.
88func (s *remoteSigner) getCert() *x509.Certificate {
89 return s.leafCert
90}
91
92// getStream returns the s2AStream field in s.
93func (s *remoteSigner) getStream() stream.S2AStream {
94 return s.s2AStream
95}
96
97func 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.
130func 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
149func 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
162func 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
175func 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}