1
18
19 package remotesigner
20
21 import (
22 "bytes"
23 "context"
24 "crypto"
25 "crypto/rand"
26 "crypto/rsa"
27 "crypto/sha256"
28 "crypto/tls"
29 "crypto/x509"
30 "fmt"
31 "log"
32 "net"
33 "strings"
34 "sync"
35 "testing"
36 "time"
37
38 "github.com/google/go-cmp/cmp"
39 "github.com/google/s2a-go/internal/v2/fakes2av2"
40 "google.golang.org/grpc"
41 "google.golang.org/grpc/credentials/insecure"
42 "google.golang.org/protobuf/testing/protocmp"
43
44 _ "embed"
45
46 commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto"
47 s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto"
48 )
49
50 const (
51 defaultTimeout = 10.0 * time.Second
52 )
53
54 func startFakeS2Av2Server(wg *sync.WaitGroup, expToken string) (stop func(), address string, err error) {
55 listener, err := net.Listen("tcp", ":0")
56 if err != nil {
57 log.Fatalf("Failed to listen on address %s: %v", address, err)
58 }
59 address = listener.Addr().String()
60 s := grpc.NewServer()
61 log.Printf("Server: started gRPC fake S2Av2 Server on address: %s", address)
62 s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ExpectedToken: expToken})
63 go func() {
64 wg.Done()
65 if err := s.Serve(listener); err != nil {
66 log.Printf("Failed to serve: %v", err)
67 }
68 }()
69 return func() { s.Stop() }, address, nil
70 }
71
72 var (
73
74 clientCertPEM []byte
75
76 clientCertDER []byte
77
78 clientKeyPEM []byte
79
80 serverCertPEM []byte
81
82 serverCertDER []byte
83
84 serverKeyPEM []byte
85 )
86
87 func TestSign(t *testing.T) {
88
89 var wg sync.WaitGroup
90 wg.Add(1)
91 stop, address, err := startFakeS2Av2Server(&wg, "TestSign_token")
92 wg.Wait()
93 if err != nil {
94 t.Fatalf("Error starting fake S2Av2 Server: %v", err)
95 }
96
97 for _, tc := range []struct {
98 description string
99 PEMCert []byte
100 DERCert []byte
101 PEMKey []byte
102 connSide commonpb.ConnectionSide
103 }{
104 {
105 description: "Sign with client key",
106 PEMCert: clientCertPEM,
107 DERCert: clientCertDER,
108 PEMKey: clientKeyPEM,
109 connSide: commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT,
110 },
111 {
112 description: "Sign with server key",
113 PEMCert: serverCertPEM,
114 DERCert: serverCertDER,
115 PEMKey: serverKeyPEM,
116 connSide: commonpb.ConnectionSide_CONNECTION_SIDE_SERVER,
117 },
118 } {
119 t.Run(tc.description, func(t *testing.T) {
120
121 opts := []grpc.DialOption{
122 grpc.WithTransportCredentials(insecure.NewCredentials()),
123 grpc.WithReturnConnectionError(),
124 grpc.WithBlock(),
125 }
126 conn, err := grpc.Dial(address, opts...)
127 if err != nil {
128 t.Fatalf("Client: failed to connect: %v", err)
129 }
130 defer conn.Close()
131 c := s2av2pb.NewS2AServiceClient(conn)
132 log.Printf("Client: connected to: %s", address)
133 ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
134 defer cancel()
135
136
137 callOpts := []grpc.CallOption{}
138 cstream, err := c.SetUpSession(ctx, callOpts...)
139 if err != nil {
140 t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err)
141 }
142 log.Printf("Client: set up bidirectional streaming RPC session.")
143
144
145
146 if err := cstream.Send(&s2av2pb.SessionReq{
147 AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{
148 {
149 MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{
150 Token: "TestSign_token",
151 },
152 },
153 },
154 ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{
155 GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{
156 ConnectionSide: tc.connSide,
157 },
158 },
159 }); err != nil {
160 t.Fatalf("Setup failed: failed to send initial SessionReq for TLS config: %v", err)
161 }
162
163 if _, err := cstream.Recv(); err != nil {
164 t.Fatalf("Setup failed: failed to receive initial SessionResp for TLS config: %v", err)
165 }
166
167
168 TLSCert, err := tls.X509KeyPair(tc.PEMCert, tc.PEMKey)
169 if err != nil {
170 t.Fatalf("tls.X509KeyPair failed: %v", err)
171 }
172 x509Cert, err := x509.ParseCertificate(tc.DERCert)
173 if err != nil {
174 t.Fatalf("Failed to parse cert: %v", err)
175 }
176 testInBytes := []byte("Test data.")
177
178
179 hsha256 := sha256.Sum256([]byte(testInBytes))
180
181
182 s := New(x509Cert, cstream)
183
184 gotSignedBytes, err := s.Sign(rand.Reader, hsha256[:], crypto.SHA256)
185 if err != nil {
186 t.Errorf("Call to remote signer Sign API failed: %v", err)
187 }
188 wantSignedBytes, err := TLSCert.PrivateKey.(crypto.Signer).Sign(rand.Reader, hsha256[:], crypto.SHA256)
189 if err != nil {
190 t.Errorf("Call to Sign API failed: %v", err)
191 }
192 if !bytes.Equal(gotSignedBytes, wantSignedBytes) {
193 t.Errorf("gotSignedBytes = %v, wantSignedBytes = %v", gotSignedBytes, wantSignedBytes)
194 }
195 if err = rsa.VerifyPKCS1v15(x509Cert.PublicKey.(*rsa.PublicKey), crypto.SHA256, hsha256[:], gotSignedBytes); err != nil {
196 t.Errorf("Failed to verify RSA PKCS #1 v1.5 signature: %v", err)
197 }
198
199
200 s = New(x509Cert, cstream)
201 pssSignerOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256}
202
203 gotSignedBytes, err = s.Sign(rand.Reader, hsha256[:], pssSignerOpts)
204 if err != nil {
205 t.Errorf("Failed to generate gotSignedBytes using RSA PSS: %v", err)
206 }
207 if err = rsa.VerifyPSS(x509Cert.PublicKey.(*rsa.PublicKey), crypto.SHA256, hsha256[:], gotSignedBytes, pssSignerOpts); err != nil {
208 t.Errorf("Failed to verify RSA PSS signature: %v", err)
209 }
210 })
211 }
212 stop()
213 }
214
215
216 func TestNew(t *testing.T) {
217
218 clientx509Cert, err := x509.ParseCertificate(clientCertDER)
219 if err != nil {
220 t.Errorf("Failed to parse cert: %v", err)
221 }
222 var cstream s2av2pb.S2AService_SetUpSessionClient
223
224 got := New(clientx509Cert, cstream)
225 if v := got.(*remoteSigner).getCert(); v != clientx509Cert {
226 t.Errorf("RemoteSigner leafCert field is incorrect. got: %v, want: %v", v, clientx509Cert)
227 }
228 if v := got.(*remoteSigner).getStream(); v != cstream {
229 t.Errorf("RemoteSigner cstream field is incorrect. got: %v, want: %v", v, cstream)
230 }
231 }
232
233
234 func TestGetSignatureAlgorithm(t *testing.T) {
235 for _, tc := range []struct {
236 description string
237 leafCert *x509.Certificate
238 signerOpts crypto.SignerOpts
239 wantSignatureAlgorithm s2av2pb.SignatureAlgorithm
240 wantError error
241 }{
242 {
243 description: "Leaf certificate is nil",
244 leafCert: nil,
245 signerOpts: crypto.SHA256,
246 wantError: fmt.Errorf("unknown signature algorithm"),
247 },
248 {
249 description: "Signer options are nil",
250 leafCert: &x509.Certificate{},
251 signerOpts: nil,
252 wantError: fmt.Errorf("unknown signature algorithm"),
253 },
254 {
255 description: "RSA PSS SHA256",
256 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
257 signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256},
258 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256,
259 },
260 {
261 description: "RSA PSS SHA384",
262 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
263 signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA384},
264 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384,
265 },
266 {
267 description: "RSA PSS SHA512",
268 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
269 signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA512},
270 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512,
271 },
272 {
273 description: "RSA PSS with unsupported hash",
274 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
275 signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.MD5},
276 wantError: fmt.Errorf("unknown signature algorithm"),
277 },
278 {
279 description: "RSA PKCS1 SHA256",
280 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
281 signerOpts: crypto.SHA256,
282 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256,
283 },
284 {
285 description: "RSA PKCS1 SHA384",
286 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
287 signerOpts: crypto.SHA384,
288 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384,
289 },
290 {
291 description: "RSA PKCS1 SHA512",
292 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
293 signerOpts: crypto.SHA512,
294 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512,
295 },
296 {
297 description: "RSA PKCS1 with unsupported hash",
298 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA},
299 signerOpts: crypto.MD5,
300 wantError: fmt.Errorf("unknown signature algorithm"),
301 },
302 {
303 description: "ECDSA SHA256",
304 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA},
305 signerOpts: crypto.SHA256,
306 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256,
307 },
308 {
309 description: "ECDSA SHA384",
310 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA},
311 signerOpts: crypto.SHA384,
312 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384,
313 },
314 {
315 description: "ECDSA SHA512",
316 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA},
317 signerOpts: crypto.SHA512,
318 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512,
319 },
320 {
321 description: "ECDSA with unsupported hash",
322 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA},
323 signerOpts: crypto.MD5,
324 wantError: fmt.Errorf("unknown signature algorithm"),
325 },
326 {
327 description: "ED25519",
328 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.Ed25519},
329 signerOpts: crypto.SHA256,
330 wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519,
331 },
332 {
333 description: "DSA",
334 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.DSA},
335 signerOpts: crypto.SHA256,
336 wantError: fmt.Errorf("unknown signature algorithm: \"DSA\""),
337 },
338 {
339 description: "Unknown public key algorithm",
340 leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.UnknownPublicKeyAlgorithm},
341 signerOpts: crypto.SHA256,
342 wantError: fmt.Errorf("unknown signature algorithm: \"0\""),
343 },
344 {
345 description: "No public key algorithm",
346 leafCert: &x509.Certificate{},
347 signerOpts: crypto.SHA256,
348 wantError: fmt.Errorf("unknown signature algorithm: \"0\""),
349 },
350 } {
351 t.Run(tc.description, func(t *testing.T) {
352 algorithm, err := getSignatureAlgorithm(tc.signerOpts, tc.leafCert)
353
354 if tc.wantError != nil {
355 if got, want := algorithm, s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED; got != want {
356 t.Errorf("Signature algorithm, got: %v, want: %v", got, want)
357 }
358 if !strings.Contains(tc.wantError.Error(), err.Error()) {
359 t.Errorf("Unexpected error, got: %v, want: %v", err, tc.wantError)
360 }
361 } else {
362 if got, want := algorithm, tc.wantSignatureAlgorithm; got != want {
363 t.Errorf("Signature algorithm, got: %v, want: %v", got, want)
364 }
365 if err != nil {
366 t.Errorf("Unexpected error: %v", err)
367 }
368 }
369 })
370 }
371 }
372
373 func TestGetSignReq(t *testing.T) {
374 for _, tc := range []struct {
375 description string
376 signatureAlgorithm s2av2pb.SignatureAlgorithm
377 expReq *s2av2pb.OffloadPrivateKeyOperationReq
378 expErr error
379 }{
380 {
381 description: "Unspecified",
382 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED,
383 expErr: fmt.Errorf("unknown signature algorithm: %v", s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED),
384 },
385 {
386 description: "RSA PKCS1 SHA256",
387 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256,
388 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
389 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
390 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256,
391 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{
392 Sha256Digest: []byte(""),
393 },
394 },
395 },
396 {
397 description: "RSA PSS SHA256",
398 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256,
399 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
400 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
401 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256,
402 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{
403 Sha256Digest: []byte(""),
404 },
405 },
406 },
407 {
408 description: "ECDSA SHA256",
409 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256,
410 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
411 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
412 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256,
413 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{
414 Sha256Digest: []byte(""),
415 },
416 },
417 },
418 {
419 description: "RSA PKCS1 SHA384",
420 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384,
421 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
422 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
423 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384,
424 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{
425 Sha384Digest: []byte(""),
426 },
427 },
428 },
429 {
430 description: "RSA PSS SHA384",
431 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384,
432 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
433 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
434 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384,
435 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{
436 Sha384Digest: []byte(""),
437 },
438 },
439 },
440 {
441 description: "ECDSA SHA384",
442 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384,
443 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
444 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
445 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384,
446 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{
447 Sha384Digest: []byte(""),
448 },
449 },
450 },
451 {
452 description: "RSA PKCS1 SHA512",
453 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512,
454 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
455 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
456 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512,
457 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{
458 Sha512Digest: []byte(""),
459 },
460 },
461 },
462 {
463 description: "RSA PSS SHA512",
464 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512,
465 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
466 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
467 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512,
468 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{
469 Sha512Digest: []byte(""),
470 },
471 },
472 },
473 {
474 description: "ECDSA SHA512",
475 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512,
476 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
477 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
478 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512,
479 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{
480 Sha512Digest: []byte(""),
481 },
482 },
483 },
484 {
485 description: "ED25519",
486 signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519,
487 expReq: &s2av2pb.OffloadPrivateKeyOperationReq{
488 Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN,
489 SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519,
490 InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{
491 Sha512Digest: []byte(""),
492 },
493 },
494 },
495 } {
496 t.Run(tc.description, func(t *testing.T) {
497 gotReq, gotErr := getSignReq(tc.signatureAlgorithm, []byte(""))
498 if gotErr != tc.expErr {
499 if (gotErr == nil) || (tc.expErr == nil) {
500 t.Errorf("gotErr = %v, expErr = %v", gotErr, tc.expErr)
501 }
502 if gotErr.Error() != tc.expErr.Error() {
503 t.Errorf("gotErr = %v, expErr = %v", gotErr, tc.expErr)
504 }
505 }
506 if diff := cmp.Diff(tc.expReq, gotReq, protocmp.Transform()); diff != "" {
507 t.Errorf("getSignReq returned incorrect OffloadPrivateKeyOperationReq, (-want +got):\n%s", diff)
508 }
509 })
510 }
511 }
512
View as plain text