pax_global_header00006660000000000000000000000064146471103660014522gustar00rootroot0000000000000052 comment=f47b8173a27ea8453fb2b18992f076aff796119d s2a-go-0.1.8/000077500000000000000000000000001464711036600126205ustar00rootroot00000000000000s2a-go-0.1.8/.gitignore000066400000000000000000000002131464711036600146040ustar00rootroot00000000000000# Ignore binaries without extension //example/client/client //example/server/server //internal/v2/fakes2av2_server/fakes2av2_server .idea/s2a-go-0.1.8/CODE_OF_CONDUCT.md000066400000000000000000000106271464711036600154250ustar00rootroot00000000000000# Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. This Code of Conduct also applies outside the project spaces when the Project Steward has a reasonable belief that an individual's behavior may have a negative impact on the project or its community. ## Conflict Resolution We do not believe that all conflict is bad; healthy debate and disagreement often yield positive results. However, it is never okay to be disrespectful or to engage in behavior that violates the project’s code of conduct. If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe. Reports should be directed to *[PROJECT STEWARD NAME(s) AND EMAIL(s)]*, the Project Steward(s) for *[PROJECT NAME]*. It is the Project Steward’s duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the Open Source Programs Office and the Google Open Source Strategy team. If for any reason you are uncomfortable reaching out to the Project Steward, please email opensource@google.com. We will investigate every complaint, but you may not receive a direct response. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the project and project-sponsored spaces. We will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone's safety, we may take action without notice. ## Attribution This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html s2a-go-0.1.8/CONTRIBUTING.md000066400000000000000000000021171464711036600150520ustar00rootroot00000000000000# How to Contribute We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. ## Contributor License Agreement Contributions to this project must be accompanied by a Contributor License Agreement (CLA). You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. ## Code reviews All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. ## Community Guidelines This project follows [Google's Open Source Community Guidelines](https://opensource.google/conduct/). s2a-go-0.1.8/LICENSE.md000066400000000000000000000261361464711036600142340ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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 http://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. s2a-go-0.1.8/README.md000066400000000000000000000014251464711036600141010ustar00rootroot00000000000000# Secure Session Agent Client Libraries The Secure Session Agent is a service that enables a workload to offload select operations from the mTLS handshake and protects a workload's private key material from exfiltration. Specifically, the workload asks the Secure Session Agent for the TLS configuration to use during the handshake, to perform private key operations, and to validate the peer certificate chain. The Secure Session Agent's client libraries enable applications to communicate with the Secure Session Agent during the TLS handshake, and to encrypt traffic to the peer after the TLS handshake is complete. This repository contains the source code for the Secure Session Agent's Go client libraries, which allow gRPC and HTTP Go applications to use the Secure Session Agent. s2a-go-0.1.8/example/000077500000000000000000000000001464711036600142535ustar00rootroot00000000000000s2a-go-0.1.8/example/README.md000066400000000000000000000003161464711036600155320ustar00rootroot00000000000000This example implements a gRPC Go Echo client and server which use self-signed X.509 certificates and s2av2TransportCreds (implementation of TransportCredentials interface) to establish an mTLS connection. s2a-go-0.1.8/example/client/000077500000000000000000000000001464711036600155315ustar00rootroot00000000000000s2a-go-0.1.8/example/client/client.go000066400000000000000000000040521464711036600173370ustar00rootroot00000000000000/* * * 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 main establishes a connection with an Echo service. package main import ( "context" "flag" "log" "time" "github.com/google/s2a-go" "google.golang.org/grpc" pb "github.com/google/s2a-go/example/proto/echo_go_proto" ) const ( defaultTimeout = 10.0 * time.Second ) var ( serverAddr = flag.String("server_addr", "0.0.0.0:8080", "Echo service address.") s2aAddr = flag.String("s2a_addr", "0.0.0.0:61365", "S2A service address.") ) func runClient(serverAddr *string) { creds, err := s2a.NewClientCreds(&s2a.ClientOptions{ S2AAddress: *s2aAddr, VerificationMode: s2a.ConnectToGoogle, LocalIdentity: s2a.NewHostname("test_rsa_client_identity"), }) if err != nil { log.Fatalf("NewClientCreds() failed: %v", err) } opts := []grpc.DialOption{ grpc.WithTransportCredentials(creds), grpc.WithReturnConnectionError(), grpc.WithDisableRetry(), grpc.WithBlock(), } conn, err := grpc.Dial(*serverAddr, opts...) if err != nil { log.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := pb.NewEchoClient(conn) log.Printf("Client: connected to: %s", *serverAddr) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() msg := "Hello S2Av2 user!" r, err := c.Echo(ctx, &pb.EchoRequest{Msg: msg}) if err != nil { log.Fatalf("Client: failed to send echo message: %v", err) } log.Printf("Client: received message from server: %s", r.GetMsg()) } func main() { runClient(serverAddr) } s2a-go-0.1.8/example/echo/000077500000000000000000000000001464711036600151715ustar00rootroot00000000000000s2a-go-0.1.8/example/echo/echo.go000066400000000000000000000020701464711036600164350ustar00rootroot00000000000000/* * * 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 echo contains the libraries for running an Echo server. package echo import ( "context" pb "github.com/google/s2a-go/example/proto/echo_go_proto" ) // Server is an echo server used for testing. type Server struct { pb.UnimplementedEchoServer } // Echo uses the message, Msg, in EchoRequest to formulate EchoResponse. func (s *Server) Echo(ctx context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) { return &pb.EchoResponse{Msg: req.GetMsg()}, nil } s2a-go-0.1.8/example/proto/000077500000000000000000000000001464711036600154165ustar00rootroot00000000000000s2a-go-0.1.8/example/proto/echo.proto000066400000000000000000000016641464711036600174300ustar00rootroot00000000000000/* * * 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. * */ syntax = "proto3"; package s2av2.example.proto; option go_package = "github.com/google/s2a/example/proto/echo_go_proto"; service Echo { // The echo service replies back the same message in the request. rpc Echo(EchoRequest) returns (EchoResponse) {} } message EchoRequest { string msg = 1; } message EchoResponse { string msg = 1; } s2a-go-0.1.8/example/proto/echo_go_proto/000077500000000000000000000000001464711036600202445ustar00rootroot00000000000000s2a-go-0.1.8/example/proto/echo_go_proto/echo.pb.go000066400000000000000000000170361464711036600221200ustar00rootroot00000000000000// // // 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. // // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: example/proto/echo.proto package echo_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type EchoRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` } func (x *EchoRequest) Reset() { *x = EchoRequest{} if protoimpl.UnsafeEnabled { mi := &file_example_proto_echo_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoRequest) ProtoMessage() {} func (x *EchoRequest) ProtoReflect() protoreflect.Message { mi := &file_example_proto_echo_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EchoRequest.ProtoReflect.Descriptor instead. func (*EchoRequest) Descriptor() ([]byte, []int) { return file_example_proto_echo_proto_rawDescGZIP(), []int{0} } func (x *EchoRequest) GetMsg() string { if x != nil { return x.Msg } return "" } type EchoResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` } func (x *EchoResponse) Reset() { *x = EchoResponse{} if protoimpl.UnsafeEnabled { mi := &file_example_proto_echo_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EchoResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*EchoResponse) ProtoMessage() {} func (x *EchoResponse) ProtoReflect() protoreflect.Message { mi := &file_example_proto_echo_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use EchoResponse.ProtoReflect.Descriptor instead. func (*EchoResponse) Descriptor() ([]byte, []int) { return file_example_proto_echo_proto_rawDescGZIP(), []int{1} } func (x *EchoResponse) GetMsg() string { if x != nil { return x.Msg } return "" } var File_example_proto_echo_proto protoreflect.FileDescriptor var file_example_proto_echo_proto_rawDesc = []byte{ 0x0a, 0x18, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x73, 0x32, 0x61, 0x76, 0x32, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1f, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x20, 0x0a, 0x0c, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x32, 0x55, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x4d, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x20, 0x2e, 0x73, 0x32, 0x61, 0x76, 0x32, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73, 0x32, 0x61, 0x76, 0x32, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_example_proto_echo_proto_rawDescOnce sync.Once file_example_proto_echo_proto_rawDescData = file_example_proto_echo_proto_rawDesc ) func file_example_proto_echo_proto_rawDescGZIP() []byte { file_example_proto_echo_proto_rawDescOnce.Do(func() { file_example_proto_echo_proto_rawDescData = protoimpl.X.CompressGZIP(file_example_proto_echo_proto_rawDescData) }) return file_example_proto_echo_proto_rawDescData } var file_example_proto_echo_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_example_proto_echo_proto_goTypes = []any{ (*EchoRequest)(nil), // 0: s2av2.example.proto.EchoRequest (*EchoResponse)(nil), // 1: s2av2.example.proto.EchoResponse } var file_example_proto_echo_proto_depIdxs = []int32{ 0, // 0: s2av2.example.proto.Echo.Echo:input_type -> s2av2.example.proto.EchoRequest 1, // 1: s2av2.example.proto.Echo.Echo:output_type -> s2av2.example.proto.EchoResponse 1, // [1:2] is the sub-list for method output_type 0, // [0:1] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_example_proto_echo_proto_init() } func file_example_proto_echo_proto_init() { if File_example_proto_echo_proto != nil { return } if !protoimpl.UnsafeEnabled { file_example_proto_echo_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*EchoRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_example_proto_echo_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*EchoResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_example_proto_echo_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 1, }, GoTypes: file_example_proto_echo_proto_goTypes, DependencyIndexes: file_example_proto_echo_proto_depIdxs, MessageInfos: file_example_proto_echo_proto_msgTypes, }.Build() File_example_proto_echo_proto = out.File file_example_proto_echo_proto_rawDesc = nil file_example_proto_echo_proto_goTypes = nil file_example_proto_echo_proto_depIdxs = nil } s2a-go-0.1.8/example/proto/echo_go_proto/echo_grpc.pb.go000066400000000000000000000102251464711036600231240ustar00rootroot00000000000000// // // 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. // // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.4.0 // - protoc v3.21.12 // source: example/proto/echo.proto package echo_go_proto import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.62.0 or later. const _ = grpc.SupportPackageIsVersion8 const ( Echo_Echo_FullMethodName = "/s2av2.example.proto.Echo/Echo" ) // EchoClient is the client API for Echo service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type EchoClient interface { // The echo service replies back the same message in the request. Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) } type echoClient struct { cc grpc.ClientConnInterface } func NewEchoClient(cc grpc.ClientConnInterface) EchoClient { return &echoClient{cc} } func (c *echoClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(EchoResponse) err := c.cc.Invoke(ctx, Echo_Echo_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } // EchoServer is the server API for Echo service. // All implementations must embed UnimplementedEchoServer // for forward compatibility type EchoServer interface { // The echo service replies back the same message in the request. Echo(context.Context, *EchoRequest) (*EchoResponse, error) mustEmbedUnimplementedEchoServer() } // UnimplementedEchoServer must be embedded to have forward compatible implementations. type UnimplementedEchoServer struct { } func (UnimplementedEchoServer) Echo(context.Context, *EchoRequest) (*EchoResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") } func (UnimplementedEchoServer) mustEmbedUnimplementedEchoServer() {} // UnsafeEchoServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to EchoServer will // result in compilation errors. type UnsafeEchoServer interface { mustEmbedUnimplementedEchoServer() } func RegisterEchoServer(s grpc.ServiceRegistrar, srv EchoServer) { s.RegisterService(&Echo_ServiceDesc, srv) } func _Echo_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(EchoRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(EchoServer).Echo(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: Echo_Echo_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(EchoServer).Echo(ctx, req.(*EchoRequest)) } return interceptor(ctx, in, info, handler) } // Echo_ServiceDesc is the grpc.ServiceDesc for Echo service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var Echo_ServiceDesc = grpc.ServiceDesc{ ServiceName: "s2av2.example.proto.Echo", HandlerType: (*EchoServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "Echo", Handler: _Echo_Echo_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "example/proto/echo.proto", } s2a-go-0.1.8/example/server/000077500000000000000000000000001464711036600155615ustar00rootroot00000000000000s2a-go-0.1.8/example/server/server.go000066400000000000000000000032531464711036600174210ustar00rootroot00000000000000/* * * 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 main runs an Echo service. package main import ( "flag" "log" "net" "github.com/google/s2a-go" "github.com/google/s2a-go/example/echo" "google.golang.org/grpc" pb "github.com/google/s2a-go/example/proto/echo_go_proto" ) var ( port = flag.String("port", ":8080", "Echo service address port.") s2aAddr = flag.String("s2a_addr", "0.0.0.0:61365", "S2A service address.") ) func runServer(listenPort *string) { creds, err := s2a.NewServerCreds(&s2a.ServerOptions{ S2AAddress: *s2aAddr, VerificationMode: s2a.ConnectToGoogle, LocalIdentities: []s2a.Identity{s2a.NewHostname("test_rsa_server_identity")}, }) if err != nil { log.Fatalf("NewClientCreds() failed: %v", err) } listener, err := net.Listen("tcp", *port) if err != nil { log.Fatalf("Failed to listen on addres %s: %v", *port, err) } s := grpc.NewServer(grpc.Creds(creds)) log.Printf("Server: started gRPC Echo Server at: %s", *port) pb.RegisterEchoServer(s, &echo.Server{}) if err := s.Serve(listener); err != nil { log.Fatalf("Failed to serve: %v", err) } } func main() { runServer(port) } s2a-go-0.1.8/fallback/000077500000000000000000000000001464711036600143575ustar00rootroot00000000000000s2a-go-0.1.8/fallback/s2a_fallback.go000066400000000000000000000147751464711036600172300ustar00rootroot00000000000000/* * * Copyright 2023 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 fallback provides default implementations of fallback options when S2A fails. package fallback import ( "context" "crypto/tls" "fmt" "net" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" ) const ( alpnProtoStrH2 = "h2" alpnProtoStrHTTP = "http/1.1" defaultHTTPSPort = "443" ) // FallbackTLSConfigGRPC is a tls.Config used by the DefaultFallbackClientHandshakeFunc function. // It supports GRPC use case, thus the alpn is set to 'h2'. var FallbackTLSConfigGRPC = tls.Config{ MinVersion: tls.VersionTLS13, ClientSessionCache: nil, NextProtos: []string{alpnProtoStrH2}, } // FallbackTLSConfigHTTP is a tls.Config used by the DefaultFallbackDialerAndAddress func. // It supports the HTTP use case and the alpn is set to both 'http/1.1' and 'h2'. var FallbackTLSConfigHTTP = tls.Config{ MinVersion: tls.VersionTLS13, ClientSessionCache: nil, NextProtos: []string{alpnProtoStrH2, alpnProtoStrHTTP}, } // ClientHandshake establishes a TLS connection and returns it, plus its auth info. // Inputs: // // targetServer: the server attempted with S2A. // conn: the tcp connection to the server at address targetServer that was passed into S2A's ClientHandshake func. // If fallback is successful, the `conn` should be closed. // err: the error encountered when performing the client-side TLS handshake with S2A. type ClientHandshake func(ctx context.Context, targetServer string, conn net.Conn, err error) (net.Conn, credentials.AuthInfo, error) // DefaultFallbackClientHandshakeFunc returns a ClientHandshake function, // which establishes a TLS connection to the provided fallbackAddr, returns the new connection and its auth info. // Example use: // // transportCreds, _ = s2a.NewClientCreds(&s2a.ClientOptions{ // S2AAddress: s2aAddress, // FallbackOpts: &s2a.FallbackOptions{ // optional // FallbackClientHandshakeFunc: fallback.DefaultFallbackClientHandshakeFunc(fallbackAddr), // }, // }) // // The fallback server's certificate must be verifiable using OS root store. // The fallbackAddr is expected to be a network address, e.g. example.com:port. If port is not specified, // it uses default port 443. // In the returned function's TLS config, ClientSessionCache is explicitly set to nil to disable TLS resumption, // and min TLS version is set to 1.3. func DefaultFallbackClientHandshakeFunc(fallbackAddr string) (ClientHandshake, error) { var fallbackDialer = tls.Dialer{Config: &FallbackTLSConfigGRPC} return defaultFallbackClientHandshakeFuncInternal(fallbackAddr, fallbackDialer.DialContext) } func defaultFallbackClientHandshakeFuncInternal(fallbackAddr string, dialContextFunc func(context.Context, string, string) (net.Conn, error)) (ClientHandshake, error) { fallbackServerAddr, err := processFallbackAddr(fallbackAddr) if err != nil { if grpclog.V(1) { grpclog.Infof("error processing fallback address [%s]: %v", fallbackAddr, err) } return nil, err } return func(ctx context.Context, targetServer string, conn net.Conn, s2aErr error) (net.Conn, credentials.AuthInfo, error) { fbConn, fbErr := dialContextFunc(ctx, "tcp", fallbackServerAddr) if fbErr != nil { grpclog.Infof("dialing to fallback server %s failed: %v", fallbackServerAddr, fbErr) return nil, nil, fmt.Errorf("dialing to fallback server %s failed: %v; S2A client handshake with %s error: %w", fallbackServerAddr, fbErr, targetServer, s2aErr) } tc, success := fbConn.(*tls.Conn) if !success { grpclog.Infof("the connection with fallback server is expected to be tls but isn't") return nil, nil, fmt.Errorf("the connection with fallback server is expected to be tls but isn't; S2A client handshake with %s error: %w", targetServer, s2aErr) } tlsInfo := credentials.TLSInfo{ State: tc.ConnectionState(), CommonAuthInfo: credentials.CommonAuthInfo{ SecurityLevel: credentials.PrivacyAndIntegrity, }, } if grpclog.V(1) { grpclog.Infof("ConnectionState.NegotiatedProtocol: %v", tc.ConnectionState().NegotiatedProtocol) grpclog.Infof("ConnectionState.HandshakeComplete: %v", tc.ConnectionState().HandshakeComplete) grpclog.Infof("ConnectionState.ServerName: %v", tc.ConnectionState().ServerName) } conn.Close() return fbConn, tlsInfo, nil }, nil } // DefaultFallbackDialerAndAddress returns a TLS dialer and the network address to dial. // Example use: // // fallbackDialer, fallbackServerAddr := fallback.DefaultFallbackDialerAndAddress(fallbackAddr) // dialTLSContext := s2a.NewS2aDialTLSContextFunc(&s2a.ClientOptions{ // S2AAddress: s2aAddress, // required // FallbackOpts: &s2a.FallbackOptions{ // FallbackDialer: &s2a.FallbackDialer{ // Dialer: fallbackDialer, // ServerAddr: fallbackServerAddr, // }, // }, // }) // // The fallback server's certificate should be verifiable using OS root store. // The fallbackAddr is expected to be a network address, e.g. example.com:port. If port is not specified, // it uses default port 443. // In the returned function's TLS config, ClientSessionCache is explicitly set to nil to disable TLS resumption, // and min TLS version is set to 1.3. func DefaultFallbackDialerAndAddress(fallbackAddr string) (*tls.Dialer, string, error) { fallbackServerAddr, err := processFallbackAddr(fallbackAddr) if err != nil { if grpclog.V(1) { grpclog.Infof("error processing fallback address [%s]: %v", fallbackAddr, err) } return nil, "", err } return &tls.Dialer{Config: &FallbackTLSConfigHTTP}, fallbackServerAddr, nil } func processFallbackAddr(fallbackAddr string) (string, error) { var fallbackServerAddr string var err error if fallbackAddr == "" { return "", fmt.Errorf("empty fallback address") } _, _, err = net.SplitHostPort(fallbackAddr) if err != nil { // fallbackAddr does not have port suffix fallbackServerAddr = net.JoinHostPort(fallbackAddr, defaultHTTPSPort) } else { // FallbackServerAddr already has port suffix fallbackServerAddr = fallbackAddr } return fallbackServerAddr, nil } s2a-go-0.1.8/fallback/s2a_fallback_test.go000066400000000000000000000106351464711036600202560ustar00rootroot00000000000000/* * * Copyright 2023 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 fallback import ( "context" "fmt" "net" "reflect" "testing" ) func TestDefaultFallbackClientHandshakeFunc(t *testing.T) { testDialContextFunc := func(context.Context, string, string) (net.Conn, error) { return nil, fmt.Errorf("testDialError") } for _, tc := range []struct { desc string inputFallbackAddr string funcInitialized bool expectedAddr string expectNilErr bool }{ { "working case, fallback address has port suffix", "example.com:443", true, "example.com:443", true, }, { "working case, fallback address has no port suffix", "example.com", true, "example.com:443", true, }, { "working case, IP address, with port", "192.168.1.1:443", true, "192.168.1.1:443", true, }, { "working case, IP address, no port", "192.168.1.1", true, "192.168.1.1:443", true, }, { "working case, IPv6 address, with port", "[2001:db8::1]:443", true, "[2001:db8::1]:443", true, }, { "working case, IPv6 address, no port", "2001:db8::1", true, "[2001:db8::1]:443", true, }, { "test empty fallback address", "", false, "", false, }, } { fbFunc, err := defaultFallbackClientHandshakeFuncInternal(tc.inputFallbackAddr, testDialContextFunc) if got, want := fbFunc != nil, tc.funcInitialized; got != want { t.Errorf("%v: fallback handshake func is initialized=[%v], want [%v]", tc.desc, got, want) } if got, want := err == nil, tc.expectNilErr; got != want { t.Errorf("%v: got error [%v], want nil error [%v]", tc.desc, err, want) } if err == nil { _, _, err := fbFunc(context.TODO(), "", nil, fmt.Errorf("testS2AError")) if err == nil { t.Errorf("%v: expecting an error from the test dial function, got nil instead", tc.desc) } expectedErr := fmt.Sprintf("dialing to fallback server %s failed: testDialError; S2A client handshake with error: testS2AError", tc.expectedAddr) if got, want := err.Error(), expectedErr; got != want { t.Errorf("%v: fallback handshake got error [%v], want error [%v]", tc.desc, got, want) } } } } func TestDefaultFallbackDialerAndAddress(t *testing.T) { for _, tc := range []struct { desc string inputFallbackAddr string dialerInitialized bool expectedAddr string expectNilErr bool }{ { "working case, fallback address has port suffix", "example.com:443", true, "example.com:443", true, }, { "working case, fallback address has no port suffix", "example.com", true, "example.com:443", true, }, { "working case, IP address, with port", "192.168.1.1:443", true, "192.168.1.1:443", true, }, { "working case, IP address, no port", "192.168.1.1", true, "192.168.1.1:443", true, }, { "working case, IPv6 address, with port", "[2001:db8::1]:443", true, "[2001:db8::1]:443", true, }, { "working case, IPv6 address, no port", "2001:db8::1", true, "[2001:db8::1]:443", true, }, { "test empty fallback address", "", false, "", false, }, } { fbDialer, fbAddr, err := DefaultFallbackDialerAndAddress(tc.inputFallbackAddr) if got, want := fbDialer != nil, tc.dialerInitialized; got != want { t.Errorf("%v: fallback dialer is initialized=[%v], want [%v]", tc.desc, got, want) } if got, want := fbAddr, tc.expectedAddr; got != want { t.Errorf("%v: returned fallback address=[%v], want [%v]", tc.desc, got, want) } if got, want := err == nil, tc.expectNilErr; got != want { t.Errorf("%v: got error [%v], want nil error [%v]", tc.desc, err, want) } if err == nil { if !reflect.DeepEqual(fbDialer.Config, &FallbackTLSConfigHTTP) { t.Errorf("%v: unexpected tls config from fallback dialer: [%v], expected: [%v]", tc.desc, fbDialer.Config, &FallbackTLSConfigHTTP) } } } } s2a-go-0.1.8/go.mod000066400000000000000000000032571464711036600137350ustar00rootroot00000000000000module github.com/google/s2a-go go 1.20 require ( cloud.google.com/go/translate v1.10.3 github.com/google/go-cmp v0.6.0 golang.org/x/crypto v0.22.0 golang.org/x/sync v0.7.0 google.golang.org/api v0.177.0 google.golang.org/appengine v1.6.8 google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.34.2 ) require ( cloud.google.com/go v0.112.2 // indirect cloud.google.com/go/auth v0.3.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/longrunning v0.5.6 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.3 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/net v0.24.0 // indirect golang.org/x/oauth2 v0.19.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 // indirect ) s2a-go-0.1.8/go.sum000066400000000000000000000425611464711036600137630ustar00rootroot00000000000000cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.112.2 h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw= cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= cloud.google.com/go/auth v0.3.0 h1:PRyzEpGfx/Z9e8+lHsbkoUVXD0gnu4MNmm7Gp8TQNIs= cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/longrunning v0.5.6 h1:xAe8+0YaWoCKr9t1+aWe+OeQgN/iJK1fEgZSXmjuEaE= cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= cloud.google.com/go/translate v1.10.3 h1:g+B29z4gtRGsiKDoTF+bNeH25bLRokAaElygX2FcZkE= cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.177.0 h1:8a0p/BbPa65GlqGWtUKxot4p0TV8OGOfyTjtmkXNXmk= google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6 h1:DTJM0R8LECCgFeUwApvcEJHz85HLagW8uRENYxHh1ww= google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6/go.mod h1:10yRODfgim2/T8csjQsMPgZOMvtytXKTDRzH6HRGzRw= google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE= google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= s2a-go-0.1.8/internal/000077500000000000000000000000001464711036600144345ustar00rootroot00000000000000s2a-go-0.1.8/internal/authinfo/000077500000000000000000000000001464711036600162515ustar00rootroot00000000000000s2a-go-0.1.8/internal/authinfo/authinfo.go000066400000000000000000000077301464711036600204240ustar00rootroot00000000000000/* * * Copyright 2021 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 authinfo provides authentication and authorization information that // results from the TLS handshake. package authinfo import ( "errors" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" contextpb "github.com/google/s2a-go/internal/proto/s2a_context_go_proto" grpcpb "github.com/google/s2a-go/internal/proto/s2a_go_proto" "google.golang.org/grpc/credentials" ) var _ credentials.AuthInfo = (*S2AAuthInfo)(nil) const s2aAuthType = "s2a" // S2AAuthInfo exposes authentication and authorization information from the // S2A session result to the gRPC stack. type S2AAuthInfo struct { s2aContext *contextpb.S2AContext commonAuthInfo credentials.CommonAuthInfo } // NewS2AAuthInfo returns a new S2AAuthInfo object from the S2A session result. func NewS2AAuthInfo(result *grpcpb.SessionResult) (credentials.AuthInfo, error) { return newS2AAuthInfo(result) } func newS2AAuthInfo(result *grpcpb.SessionResult) (*S2AAuthInfo, error) { if result == nil { return nil, errors.New("NewS2aAuthInfo given nil session result") } return &S2AAuthInfo{ s2aContext: &contextpb.S2AContext{ ApplicationProtocol: result.GetApplicationProtocol(), TlsVersion: result.GetState().GetTlsVersion(), Ciphersuite: result.GetState().GetTlsCiphersuite(), PeerIdentity: result.GetPeerIdentity(), LocalIdentity: result.GetLocalIdentity(), PeerCertFingerprint: result.GetPeerCertFingerprint(), LocalCertFingerprint: result.GetLocalCertFingerprint(), IsHandshakeResumed: result.GetState().GetIsHandshakeResumed(), }, commonAuthInfo: credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}, }, nil } // AuthType returns the authentication type. func (s *S2AAuthInfo) AuthType() string { return s2aAuthType } // ApplicationProtocol returns the application protocol, e.g. "grpc". func (s *S2AAuthInfo) ApplicationProtocol() string { return s.s2aContext.GetApplicationProtocol() } // TLSVersion returns the TLS version negotiated during the handshake. func (s *S2AAuthInfo) TLSVersion() commonpb.TLSVersion { return s.s2aContext.GetTlsVersion() } // Ciphersuite returns the ciphersuite negotiated during the handshake. func (s *S2AAuthInfo) Ciphersuite() commonpb.Ciphersuite { return s.s2aContext.GetCiphersuite() } // PeerIdentity returns the authenticated identity of the peer. func (s *S2AAuthInfo) PeerIdentity() *commonpb.Identity { return s.s2aContext.GetPeerIdentity() } // LocalIdentity returns the local identity of the application used during // session setup. func (s *S2AAuthInfo) LocalIdentity() *commonpb.Identity { return s.s2aContext.GetLocalIdentity() } // PeerCertFingerprint returns the SHA256 hash of the peer certificate used in // the S2A handshake. func (s *S2AAuthInfo) PeerCertFingerprint() []byte { return s.s2aContext.GetPeerCertFingerprint() } // LocalCertFingerprint returns the SHA256 hash of the local certificate used // in the S2A handshake. func (s *S2AAuthInfo) LocalCertFingerprint() []byte { return s.s2aContext.GetLocalCertFingerprint() } // IsHandshakeResumed returns true if a cached session was used to resume // the handshake. func (s *S2AAuthInfo) IsHandshakeResumed() bool { return s.s2aContext.GetIsHandshakeResumed() } // SecurityLevel returns the security level of the connection. func (s *S2AAuthInfo) SecurityLevel() credentials.SecurityLevel { return s.commonAuthInfo.SecurityLevel } s2a-go-0.1.8/internal/authinfo/authinfo_test.go000066400000000000000000000141441464711036600214600ustar00rootroot00000000000000/* * * Copyright 2021 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 authinfo import ( "bytes" "testing" "google.golang.org/grpc/credentials" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" grpcpb "github.com/google/s2a-go/internal/proto/s2a_go_proto" ) func TestS2AAuthInfo(t *testing.T) { for _, tc := range []struct { desc string sessionResult *grpcpb.SessionResult outAppProtocol string outTLSVersion commonpb.TLSVersion outCiphersuite commonpb.Ciphersuite outPeerIdentity *commonpb.Identity outLocalIdentity *commonpb.Identity outPeerCertFingerprint []byte outLocalCertFingerprint []byte outIsHandshakeResumed bool outErr bool }{ { desc: "basic 1", sessionResult: &grpcpb.SessionResult{ ApplicationProtocol: "app protocol", State: &grpcpb.SessionState{ TlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, IsHandshakeResumed: true, }, PeerIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "peer spiffe identity", }, }, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "local hostname", }, }, PeerCertFingerprint: []byte("peer cert fingerprint"), LocalCertFingerprint: []byte("local cert fingerprint"), }, outAppProtocol: "app protocol", outTLSVersion: commonpb.TLSVersion_TLS1_3, outCiphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, outPeerIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "peer spiffe identity", }, }, outLocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "local hostname", }, }, outPeerCertFingerprint: []byte("peer cert fingerprint"), outLocalCertFingerprint: []byte("local cert fingerprint"), outIsHandshakeResumed: true, }, { desc: "basic 2", sessionResult: &grpcpb.SessionResult{ ApplicationProtocol: "app protocol", State: &grpcpb.SessionState{ TlsVersion: commonpb.TLSVersion_TLS1_2, TlsCiphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, PeerIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "local hostname", }, }, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "peer spiffe identity", }, }, PeerCertFingerprint: []byte("peer cert fingerprint"), LocalCertFingerprint: []byte("local cert fingerprint"), }, outAppProtocol: "app protocol", outTLSVersion: commonpb.TLSVersion_TLS1_2, outCiphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, outPeerIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "local hostname", }, }, outLocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "peer spiffe identity", }, }, outPeerCertFingerprint: []byte("peer cert fingerprint"), outLocalCertFingerprint: []byte("local cert fingerprint"), }, { desc: "nil identities and fingerprints", sessionResult: &grpcpb.SessionResult{ ApplicationProtocol: "app protocol", State: &grpcpb.SessionState{ TlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, outAppProtocol: "app protocol", outTLSVersion: commonpb.TLSVersion_TLS1_3, outCiphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, { desc: "nil session result", outErr: true, }, } { t.Run(tc.desc, func(t *testing.T) { authInfo, err := newS2AAuthInfo(tc.sessionResult) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("NewS2AAuthInfo(%v) = (err=nil) = %v, want %v", tc.sessionResult, got, want) } if err == nil { if got, want := authInfo.AuthType(), s2aAuthType; got != want { t.Errorf("authInfo.AuthType() = %v, want %v", got, want) } if got, want := authInfo.ApplicationProtocol(), tc.outAppProtocol; got != want { t.Errorf("authInfo.ApplicationProtocol() = %v, want %v", got, want) } if got, want := authInfo.TLSVersion(), tc.outTLSVersion; got != want { t.Errorf("authInfo.TLSVersion() = %v, want %v", got, want) } if got, want := authInfo.Ciphersuite(), tc.outCiphersuite; got != want { t.Errorf("authInfo.Ciphersuite() = %v, want %v", got, want) } if got, want := authInfo.PeerIdentity().String(), tc.outPeerIdentity.String(); got != want { t.Errorf("authInfo.PeerIdentity() = %v, want %v", got, want) } if got, want := authInfo.LocalIdentity().String(), tc.outLocalIdentity.String(); got != want { t.Errorf("authInfo.LocalIdentity() = %v, want %v", got, want) } if got, want := authInfo.PeerCertFingerprint(), tc.outPeerCertFingerprint; !bytes.Equal(got, want) { t.Errorf("authinfo.PeerCertFingerprint() = %v, want %v", got, want) } if got, want := authInfo.LocalCertFingerprint(), tc.outLocalCertFingerprint; !bytes.Equal(got, want) { t.Errorf("authinfo.LocalCertFingerprint() = %v, want %v", got, want) } if got, want := authInfo.IsHandshakeResumed(), tc.outIsHandshakeResumed; got != want { t.Errorf("authinfo.IsHandshakeResumed() = %v, want %v", got, want) } if got, want := authInfo.SecurityLevel(), credentials.PrivacyAndIntegrity; got != want { t.Errorf("authInfo.SecurityLevel() = %v, want %v", got, want) } } }) } } s2a-go-0.1.8/internal/fakehandshaker/000077500000000000000000000000001464711036600173735ustar00rootroot00000000000000s2a-go-0.1.8/internal/fakehandshaker/service/000077500000000000000000000000001464711036600210335ustar00rootroot00000000000000s2a-go-0.1.8/internal/fakehandshaker/service/s2a_service.go000066400000000000000000000226441464711036600235770ustar00rootroot00000000000000/* * * Copyright 2021 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 service is a fake S2A handshaker service. package service import ( "bytes" "fmt" "os" "google.golang.org/grpc/codes" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" ) type handshakeState int const ( // initial is the state of the handshaker service before any handshake // message has been received. initial handshakeState = 0 // started is the state of the handshaker service when the handshake has // been initiated but no bytes have been sent or received. started handshakeState = 1 // sent is the state of the handshaker service when the handshake has been // initiated and bytes have been sent. sent handshakeState = 2 // completed is the state of the handshaker service when the handshake has // been completed. completed handshakeState = 3 ) const ( accessTokenEnvVariable = "S2A_ACCESS_TOKEN" grpcAppProtocol = "grpc" clientHelloFrame = "ClientHello" clientFinishedFrame = "ClientFinished" serverFrame = "ServerHelloAndFinished" ) const ( inKey = "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk" outKey = "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk" ) // FakeHandshakerService implements the s2apb.S2AServiceServer. The fake // handshaker service should not be used by more than 1 application at a time. type FakeHandshakerService struct { s2apb.S2AServiceServer assistingClient bool state handshakeState peerIdentity *commonpb.Identity localIdentity *commonpb.Identity } // SetUpSession sets up the S2A session. func (hs *FakeHandshakerService) SetUpSession(stream s2apb.S2AService_SetUpSessionServer) error { for { sessionReq, err := stream.Recv() if err != nil { return fmt.Errorf("stream recv failed: %v", err) } if err := hs.authenticateRequest(sessionReq); err != nil { return fmt.Errorf("S2A cannot authenticate the request: %v", err) } var resp *s2apb.SessionResp receivedTicket := false switch req := sessionReq.ReqOneof.(type) { case *s2apb.SessionReq_ClientStart: resp = hs.processClientStart(req) case *s2apb.SessionReq_ServerStart: resp = hs.processServerStart(req) case *s2apb.SessionReq_Next: resp = hs.processNext(req) case *s2apb.SessionReq_ResumptionTicket: resp = hs.processResumptionTicket(req) receivedTicket = true default: return fmt.Errorf("session request has unexpected type %T", req) } if err = stream.Send(resp); err != nil { return fmt.Errorf("stream send failed: %v", err) } if receivedTicket || resp.GetResult() != nil { return nil } } } // processClientStart processes a ClientSessionStartReq. func (hs *FakeHandshakerService) processClientStart(req *s2apb.SessionReq_ClientStart) *s2apb.SessionResp { resp := s2apb.SessionResp{} if hs.state != initial { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.FailedPrecondition), Details: "client start handshake not in initial state", } return &resp } if len(req.ClientStart.GetApplicationProtocols()) != 1 || req.ClientStart.GetApplicationProtocols()[0] != grpcAppProtocol { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.InvalidArgument), Details: "application protocol was not grpc", } return &resp } if req.ClientStart.GetMaxTlsVersion() != commonpb.TLSVersion_TLS1_3 { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.InvalidArgument), Details: "max TLS version must be 1.3", } return &resp } if req.ClientStart.GetMinTlsVersion() != commonpb.TLSVersion_TLS1_3 { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.InvalidArgument), Details: "min TLS version must be 1.3", } return &resp } resp.OutFrames = []byte(clientHelloFrame) resp.BytesConsumed = 0 resp.Status = &s2apb.SessionStatus{Code: uint32(codes.OK)} hs.localIdentity = req.ClientStart.LocalIdentity if len(req.ClientStart.TargetIdentities) > 0 { hs.peerIdentity = req.ClientStart.TargetIdentities[0] } hs.assistingClient = true hs.state = sent return &resp } // processServerStart processes a ServerSessionStartReq. func (hs *FakeHandshakerService) processServerStart(req *s2apb.SessionReq_ServerStart) *s2apb.SessionResp { resp := s2apb.SessionResp{} if hs.state != initial { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.FailedPrecondition), Details: "server start handshake not in initial state", } return &resp } if len(req.ServerStart.GetApplicationProtocols()) != 1 || req.ServerStart.GetApplicationProtocols()[0] != grpcAppProtocol { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.InvalidArgument), Details: "application protocol was not grpc", } return &resp } if req.ServerStart.GetMaxTlsVersion() != commonpb.TLSVersion_TLS1_3 { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.InvalidArgument), Details: "max TLS version must be 1.3", } return &resp } if req.ServerStart.GetMinTlsVersion() != commonpb.TLSVersion_TLS1_3 { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.InvalidArgument), Details: "min TLS version must be 1.3", } return &resp } if len(req.ServerStart.InBytes) == 0 { resp.BytesConsumed = 0 hs.state = started } else if bytes.Equal(req.ServerStart.InBytes, []byte(clientHelloFrame)) { resp.OutFrames = []byte(serverFrame) resp.BytesConsumed = uint32(len(clientHelloFrame)) hs.state = sent } else { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.Internal), Details: "server start request did not have the correct input bytes", } return &resp } resp.Status = &s2apb.SessionStatus{Code: uint32(codes.OK)} if len(req.ServerStart.LocalIdentities) > 0 { hs.localIdentity = req.ServerStart.LocalIdentities[0] } hs.assistingClient = false return &resp } // processNext processes a SessionNext request. func (hs *FakeHandshakerService) processNext(req *s2apb.SessionReq_Next) *s2apb.SessionResp { resp := s2apb.SessionResp{} if hs.assistingClient { if hs.state != sent { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.FailedPrecondition), Details: "client handshake was not in sent state", } return &resp } if !bytes.Equal(req.Next.InBytes, []byte(serverFrame)) { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.Internal), Details: "client request did not match server frame", } return &resp } resp.OutFrames = []byte(clientFinishedFrame) resp.BytesConsumed = uint32(len(serverFrame)) hs.state = completed } else { if hs.state == started { if !bytes.Equal(req.Next.InBytes, []byte(clientHelloFrame)) { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.Internal), Details: "server request did not match client hello frame", } return &resp } resp.OutFrames = []byte(serverFrame) resp.BytesConsumed = uint32(len(clientHelloFrame)) hs.state = sent } else if hs.state == sent { if !bytes.Equal(req.Next.InBytes[:len(clientFinishedFrame)], []byte(clientFinishedFrame)) { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.Internal), Details: "server request did not match client finished frame", } return &resp } resp.BytesConsumed = uint32(len(clientFinishedFrame)) hs.state = completed } else { resp.Status = &s2apb.SessionStatus{ Code: uint32(codes.FailedPrecondition), Details: "server request was not in expected state", } return &resp } } resp.Status = &s2apb.SessionStatus{Code: uint32(codes.OK)} if hs.state == completed { resp.Result = hs.getSessionResult() } return &resp } // processResumptionTicket processes a ResumptionTicketReq request. func (hs *FakeHandshakerService) processResumptionTicket(req *s2apb.SessionReq_ResumptionTicket) *s2apb.SessionResp { return &s2apb.SessionResp{ Status: &s2apb.SessionStatus{Code: uint32(codes.OK)}, } } // getSessionResult returns a dummy SessionResult. func (hs *FakeHandshakerService) getSessionResult() *s2apb.SessionResult { res := s2apb.SessionResult{} res.ApplicationProtocol = grpcAppProtocol res.State = &s2apb.SessionState{ TlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, InKey: []byte(inKey), OutKey: []byte(outKey), } res.PeerIdentity = hs.peerIdentity res.LocalIdentity = hs.localIdentity return &res } func (hs *FakeHandshakerService) authenticateRequest(request *s2apb.SessionReq) error { // If the S2A_ACCESS_TOKEN environment variable has not been set, then do not // enforce anything on the request. acceptedToken := os.Getenv(accessTokenEnvVariable) if acceptedToken == "" { return nil } if len(request.GetAuthMechanisms()) == 0 { return fmt.Errorf("expected token but none was received") } for _, authMechanism := range request.GetAuthMechanisms() { if authMechanism.GetToken() != acceptedToken { return fmt.Errorf("received token: %s, expected token: %s", authMechanism.GetToken(), acceptedToken) } } return nil } s2a-go-0.1.8/internal/fakehandshaker/service/s2a_service_test.go000066400000000000000000000270131464711036600246310ustar00rootroot00000000000000/* * * Copyright 2021 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 service import ( "errors" "os" "strings" "testing" "github.com/google/go-cmp/cmp" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/protobuf/testing/protocmp" ) const ( testAccessToken = "test_access_token" ) type fakeS2ASetupSessionServer struct { grpc.ServerStream recvCount int reqs []*s2apb.SessionReq resps []*s2apb.SessionResp } func (f *fakeS2ASetupSessionServer) Send(resp *s2apb.SessionResp) error { f.resps = append(f.resps, resp) return nil } func (f *fakeS2ASetupSessionServer) Recv() (*s2apb.SessionReq, error) { if f.recvCount == len(f.reqs) { return nil, errors.New("request buffer was fully exhausted") } req := f.reqs[f.recvCount] f.recvCount++ return req, nil } func TestSetupSession(t *testing.T) { os.Setenv(accessTokenEnvVariable, "") for _, tc := range []struct { desc string // Note that outResps[i] is the output for reqs[i]. reqs []*s2apb.SessionReq outResps []*s2apb.SessionResp hasNonOKStatus bool }{ { desc: "client failure no app protocols", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ClientStart{ ClientStart: &s2apb.ClientSessionStartReq{}, }, }, }, hasNonOKStatus: true, }, { desc: "client failure non initial state", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ClientStart{ ClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{grpcAppProtocol}, MinTlsVersion: commonpb.TLSVersion_TLS1_3, MaxTlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuites: []commonpb.Ciphersuite{ commonpb.Ciphersuite_AES_128_GCM_SHA256, commonpb.Ciphersuite_AES_256_GCM_SHA384, commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, }, }, { ReqOneof: &s2apb.SessionReq_ClientStart{ ClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{grpcAppProtocol}, MinTlsVersion: commonpb.TLSVersion_TLS1_3, MaxTlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuites: []commonpb.Ciphersuite{ commonpb.Ciphersuite_AES_128_GCM_SHA256, commonpb.Ciphersuite_AES_256_GCM_SHA384, commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, }, }, }, outResps: []*s2apb.SessionResp{ { OutFrames: []byte(clientHelloFrame), Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, }, hasNonOKStatus: true, }, { desc: "client test", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ClientStart{ ClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{grpcAppProtocol}, MinTlsVersion: commonpb.TLSVersion_TLS1_3, MaxTlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuites: []commonpb.Ciphersuite{ commonpb.Ciphersuite_AES_128_GCM_SHA256, commonpb.Ciphersuite_AES_256_GCM_SHA384, commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{Hostname: "local hostname"}, }, TargetIdentities: []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_SpiffeId{SpiffeId: "peer spiffe identity"}, }, }, }, }, }, { ReqOneof: &s2apb.SessionReq_Next{ Next: &s2apb.SessionNextReq{ InBytes: []byte(serverFrame), }, }, }, }, outResps: []*s2apb.SessionResp{ { OutFrames: []byte(clientHelloFrame), Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, { OutFrames: []byte(clientFinishedFrame), BytesConsumed: uint32(len(serverFrame)), Result: &s2apb.SessionResult{ ApplicationProtocol: grpcAppProtocol, State: &s2apb.SessionState{ TlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, InKey: []byte(inKey), OutKey: []byte(outKey), }, PeerIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{SpiffeId: "peer spiffe identity"}, }, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{Hostname: "local hostname"}, }, }, Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, }, }, { desc: "server failure no app protocols", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ServerStart{ ServerStart: &s2apb.ServerSessionStartReq{}, }, }, }, hasNonOKStatus: true, }, { desc: "server failure non initial state", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ServerStart{ ServerStart: &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{grpcAppProtocol}, MinTlsVersion: commonpb.TLSVersion_TLS1_3, MaxTlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuites: []commonpb.Ciphersuite{ commonpb.Ciphersuite_AES_128_GCM_SHA256, commonpb.Ciphersuite_AES_256_GCM_SHA384, commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, }, }, { ReqOneof: &s2apb.SessionReq_ServerStart{ ServerStart: &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{grpcAppProtocol}, MinTlsVersion: commonpb.TLSVersion_TLS1_3, MaxTlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuites: []commonpb.Ciphersuite{ commonpb.Ciphersuite_AES_128_GCM_SHA256, commonpb.Ciphersuite_AES_256_GCM_SHA384, commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, }, }, }, outResps: []*s2apb.SessionResp{ { Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, }, hasNonOKStatus: true, }, { desc: "server test", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ServerStart{ ServerStart: &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{grpcAppProtocol}, MinTlsVersion: commonpb.TLSVersion_TLS1_3, MaxTlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuites: []commonpb.Ciphersuite{ commonpb.Ciphersuite_AES_128_GCM_SHA256, commonpb.Ciphersuite_AES_256_GCM_SHA384, commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, }, InBytes: []byte(clientHelloFrame), LocalIdentities: []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{Hostname: "local hostname"}, }, }, }, }, }, { ReqOneof: &s2apb.SessionReq_Next{ Next: &s2apb.SessionNextReq{ InBytes: []byte(clientFinishedFrame), }, }, }, }, outResps: []*s2apb.SessionResp{ { OutFrames: []byte(serverFrame), BytesConsumed: uint32(len(clientHelloFrame)), Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, { BytesConsumed: uint32(len(clientFinishedFrame)), Result: &s2apb.SessionResult{ ApplicationProtocol: grpcAppProtocol, State: &s2apb.SessionState{ TlsVersion: commonpb.TLSVersion_TLS1_3, TlsCiphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, InKey: []byte(inKey), OutKey: []byte(outKey), }, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{Hostname: "local hostname"}, }, }, Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, }, }, { desc: "resumption ticket test", reqs: []*s2apb.SessionReq{ { ReqOneof: &s2apb.SessionReq_ResumptionTicket{ ResumptionTicket: &s2apb.ResumptionTicketReq{ ConnectionId: 1234, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{Hostname: "local hostname"}, }, }, }, }, }, outResps: []*s2apb.SessionResp{ { Status: &s2apb.SessionStatus{ Code: uint32(codes.OK), }, }, }, hasNonOKStatus: false, }, } { t.Run(tc.desc, func(t *testing.T) { hs := FakeHandshakerService{} stream := &fakeS2ASetupSessionServer{reqs: tc.reqs} if got, want := hs.SetUpSession(stream) == nil, !tc.hasNonOKStatus; got != want { t.Errorf("hs.SetUpSession(%v) = (err=nil) = %v, want %v", stream, got, want) } hasNonOKStatus := false for i := range tc.reqs { if stream.resps[i].GetStatus().GetCode() != uint32(codes.OK) { hasNonOKStatus = true break } if got, want := stream.resps[i], tc.outResps[i]; !cmp.Equal(got, want, protocmp.Transform()) { t.Fatalf("stream.resps[%d] = %v, want %v", i, got, want) } } if got, want := hasNonOKStatus, tc.hasNonOKStatus; got != want { t.Errorf("hasNonOKStatus = %v, want %v", got, want) } }) } } func TestAuthenticateRequest(t *testing.T) { for _, tc := range []struct { description string acceptedToken string request *s2apb.SessionReq expectedError string }{ { description: "access token env variable is not set", }, { description: "request contains valid token", acceptedToken: testAccessToken, request: &s2apb.SessionReq{ AuthMechanisms: []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, }, { description: "request contains invalid token", acceptedToken: testAccessToken, request: &s2apb.SessionReq{ AuthMechanisms: []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: "bad_access_token", }, }, }, }, expectedError: "received token: bad_access_token, expected token: test_access_token", }, { description: "request contains valid and invalid tokens", acceptedToken: testAccessToken, request: &s2apb.SessionReq{ AuthMechanisms: []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: "bad_access_token", }, }, }, }, expectedError: "received token: bad_access_token, expected token: test_access_token", }, } { t.Run(tc.description, func(t *testing.T) { os.Setenv(accessTokenEnvVariable, tc.acceptedToken) hs := &FakeHandshakerService{} err := hs.authenticateRequest(tc.request) if got, want := (err == nil), (tc.expectedError == ""); got != want { t.Errorf("(err == nil): %t, (tc.expectedError == \"\"): %t", got, want) } if err != nil && !strings.Contains(err.Error(), tc.expectedError) { t.Errorf("hs.authenticateRequest(%v)=%v, expected error to have substring: %v", tc.request, err, tc.expectedError) } }) } } s2a-go-0.1.8/internal/handshaker/000077500000000000000000000000001464711036600165445ustar00rootroot00000000000000s2a-go-0.1.8/internal/handshaker/handshaker.go000066400000000000000000000401741464711036600212110ustar00rootroot00000000000000/* * * Copyright 2021 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 handshaker communicates with the S2A handshaker service. package handshaker import ( "context" "errors" "fmt" "io" "net" "sync" "github.com/google/s2a-go/internal/authinfo" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" "github.com/google/s2a-go/internal/record" "github.com/google/s2a-go/internal/tokenmanager" grpc "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" ) var ( // appProtocol contains the application protocol accepted by the handshaker. appProtocol = "grpc" // frameLimit is the maximum size of a frame in bytes. frameLimit = 1024 * 64 // peerNotRespondingError is the error thrown when the peer doesn't respond. errPeerNotResponding = errors.New("peer is not responding and re-connection should be attempted") ) // Handshaker defines a handshaker interface. type Handshaker interface { // ClientHandshake starts and completes a TLS handshake from the client side, // and returns a secure connection along with additional auth information. ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) // ServerHandshake starts and completes a TLS handshake from the server side, // and returns a secure connection along with additional auth information. ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) // Close terminates the Handshaker. It should be called when the handshake // is complete. Close() error } // ClientHandshakerOptions contains the options needed to configure the S2A // handshaker service on the client-side. type ClientHandshakerOptions struct { // MinTLSVersion specifies the min TLS version supported by the client. MinTLSVersion commonpb.TLSVersion // MaxTLSVersion specifies the max TLS version supported by the client. MaxTLSVersion commonpb.TLSVersion // TLSCiphersuites is the ordered list of ciphersuites supported by the // client. TLSCiphersuites []commonpb.Ciphersuite // TargetIdentities contains a list of allowed server identities. One of the // target identities should match the peer identity in the handshake // result; otherwise, the handshake fails. TargetIdentities []*commonpb.Identity // LocalIdentity is the local identity of the client application. If none is // provided, then the S2A will choose the default identity. LocalIdentity *commonpb.Identity // TargetName is the allowed server name, which may be used for server // authorization check by the S2A if it is provided. TargetName string // EnsureProcessSessionTickets allows users to wait and ensure that all // available session tickets are sent to S2A before a process completes. EnsureProcessSessionTickets *sync.WaitGroup } // ServerHandshakerOptions contains the options needed to configure the S2A // handshaker service on the server-side. type ServerHandshakerOptions struct { // MinTLSVersion specifies the min TLS version supported by the server. MinTLSVersion commonpb.TLSVersion // MaxTLSVersion specifies the max TLS version supported by the server. MaxTLSVersion commonpb.TLSVersion // TLSCiphersuites is the ordered list of ciphersuites supported by the // server. TLSCiphersuites []commonpb.Ciphersuite // LocalIdentities is the list of local identities that may be assumed by // the server. If no local identity is specified, then the S2A chooses a // default local identity. LocalIdentities []*commonpb.Identity } // s2aHandshaker performs a TLS handshake using the S2A handshaker service. type s2aHandshaker struct { // stream is used to communicate with the S2A handshaker service. stream s2apb.S2AService_SetUpSessionClient // conn is the connection to the peer. conn net.Conn // clientOpts should be non-nil iff the handshaker is client-side. clientOpts *ClientHandshakerOptions // serverOpts should be non-nil iff the handshaker is server-side. serverOpts *ServerHandshakerOptions // isClient determines if the handshaker is client or server side. isClient bool // hsAddr stores the address of the S2A handshaker service. hsAddr string // tokenManager manages access tokens for authenticating to S2A. tokenManager tokenmanager.AccessTokenManager // localIdentities is the set of local identities for whom the // tokenManager should fetch a token when preparing a request to be // sent to S2A. localIdentities []*commonpb.Identity } // NewClientHandshaker creates an s2aHandshaker instance that performs a // client-side TLS handshake using the S2A handshaker service. func NewClientHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, hsAddr string, opts *ClientHandshakerOptions) (Handshaker, error) { stream, err := s2apb.NewS2AServiceClient(conn).SetUpSession(ctx, grpc.WaitForReady(true)) if err != nil { return nil, err } tokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() if err != nil { grpclog.Infof("failed to create single token access token manager: %v", err) } return newClientHandshaker(stream, c, hsAddr, opts, tokenManager), nil } func newClientHandshaker(stream s2apb.S2AService_SetUpSessionClient, c net.Conn, hsAddr string, opts *ClientHandshakerOptions, tokenManager tokenmanager.AccessTokenManager) *s2aHandshaker { var localIdentities []*commonpb.Identity if opts != nil { localIdentities = []*commonpb.Identity{opts.LocalIdentity} } return &s2aHandshaker{ stream: stream, conn: c, clientOpts: opts, isClient: true, hsAddr: hsAddr, tokenManager: tokenManager, localIdentities: localIdentities, } } // NewServerHandshaker creates an s2aHandshaker instance that performs a // server-side TLS handshake using the S2A handshaker service. func NewServerHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, hsAddr string, opts *ServerHandshakerOptions) (Handshaker, error) { stream, err := s2apb.NewS2AServiceClient(conn).SetUpSession(ctx, grpc.WaitForReady(true)) if err != nil { return nil, err } tokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() if err != nil { grpclog.Infof("failed to create single token access token manager: %v", err) } return newServerHandshaker(stream, c, hsAddr, opts, tokenManager), nil } func newServerHandshaker(stream s2apb.S2AService_SetUpSessionClient, c net.Conn, hsAddr string, opts *ServerHandshakerOptions, tokenManager tokenmanager.AccessTokenManager) *s2aHandshaker { var localIdentities []*commonpb.Identity if opts != nil { localIdentities = opts.LocalIdentities } return &s2aHandshaker{ stream: stream, conn: c, serverOpts: opts, isClient: false, hsAddr: hsAddr, tokenManager: tokenManager, localIdentities: localIdentities, } } // ClientHandshake performs a client-side TLS handshake using the S2A handshaker // service. When complete, returns a TLS connection. func (h *s2aHandshaker) ClientHandshake(_ context.Context) (net.Conn, credentials.AuthInfo, error) { if !h.isClient { return nil, nil, errors.New("only handshakers created using NewClientHandshaker can perform a client-side handshake") } // Extract the hostname from the target name. The target name is assumed to be an authority. hostname, _, err := net.SplitHostPort(h.clientOpts.TargetName) if err != nil { // If the target name had no host port or could not be parsed, use it as is. hostname = h.clientOpts.TargetName } // Prepare a client start message to send to the S2A handshaker service. req := &s2apb.SessionReq{ ReqOneof: &s2apb.SessionReq_ClientStart{ ClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{appProtocol}, MinTlsVersion: h.clientOpts.MinTLSVersion, MaxTlsVersion: h.clientOpts.MaxTLSVersion, TlsCiphersuites: h.clientOpts.TLSCiphersuites, TargetIdentities: h.clientOpts.TargetIdentities, LocalIdentity: h.clientOpts.LocalIdentity, TargetName: hostname, }, }, AuthMechanisms: h.getAuthMechanisms(), } conn, result, err := h.setUpSession(req) if err != nil { return nil, nil, err } authInfo, err := authinfo.NewS2AAuthInfo(result) if err != nil { return nil, nil, err } return conn, authInfo, nil } // ServerHandshake performs a server-side TLS handshake using the S2A handshaker // service. When complete, returns a TLS connection. func (h *s2aHandshaker) ServerHandshake(_ context.Context) (net.Conn, credentials.AuthInfo, error) { if h.isClient { return nil, nil, errors.New("only handshakers created using NewServerHandshaker can perform a server-side handshake") } p := make([]byte, frameLimit) n, err := h.conn.Read(p) if err != nil { return nil, nil, err } // Prepare a server start message to send to the S2A handshaker service. req := &s2apb.SessionReq{ ReqOneof: &s2apb.SessionReq_ServerStart{ ServerStart: &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{appProtocol}, MinTlsVersion: h.serverOpts.MinTLSVersion, MaxTlsVersion: h.serverOpts.MaxTLSVersion, TlsCiphersuites: h.serverOpts.TLSCiphersuites, LocalIdentities: h.serverOpts.LocalIdentities, InBytes: p[:n], }, }, AuthMechanisms: h.getAuthMechanisms(), } conn, result, err := h.setUpSession(req) if err != nil { return nil, nil, err } authInfo, err := authinfo.NewS2AAuthInfo(result) if err != nil { return nil, nil, err } return conn, authInfo, nil } // setUpSession proxies messages between the peer and the S2A handshaker // service. func (h *s2aHandshaker) setUpSession(req *s2apb.SessionReq) (net.Conn, *s2apb.SessionResult, error) { resp, err := h.accessHandshakerService(req) if err != nil { return nil, nil, err } // Check if the returned status is an error. if resp.GetStatus() != nil { if got, want := resp.GetStatus().Code, uint32(codes.OK); got != want { return nil, nil, fmt.Errorf("%v", resp.GetStatus().Details) } } // Calculate the extra unread bytes from the Session. Attempting to consume // more than the bytes sent will throw an error. var extra []byte if req.GetServerStart() != nil { if resp.GetBytesConsumed() > uint32(len(req.GetServerStart().GetInBytes())) { return nil, nil, errors.New("handshaker service consumed bytes value is out-of-bounds") } extra = req.GetServerStart().GetInBytes()[resp.GetBytesConsumed():] } result, extra, err := h.processUntilDone(resp, extra) if err != nil { return nil, nil, err } if result.GetLocalIdentity() == nil { return nil, nil, errors.New("local identity must be populated in session result") } // Create a new TLS record protocol using the Session Result. newConn, err := record.NewConn(&record.ConnParameters{ NetConn: h.conn, Ciphersuite: result.GetState().GetTlsCiphersuite(), TLSVersion: result.GetState().GetTlsVersion(), InTrafficSecret: result.GetState().GetInKey(), OutTrafficSecret: result.GetState().GetOutKey(), UnusedBuf: extra, InSequence: result.GetState().GetInSequence(), OutSequence: result.GetState().GetOutSequence(), HSAddr: h.hsAddr, ConnectionID: result.GetState().GetConnectionId(), LocalIdentity: result.GetLocalIdentity(), EnsureProcessSessionTickets: h.ensureProcessSessionTickets(), }) if err != nil { return nil, nil, err } return newConn, result, nil } func (h *s2aHandshaker) ensureProcessSessionTickets() *sync.WaitGroup { if h.clientOpts == nil { return nil } return h.clientOpts.EnsureProcessSessionTickets } // accessHandshakerService sends the session request to the S2A handshaker // service and returns the session response. func (h *s2aHandshaker) accessHandshakerService(req *s2apb.SessionReq) (*s2apb.SessionResp, error) { if err := h.stream.Send(req); err != nil { return nil, err } resp, err := h.stream.Recv() if err != nil { return nil, err } return resp, nil } // processUntilDone continues proxying messages between the peer and the S2A // handshaker service until the handshaker service returns the SessionResult at // the end of the handshake or an error occurs. func (h *s2aHandshaker) processUntilDone(resp *s2apb.SessionResp, unusedBytes []byte) (*s2apb.SessionResult, []byte, error) { for { if len(resp.OutFrames) > 0 { if _, err := h.conn.Write(resp.OutFrames); err != nil { return nil, nil, err } } if resp.Result != nil { return resp.Result, unusedBytes, nil } buf := make([]byte, frameLimit) n, err := h.conn.Read(buf) if err != nil && err != io.EOF { return nil, nil, err } // If there is nothing to send to the handshaker service and nothing is // received from the peer, then we are stuck. This covers the case when // the peer is not responding. Note that handshaker service connection // issues are caught in accessHandshakerService before we even get // here. if len(resp.OutFrames) == 0 && n == 0 { return nil, nil, errPeerNotResponding } // Append extra bytes from the previous interaction with the handshaker // service with the current buffer read from conn. p := append(unusedBytes, buf[:n]...) // From here on, p and unusedBytes point to the same slice. resp, err = h.accessHandshakerService(&s2apb.SessionReq{ ReqOneof: &s2apb.SessionReq_Next{ Next: &s2apb.SessionNextReq{ InBytes: p, }, }, AuthMechanisms: h.getAuthMechanisms(), }) if err != nil { return nil, nil, err } // Cache the local identity returned by S2A, if it is populated. This // overwrites any existing local identities. This is done because, once the // S2A has selected a local identity, then only that local identity should // be asserted in future requests until the end of the current handshake. if resp.GetLocalIdentity() != nil { h.localIdentities = []*commonpb.Identity{resp.GetLocalIdentity()} } // Set unusedBytes based on the handshaker service response. if resp.GetBytesConsumed() > uint32(len(p)) { return nil, nil, errors.New("handshaker service consumed bytes value is out-of-bounds") } unusedBytes = p[resp.GetBytesConsumed():] } } // Close shuts down the handshaker and the stream to the S2A handshaker service // when the handshake is complete. It should be called when the caller obtains // the secure connection at the end of the handshake. func (h *s2aHandshaker) Close() error { return h.stream.CloseSend() } func (h *s2aHandshaker) getAuthMechanisms() []*s2apb.AuthenticationMechanism { if h.tokenManager == nil { return nil } // First handle the special case when no local identities have been provided // by the application. In this case, an AuthenticationMechanism with no local // identity will be sent. if len(h.localIdentities) == 0 { token, err := h.tokenManager.DefaultToken() if err != nil { grpclog.Infof("unable to get token for empty local identity: %v", err) return nil } return []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: token, }, }, } } // Next, handle the case where the application (or the S2A) has provided // one or more local identities. var authMechanisms []*s2apb.AuthenticationMechanism for _, localIdentity := range h.localIdentities { token, err := h.tokenManager.Token(localIdentity) if err != nil { grpclog.Infof("unable to get token for local identity %v: %v", localIdentity, err) continue } authMechanism := &s2apb.AuthenticationMechanism{ Identity: localIdentity, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: token, }, } authMechanisms = append(authMechanisms, authMechanism) } return authMechanisms } s2a-go-0.1.8/internal/handshaker/handshaker_test.go000066400000000000000000001056111464711036600222460ustar00rootroot00000000000000/* * * Copyright 2021 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 handshaker import ( "bytes" "context" "errors" "fmt" "io" "net" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" commonpbv1 "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" "github.com/google/s2a-go/internal/tokenmanager" "golang.org/x/sync/errgroup" grpc "google.golang.org/grpc" "google.golang.org/protobuf/testing/protocmp" ) var ( testAccessToken = "test_access_token" // testHSAddr is the handshaker service address used for testing testHSAddr = "handshaker_address" // testHostname is the hostname of the server used for testing. testHostname = "localhost" // testClientHandshakerOptions are the client-side handshaker options used for // testing. testClientHandshakerOptions = &ClientHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, TargetName: testHostname + ":1234", } // testClientStart is the ClientSessionStartReq message that the S2A expects // to receive first from the test client. testClientStart = &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, TargetName: testHostname, } // testClientNext is the SessionNextReq message that the S2A expects // to receive second from the test client. testClientNext = &s2apb.SessionNextReq{ InBytes: []byte("ServerHelloServerFinished"), } // testServerHandshakerOptions are the server-side handshaker options used // for testing. testServerHandshakerOptions = &ServerHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, LocalIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "server_local_hostname", }, }, }, } // testServerStart is the ServerSessionStartReq message that the S2A expects // to receive from the test server. testServerStart = &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, LocalIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "server_local_hostname", }, }, }, InBytes: []byte("ClientHello"), } // testServerNext is the SessionNextReq message that the S2A expects to // receive second from the test server. testServerNext = &s2apb.SessionNextReq{ InBytes: []byte("ClientFinished"), } testClientSessionResult = &s2apb.SessionResult{ ApplicationProtocol: "grpc", State: &s2apb.SessionState{ TlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuite: commonpbv1.Ciphersuite_AES_128_GCM_SHA256, InSequence: 0, OutSequence: 0, InKey: make([]byte, 32), OutKey: make([]byte, 32), }, PeerIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, LocalCertFingerprint: []byte("client_cert_fingerprint"), PeerCertFingerprint: []byte("server_cert_fingerprint"), } testServerSessionResult = &s2apb.SessionResult{ ApplicationProtocol: "grpc", State: &s2apb.SessionState{ TlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuite: commonpbv1.Ciphersuite_AES_128_GCM_SHA256, InSequence: 0, OutSequence: 0, InKey: make([]byte, 32), OutKey: make([]byte, 32), }, PeerIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, LocalCertFingerprint: []byte("server_cert_fingerprint"), PeerCertFingerprint: []byte("client_cert_fingerprint"), } testResultWithoutLocalIdentity = &s2apb.SessionResult{ ApplicationProtocol: "grpc", State: &s2apb.SessionState{ TlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuite: commonpbv1.Ciphersuite_AES_128_GCM_SHA256, InSequence: 0, OutSequence: 0, InKey: make([]byte, 32), OutKey: make([]byte, 32), }, PeerIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, LocalCertFingerprint: []byte("server_cert_fingerprint"), PeerCertFingerprint: []byte("client_cert_fingerprint"), } ) // fakeConn is a fake implementation of the net.Conn interface that is used for // testing. type fakeConn struct { net.Conn in *bytes.Buffer out *bytes.Buffer } func (fc *fakeConn) Read(b []byte) (n int, err error) { return fc.in.Read(b) } func (fc *fakeConn) Write(b []byte) (n int, err error) { return fc.out.Write(b) } func (fc *fakeConn) Close() error { return nil } // fakeInvalidConn is a fake implementation of a invalid net.Conn interface // that is used for testing. type fakeInvalidConn struct { net.Conn } func (fc *fakeInvalidConn) Read(_ []byte) (n int, err error) { return 0, io.EOF } func (fc *fakeInvalidConn) Write(_ []byte) (n int, err error) { return 0, nil } func (fc *fakeInvalidConn) Close() error { return nil } // fakeStream is a fake implementation of the grpc.ClientStream interface that // is used for testing. type fakeStream struct { grpc.ClientStream t *testing.T fc *fakeConn expectedClientStart *s2apb.ClientSessionStartReq expectedServerStart *s2apb.ServerSessionStartReq expectToken bool // expectedResp is the expected SessionResp message from the handshaker // service. expectedResp *s2apb.SessionResp // isFirstAccess indicates whether the first call to the handshaker service // has been made or not. isFirstAccess bool isClient bool isLocalIdentityMissing bool } func (fs *fakeStream) Recv() (*s2apb.SessionResp, error) { resp := fs.expectedResp fs.expectedResp = nil return resp, nil } func (fs *fakeStream) Send(req *s2apb.SessionReq) error { var resp *s2apb.SessionResp if fs.expectToken { if len(req.GetAuthMechanisms()) == 0 { return fmt.Errorf("request to S2A did not contain any tokens") } // Ensure that every token appearing in the request has a valid token. for _, authMechanism := range req.GetAuthMechanisms() { if authMechanism.GetToken() != testAccessToken { return fmt.Errorf("request to S2A contained invalid token") } } } if !fs.isFirstAccess { // Generate the bytes to be returned by Recv() for the first handshake // message. fs.isFirstAccess = true if fs.isClient { if diff := cmp.Diff(req.GetClientStart(), fs.expectedClientStart, protocmp.Transform()); diff != "" { return fmt.Errorf("client start message is incorrect, (-want +got):\n%s", diff) } resp = &s2apb.SessionResp{ OutFrames: []byte("ClientHello"), // There are no consumed bytes for a client start message BytesConsumed: 0, } } else { // Expect a server start message. if req.GetServerStart() == nil { return errors.New("first request from server does not have server start") } if diff := cmp.Diff(req.GetServerStart(), fs.expectedServerStart, protocmp.Transform()); diff != "" { return fmt.Errorf("server start message is incorrect, (-want +got):\n%s", diff) } fs.fc.in.Write([]byte("ClientFinished")) resp = &s2apb.SessionResp{ OutFrames: []byte("ServerHelloServerFinished"), // Simulate consuming the ClientHello message. BytesConsumed: uint32(len("ClientHello")), } } } else { // Construct a SessionResp message that contains the handshake result. if fs.isClient { // Expect next message with "ServerHelloServerFinished". if req.GetNext() == nil { return errors.New("second request from client does not have next") } if got, want := cmp.Equal(req.GetNext(), testClientNext, protocmp.Transform()), true; got != want { return errors.New("client next message is incorrect") } if fs.isLocalIdentityMissing { resp = &s2apb.SessionResp{ Result: testResultWithoutLocalIdentity, BytesConsumed: uint32(len("ClientFinished")), } } else { resp = &s2apb.SessionResp{ Result: testClientSessionResult, BytesConsumed: uint32(len("ServerHelloServerFinished")), } } } else { // Expect next message with "ClientFinished". if req.GetNext() == nil { return errors.New("second request from server does not have next") } if got, want := cmp.Equal(req.GetNext(), testServerNext, protocmp.Transform()), true; got != want { return errors.New("server next message is incorrect") } if fs.isLocalIdentityMissing { resp = &s2apb.SessionResp{ Result: testResultWithoutLocalIdentity, BytesConsumed: uint32(len("ClientFinished")), } } else { resp = &s2apb.SessionResp{ Result: testServerSessionResult, BytesConsumed: uint32(len("ClientFinished")), } } } } fs.expectedResp = resp return nil } func (*fakeStream) CloseSend() error { return nil } // fakeInvalidStream is a fake implementation of an invalid grpc.ClientStream // interface that is used for testing. type fakeInvalidStream struct { grpc.ClientStream } func (*fakeInvalidStream) Recv() (*s2apb.SessionResp, error) { return &s2apb.SessionResp{}, nil } func (*fakeInvalidStream) Send(*s2apb.SessionReq) error { return nil } func (*fakeInvalidStream) CloseSend() error { return nil } type fakeAccessTokenManager struct { acceptedIdentity *commonpbv1.Identity accessToken string allowEmptyIdentity bool } func (m *fakeAccessTokenManager) DefaultToken() (string, error) { if !m.allowEmptyIdentity { return "", fmt.Errorf("not allowed to get token for empty identity") } return m.accessToken, nil } func (m *fakeAccessTokenManager) Token(identity interface{}) (string, error) { switch v := identity.(type) { case *commonpbv1.Identity: // valid type. case *commonpb.Identity: // valid type. default: return "", fmt.Errorf("Incorrect identity type: %v", v) } if identity == nil || cmp.Equal(identity, &commonpbv1.Identity{}, protocmp.Transform()) { if !m.allowEmptyIdentity { return "", fmt.Errorf("not allowed to get token for empty identity") } return m.accessToken, nil } if cmp.Equal(identity, m.acceptedIdentity, protocmp.Transform()) { return m.accessToken, nil } return "", fmt.Errorf("unable to get token") } // TestNewClientHandshaker creates a fake stream, and ensures that // newClientHandshaker returns a valid client-side handshaker instance. func TestNewClientHandshaker(t *testing.T) { stream := &fakeStream{} c := &fakeConn{} chs := newClientHandshaker(stream, c, testHSAddr, testClientHandshakerOptions, &fakeAccessTokenManager{}) if chs.clientOpts != testClientHandshakerOptions || chs.conn != c { t.Errorf("handshaker parameters incorrect") } } // TestNewServerHandshaker creates a fake stream, and ensures that // newServerHandshaker returns a valid server-side handshaker instance. func TestNewServerHandshaker(t *testing.T) { stream := &fakeStream{} c := &fakeConn{} shs := newServerHandshaker(stream, c, testHSAddr, testServerHandshakerOptions, &fakeAccessTokenManager{}) if shs.serverOpts != testServerHandshakerOptions || shs.conn != c { t.Errorf("handshaker parameters incorrect") } } func TestClientHandshakeSuccess(t *testing.T) { for _, tc := range []struct { description string options *ClientHandshakerOptions tokenManager tokenmanager.AccessTokenManager expectedClientStart *s2apb.ClientSessionStartReq }{ { description: "full client options", options: testClientHandshakerOptions, expectedClientStart: testClientStart, }, { description: "full client options with no port in target name", options: &ClientHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, TargetName: testHostname, }, expectedClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, TargetName: testHostname, }, }, { description: "full client options with no local identity", options: &ClientHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, TargetName: testHostname + ":1234", }, expectedClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, TargetName: testHostname, }, }, { description: "full client options, sending tokens", options: testClientHandshakerOptions, expectedClientStart: testClientStart, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, }, }, { description: "full client options with no local identity, sending tokens", options: &ClientHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, TargetName: testHostname + ":1234", }, expectedClientStart: &s2apb.ClientSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, TargetIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "target_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "target_hostname", }, }, }, TargetName: testHostname, }, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, allowEmptyIdentity: true, }, }, } { t.Run(tc.description, func(t *testing.T) { // Set up all fakes and input data. var errg errgroup.Group stream := &fakeStream{ t: t, isClient: true, expectedClientStart: tc.expectedClientStart, expectToken: (tc.tokenManager != nil), } in := bytes.NewBuffer([]byte("ServerHelloServerFinished")) c := &fakeConn{ in: in, out: new(bytes.Buffer), } // Do the handshake. chs := newClientHandshaker(stream, c, testHSAddr, tc.options, tc.tokenManager) errg.Go(func() error { newConn, auth, err := chs.ClientHandshake(context.Background()) if err != nil { return err } if auth.AuthType() != "s2a" { return errors.New("s2a auth type incorrect") } if newConn == nil { return errors.New("expected non-nil net.Conn") } if err := chs.Close(); err != nil { t.Errorf("chs.Close() failed: %v", err) } return nil }) if err := errg.Wait(); err != nil { t.Errorf("client handshake failed: %v", err) } }) } } func TestServerHandshakeSuccess(t *testing.T) { for _, tc := range []struct { description string options *ServerHandshakerOptions tokenManager tokenmanager.AccessTokenManager expectedServerStart *s2apb.ServerSessionStartReq }{ { description: "full server options", options: testServerHandshakerOptions, expectedServerStart: testServerStart, }, { description: "full server options with no local identities", options: &ServerHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, expectedServerStart: &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, InBytes: []byte("ClientHello"), }, }, { description: "full server options, sending tokens", options: testServerHandshakerOptions, expectedServerStart: testServerStart, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, }, }, { description: "full server options with no local identity, sending tokens", options: &ServerHandshakerOptions{ MinTLSVersion: commonpbv1.TLSVersion_TLS1_2, MaxTLSVersion: commonpbv1.TLSVersion_TLS1_3, TLSCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, }, expectedServerStart: &s2apb.ServerSessionStartReq{ ApplicationProtocols: []string{"grpc"}, MinTlsVersion: commonpbv1.TLSVersion_TLS1_2, MaxTlsVersion: commonpbv1.TLSVersion_TLS1_3, TlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, InBytes: []byte("ClientHello"), }, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, allowEmptyIdentity: true, }, }, } { t.Run(tc.description, func(t *testing.T) { // Set up all fakes and input data. var errg errgroup.Group in := bytes.NewBuffer([]byte("ClientHello")) c := &fakeConn{ in: in, out: new(bytes.Buffer), } stream := &fakeStream{ t: t, fc: c, isClient: false, expectedServerStart: tc.expectedServerStart, expectToken: (tc.tokenManager != nil), } // Do the handshake. shs := newServerHandshaker(stream, c, testHSAddr, tc.options, tc.tokenManager) errg.Go(func() error { newConn, auth, err := shs.ServerHandshake(context.Background()) if err != nil { return err } if auth.AuthType() != "s2a" { return errors.New("s2a auth type incorrect") } if newConn == nil { return errors.New("expected non-nil net.Conn") } if err = shs.Close(); err != nil { t.Errorf("shs.Close() failed: %v", err) } return nil }) if err := errg.Wait(); err != nil { t.Errorf("server handshake failed: %v", err) } }) } } // Note that there is no need to test the case where S2A is expecting a token // and the application does not send a token, because this case is functionally // the same as the application sending an invalid token. func TestS2ARejectsTokenFromClient(t *testing.T) { stream := &fakeStream{ t: t, isClient: true, expectToken: true, } in := bytes.NewBuffer([]byte("ServerHelloServerFinished")) c := &fakeConn{ in: in, out: new(bytes.Buffer), } tokenManager := &fakeAccessTokenManager{ accessToken: "bad_access_token", acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "client_local_spiffe_id", }, }, } chs := newClientHandshaker(stream, c, testHSAddr, testClientHandshakerOptions, tokenManager) _, _, err := chs.ClientHandshake(context.Background()) if err == nil { t.Errorf("expected non-nil error from call to chs.ClientHandshake()") } if !strings.Contains(err.Error(), "request to S2A contained invalid token") { t.Errorf("chs.ClientHandshake() produced unexpected error: %v", err) } } func TestS2ARejectsTokenFromServer(t *testing.T) { stream := &fakeStream{ t: t, isClient: false, expectToken: true, } in := bytes.NewBuffer([]byte("ClientHello")) c := &fakeConn{ in: in, out: new(bytes.Buffer), } tokenManager := &fakeAccessTokenManager{ accessToken: "bad_access_token", acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "server_local_spiffe_id", }, }, } chs := newServerHandshaker(stream, c, testHSAddr, testServerHandshakerOptions, tokenManager) _, _, err := chs.ServerHandshake(context.Background()) if err == nil { t.Errorf("expected non-nil error from call to chs.ServerHandshake()") } if !strings.Contains(err.Error(), "request to S2A contained invalid token") { t.Errorf("chs.ServerHandshake() produced unexpected error: %v", err) } } func TestInvalidHandshaker(t *testing.T) { emptyCHS := &s2aHandshaker{ isClient: false, } _, _, err := emptyCHS.ClientHandshake(context.Background()) if err == nil { t.Error("ClientHandshake() should fail with server-side handshaker service") } emptySHS := &s2aHandshaker{ isClient: true, } _, _, err = emptySHS.ServerHandshake(context.Background()) if err == nil { t.Error("ServerHandshake() should fail with client-side handshaker service") } } // TestPeerNotResponding uses an invalid net.Conn instance and performs a // client-side handshake to test the case when the peer is not responding. func TestPeerNotResponding(t *testing.T) { stream := &fakeInvalidStream{} c := &fakeInvalidConn{} chs := &s2aHandshaker{ stream: stream, conn: c, clientOpts: testClientHandshakerOptions, isClient: true, hsAddr: testHSAddr, } _, authInfo, err := chs.ClientHandshake(context.Background()) if authInfo != nil { t.Error("expected non-nil S2A authInfo") } if got, want := err, errPeerNotResponding; got != want { t.Errorf("ClientHandshake() = %v, want %v", got, want) } if err = chs.Close(); err != nil { t.Errorf("chs.Close() failed: %v", err) } } // TestLocalIdentityNotSet performs a client-side handshake that fails // because the local identity is not set in the handshake result. func TestLocalIdentityNotSet(t *testing.T) { var errg errgroup.Group stream := &fakeStream{ t: t, isClient: true, isLocalIdentityMissing: true, } in := bytes.NewBuffer([]byte("ServerHelloServerFinished")) c := &fakeConn{ in: in, out: new(bytes.Buffer), } chs := &s2aHandshaker{ stream: stream, conn: c, clientOpts: testClientHandshakerOptions, isClient: true, hsAddr: testHSAddr, } errg.Go(func() error { newConn, auth, err := chs.ClientHandshake(context.Background()) if cmp.Equal(err, errors.New("local identity must be populated in session result"), cmpopts.EquateErrors()) { return fmt.Errorf("unexpected error: %v", err) } if auth != nil { return errors.New("expected nil credentials.AuthInfo") } if newConn != nil { return errors.New("expected nil net.Conn") } return nil }) if err := errg.Wait(); err != nil { t.Errorf("client handshake failed: %v", err) } } func TestGetAuthMechanismsForClient(t *testing.T) { sortProtos := cmpopts.SortSlices(func(m1, m2 *s2apb.AuthenticationMechanism) bool { return m1.String() < m2.String() }) for _, tc := range []struct { description string options *ClientHandshakerOptions tokenManager tokenmanager.AccessTokenManager expectedAuthMechanisms []*s2apb.AuthenticationMechanism }{ { description: "token manager is nil", tokenManager: nil, expectedAuthMechanisms: nil, }, { description: "token manager expects empty identity", tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, allowEmptyIdentity: true, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, { description: "token manager does not expect empty identity", tokenManager: &fakeAccessTokenManager{ allowEmptyIdentity: false, }, expectedAuthMechanisms: nil, }, { description: "token manager expects SPIFFE ID", options: &ClientHandshakerOptions{ LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, }, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { Identity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, { description: "token manager does not expect hostname", options: &ClientHandshakerOptions{ LocalIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "disallowed_hostname", }, }, }, tokenManager: &fakeAccessTokenManager{}, expectedAuthMechanisms: nil, }, } { t.Run(tc.description, func(t *testing.T) { handshaker := newClientHandshaker(nil, nil, "", tc.options, tc.tokenManager) authMechanisms := handshaker.getAuthMechanisms() if got, want := (authMechanisms == nil), (tc.expectedAuthMechanisms == nil); got != want { t.Errorf("authMechanisms == nil: %t, tc.expectedAuthMechanisms == nil: %t", got, want) } if authMechanisms != nil && tc.expectedAuthMechanisms != nil { if diff := cmp.Diff(authMechanisms, tc.expectedAuthMechanisms, protocmp.Transform(), sortProtos); diff != "" { t.Errorf("handshaker.getAuthMechanisms() returned incorrect slice, (-want +got):\n%s", diff) } } }) } } func TestGetAuthMechanismsForServer(t *testing.T) { sortProtos := cmpopts.SortSlices(func(m1, m2 *s2apb.AuthenticationMechanism) bool { return m1.String() < m2.String() }) for _, tc := range []struct { description string options *ServerHandshakerOptions tokenManager tokenmanager.AccessTokenManager expectedAuthMechanisms []*s2apb.AuthenticationMechanism }{ { description: "token manager is nil", tokenManager: nil, expectedAuthMechanisms: nil, }, { description: "token manager expects empty identity", tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, allowEmptyIdentity: true, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, { description: "token manager does not expect empty identity", tokenManager: &fakeAccessTokenManager{ allowEmptyIdentity: false, }, expectedAuthMechanisms: nil, }, { description: "token manager expects 2 SPIFFE IDs", options: &ServerHandshakerOptions{ LocalIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, }, }, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { Identity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, { Identity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, { description: "token manager expects a SPIFFE ID but does not expect hostname", options: &ServerHandshakerOptions{ LocalIdentities: []*commonpbv1.Identity{ { IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, { IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "disallowed_hostname", }, }, }, }, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { Identity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, } { t.Run(tc.description, func(t *testing.T) { handshaker := newServerHandshaker(nil, nil, "", tc.options, tc.tokenManager) authMechanisms := handshaker.getAuthMechanisms() if got, want := (authMechanisms == nil), (tc.expectedAuthMechanisms == nil); got != want { t.Errorf("authMechanisms == nil: %t, tc.expectedAuthMechanisms == nil: %t", got, want) } if authMechanisms != nil && tc.expectedAuthMechanisms != nil { if diff := cmp.Diff(authMechanisms, tc.expectedAuthMechanisms, protocmp.Transform(), sortProtos); diff != "" { t.Errorf("handshaker.getAuthMechanisms() returned incorrect slice, (-want +got):\n%s", diff) } } }) } } s2a-go-0.1.8/internal/handshaker/service/000077500000000000000000000000001464711036600202045ustar00rootroot00000000000000s2a-go-0.1.8/internal/handshaker/service/service.go000066400000000000000000000041301464711036600221710ustar00rootroot00000000000000/* * * Copyright 2021 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 service is a utility for calling the S2A handshaker service. package service import ( "context" "sync" grpc "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" ) var ( // mu guards hsConnMap and hsDialer. mu sync.Mutex // hsConnMap represents a mapping from an S2A handshaker service address // to a corresponding connection to an S2A handshaker service instance. hsConnMap = make(map[string]*grpc.ClientConn) // hsDialer will be reassigned in tests. hsDialer = grpc.DialContext ) // Dial dials the S2A handshaker service. If a connection has already been // established, this function returns it. Otherwise, a new connection is // created. func Dial(ctx context.Context, handshakerServiceAddress string, transportCreds credentials.TransportCredentials) (*grpc.ClientConn, error) { mu.Lock() defer mu.Unlock() hsConn, ok := hsConnMap[handshakerServiceAddress] if !ok { // Create a new connection to the S2A handshaker service. Note that // this connection stays open until the application is closed. var grpcOpts []grpc.DialOption if transportCreds != nil { grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(transportCreds)) } else { grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(insecure.NewCredentials())) } var err error hsConn, err = hsDialer(ctx, handshakerServiceAddress, grpcOpts...) if err != nil { return nil, err } hsConnMap[handshakerServiceAddress] = hsConn } return hsConn, nil } s2a-go-0.1.8/internal/handshaker/service/service_test.go000066400000000000000000000057631464711036600232450ustar00rootroot00000000000000/* * * Copyright 2021 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 service import ( "context" "crypto/tls" "testing" "google.golang.org/grpc/credentials" grpc "google.golang.org/grpc" ) const ( testAddress1 = "test_address_1" testAddress2 = "test_address_2" testAddress3 = "test_address_3" ) func TestDial(t *testing.T) { defer func() func() { temp := hsDialer hsDialer = func(ctx context.Context, target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { return &grpc.ClientConn{}, nil } return func() { hsDialer = temp } }() ctx := context.Background() // First call to Dial, it should create a connection to the server running // at the given address. conn1, err := Dial(ctx, testAddress1, nil) if err != nil { t.Fatalf("first call to Dial(%v) failed: %v", testAddress1, err) } if conn1 == nil { t.Fatalf("first call to Dial(%v)=(nil, _), want not nil", testAddress1) } if got, want := hsConnMap[testAddress1], conn1; got != want { t.Fatalf("hsConnMap[%v] = %v, want %v", testAddress1, got, want) } // Second call to Dial should return conn1 above. conn2, err := Dial(ctx, testAddress1, nil) if err != nil { t.Fatalf("second call to Dial(%v) failed: %v", testAddress1, err) } if got, want := conn2, conn1; got != want { t.Fatalf("second call to Dial(%v)=(%v, _), want (%v, _)", testAddress1, got, want) } if got, want := hsConnMap[testAddress1], conn1; got != want { t.Fatalf("hsConnMap[%v] = %v, want %v", testAddress1, got, want) } // Third call to Dial using a different address should create a new // connection. conn3, err := Dial(ctx, testAddress2, nil) if err != nil { t.Fatalf("third call to Dial(%v) failed: %v", testAddress2, err) } if conn3 == nil { t.Fatalf("third call to Dial(%v)=(nil, _), want not nil", testAddress2) } if got, want := hsConnMap[testAddress2], conn3; got != want { t.Fatalf("hsConnMap[%v] = %v, want %v", testAddress2, got, want) } if got, want := conn2 == conn3, false; got != want { t.Fatalf("(conn2 == conn3) = %v, want %v", got, want) } // Connect to an address with transportCredentials. conn4, err := Dial(ctx, testAddress3, credentials.NewTLS(&tls.Config{})) if err != nil { t.Fatalf("first call to Dial(%v) failed: %v", testAddress3, err) } if conn4 == nil { t.Fatalf("first call to Dial(%v)=(nil, _), want not nil", testAddress3) } if got, want := hsConnMap[testAddress3], conn4; got != want { t.Fatalf("hsConnMap[%v] = %v, want %v", testAddress3, got, want) } } s2a-go-0.1.8/internal/proto/000077500000000000000000000000001464711036600155775ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/common/000077500000000000000000000000001464711036600170675ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/common/common.proto000066400000000000000000000033301464711036600214430ustar00rootroot00000000000000// Copyright 2021 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. syntax = "proto3"; package s2a.proto; option go_package = "github.com/google/s2a/internal/proto/common_go_proto"; // The ciphersuites supported by S2A. The name determines the confidentiality, // and authentication ciphers as well as the hash algorithm used for PRF in // TLS 1.2 or HKDF in TLS 1.3. Thus, the components of the name are: // - AEAD -- for encryption and authentication, e.g., AES_128_GCM. // - Hash algorithm -- used in PRF or HKDF, e.g., SHA256. enum Ciphersuite { AES_128_GCM_SHA256 = 0; AES_256_GCM_SHA384 = 1; CHACHA20_POLY1305_SHA256 = 2; } // The TLS versions supported by S2A's handshaker module. enum TLSVersion { TLS1_2 = 0; TLS1_3 = 1; } message Identity { oneof identity_oneof { // The SPIFFE ID of a connection endpoint. string spiffe_id = 1; // The hostname of a connection endpoint. string hostname = 2; // The UID of a connection endpoint. string uid = 4; // The username of a connection endpoint. string username = 5; // The GCP ID of a connection endpoint. string gcp_id = 6; } // Additional identity-specific attributes. map attributes = 3; } s2a-go-0.1.8/internal/proto/common_go_proto/000077500000000000000000000000001464711036600207775ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/common_go_proto/common.pb.go000066400000000000000000000324111464711036600232170ustar00rootroot00000000000000// Copyright 2021 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/common/common.proto package common_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // The ciphersuites supported by S2A. The name determines the confidentiality, // and authentication ciphers as well as the hash algorithm used for PRF in // TLS 1.2 or HKDF in TLS 1.3. Thus, the components of the name are: // - AEAD -- for encryption and authentication, e.g., AES_128_GCM. // - Hash algorithm -- used in PRF or HKDF, e.g., SHA256. type Ciphersuite int32 const ( Ciphersuite_AES_128_GCM_SHA256 Ciphersuite = 0 Ciphersuite_AES_256_GCM_SHA384 Ciphersuite = 1 Ciphersuite_CHACHA20_POLY1305_SHA256 Ciphersuite = 2 ) // Enum value maps for Ciphersuite. var ( Ciphersuite_name = map[int32]string{ 0: "AES_128_GCM_SHA256", 1: "AES_256_GCM_SHA384", 2: "CHACHA20_POLY1305_SHA256", } Ciphersuite_value = map[string]int32{ "AES_128_GCM_SHA256": 0, "AES_256_GCM_SHA384": 1, "CHACHA20_POLY1305_SHA256": 2, } ) func (x Ciphersuite) Enum() *Ciphersuite { p := new(Ciphersuite) *p = x return p } func (x Ciphersuite) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Ciphersuite) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_common_common_proto_enumTypes[0].Descriptor() } func (Ciphersuite) Type() protoreflect.EnumType { return &file_internal_proto_common_common_proto_enumTypes[0] } func (x Ciphersuite) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Ciphersuite.Descriptor instead. func (Ciphersuite) EnumDescriptor() ([]byte, []int) { return file_internal_proto_common_common_proto_rawDescGZIP(), []int{0} } // The TLS versions supported by S2A's handshaker module. type TLSVersion int32 const ( TLSVersion_TLS1_2 TLSVersion = 0 TLSVersion_TLS1_3 TLSVersion = 1 ) // Enum value maps for TLSVersion. var ( TLSVersion_name = map[int32]string{ 0: "TLS1_2", 1: "TLS1_3", } TLSVersion_value = map[string]int32{ "TLS1_2": 0, "TLS1_3": 1, } ) func (x TLSVersion) Enum() *TLSVersion { p := new(TLSVersion) *p = x return p } func (x TLSVersion) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (TLSVersion) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_common_common_proto_enumTypes[1].Descriptor() } func (TLSVersion) Type() protoreflect.EnumType { return &file_internal_proto_common_common_proto_enumTypes[1] } func (x TLSVersion) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use TLSVersion.Descriptor instead. func (TLSVersion) EnumDescriptor() ([]byte, []int) { return file_internal_proto_common_common_proto_rawDescGZIP(), []int{1} } type Identity struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to IdentityOneof: // // *Identity_SpiffeId // *Identity_Hostname // *Identity_Uid // *Identity_Username // *Identity_GcpId IdentityOneof isIdentity_IdentityOneof `protobuf_oneof:"identity_oneof"` // Additional identity-specific attributes. Attributes map[string]string `protobuf:"bytes,3,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Identity) Reset() { *x = Identity{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_common_common_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Identity) String() string { return protoimpl.X.MessageStringOf(x) } func (*Identity) ProtoMessage() {} func (x *Identity) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_common_common_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Identity.ProtoReflect.Descriptor instead. func (*Identity) Descriptor() ([]byte, []int) { return file_internal_proto_common_common_proto_rawDescGZIP(), []int{0} } func (m *Identity) GetIdentityOneof() isIdentity_IdentityOneof { if m != nil { return m.IdentityOneof } return nil } func (x *Identity) GetSpiffeId() string { if x, ok := x.GetIdentityOneof().(*Identity_SpiffeId); ok { return x.SpiffeId } return "" } func (x *Identity) GetHostname() string { if x, ok := x.GetIdentityOneof().(*Identity_Hostname); ok { return x.Hostname } return "" } func (x *Identity) GetUid() string { if x, ok := x.GetIdentityOneof().(*Identity_Uid); ok { return x.Uid } return "" } func (x *Identity) GetUsername() string { if x, ok := x.GetIdentityOneof().(*Identity_Username); ok { return x.Username } return "" } func (x *Identity) GetGcpId() string { if x, ok := x.GetIdentityOneof().(*Identity_GcpId); ok { return x.GcpId } return "" } func (x *Identity) GetAttributes() map[string]string { if x != nil { return x.Attributes } return nil } type isIdentity_IdentityOneof interface { isIdentity_IdentityOneof() } type Identity_SpiffeId struct { // The SPIFFE ID of a connection endpoint. SpiffeId string `protobuf:"bytes,1,opt,name=spiffe_id,json=spiffeId,proto3,oneof"` } type Identity_Hostname struct { // The hostname of a connection endpoint. Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3,oneof"` } type Identity_Uid struct { // The UID of a connection endpoint. Uid string `protobuf:"bytes,4,opt,name=uid,proto3,oneof"` } type Identity_Username struct { // The username of a connection endpoint. Username string `protobuf:"bytes,5,opt,name=username,proto3,oneof"` } type Identity_GcpId struct { // The GCP ID of a connection endpoint. GcpId string `protobuf:"bytes,6,opt,name=gcp_id,json=gcpId,proto3,oneof"` } func (*Identity_SpiffeId) isIdentity_IdentityOneof() {} func (*Identity_Hostname) isIdentity_IdentityOneof() {} func (*Identity_Uid) isIdentity_IdentityOneof() {} func (*Identity_Username) isIdentity_IdentityOneof() {} func (*Identity_GcpId) isIdentity_IdentityOneof() {} var File_internal_proto_common_common_proto protoreflect.FileDescriptor var file_internal_proto_common_common_proto_rawDesc = []byte{ 0x0a, 0x22, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa8, 0x02, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x09, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x06, 0x67, 0x63, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x67, 0x63, 0x70, 0x49, 0x64, 0x12, 0x43, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x2a, 0x5b, 0x0a, 0x0b, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x02, 0x2a, 0x24, 0x0a, 0x0a, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x4c, 0x53, 0x31, 0x5f, 0x32, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x4c, 0x53, 0x31, 0x5f, 0x33, 0x10, 0x01, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_common_common_proto_rawDescOnce sync.Once file_internal_proto_common_common_proto_rawDescData = file_internal_proto_common_common_proto_rawDesc ) func file_internal_proto_common_common_proto_rawDescGZIP() []byte { file_internal_proto_common_common_proto_rawDescOnce.Do(func() { file_internal_proto_common_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_common_common_proto_rawDescData) }) return file_internal_proto_common_common_proto_rawDescData } var file_internal_proto_common_common_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_internal_proto_common_common_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_internal_proto_common_common_proto_goTypes = []any{ (Ciphersuite)(0), // 0: s2a.proto.Ciphersuite (TLSVersion)(0), // 1: s2a.proto.TLSVersion (*Identity)(nil), // 2: s2a.proto.Identity nil, // 3: s2a.proto.Identity.AttributesEntry } var file_internal_proto_common_common_proto_depIdxs = []int32{ 3, // 0: s2a.proto.Identity.attributes:type_name -> s2a.proto.Identity.AttributesEntry 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_internal_proto_common_common_proto_init() } func file_internal_proto_common_common_proto_init() { if File_internal_proto_common_common_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_common_common_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*Identity); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_internal_proto_common_common_proto_msgTypes[0].OneofWrappers = []any{ (*Identity_SpiffeId)(nil), (*Identity_Hostname)(nil), (*Identity_Uid)(nil), (*Identity_Username)(nil), (*Identity_GcpId)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_common_common_proto_rawDesc, NumEnums: 2, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_internal_proto_common_common_proto_goTypes, DependencyIndexes: file_internal_proto_common_common_proto_depIdxs, EnumInfos: file_internal_proto_common_common_proto_enumTypes, MessageInfos: file_internal_proto_common_common_proto_msgTypes, }.Build() File_internal_proto_common_common_proto = out.File file_internal_proto_common_common_proto_rawDesc = nil file_internal_proto_common_common_proto_goTypes = nil file_internal_proto_common_common_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/examples/000077500000000000000000000000001464711036600174155ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/examples/helloworld.proto000066400000000000000000000025301464711036600226550ustar00rootroot00000000000000// Copyright 2021 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. syntax = "proto3"; package s2a.examples; option go_package = "github.com/google/s2a/internal/proto/examples/helloworld_go_proto"; // The greeting service definition. service Greeter { // A unary RPC. rpc SayHello(HelloRequest) returns (HelloReply) {} // A client-side streaming RPC. rpc SayHelloManyRequests(stream HelloRequest) returns (HelloReply) {} // A server-side streaming RPC. rpc SayHelloManyReplies(HelloRequest) returns (stream HelloReply) {} // A bidirectional streaming RPC. rpc SayHelloConversation(stream HelloRequest) returns (stream HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; } s2a-go-0.1.8/internal/proto/examples/helloworld_go_proto/000077500000000000000000000000001464711036600235005ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/examples/helloworld_go_proto/helloworld.pb.go000066400000000000000000000244371464711036600266140ustar00rootroot00000000000000// Copyright 2021 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/examples/helloworld.proto package helloworld_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // The request message containing the user's name. type HelloRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` } func (x *HelloRequest) Reset() { *x = HelloRequest{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_examples_helloworld_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HelloRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*HelloRequest) ProtoMessage() {} func (x *HelloRequest) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_examples_helloworld_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead. func (*HelloRequest) Descriptor() ([]byte, []int) { return file_internal_proto_examples_helloworld_proto_rawDescGZIP(), []int{0} } func (x *HelloRequest) GetName() string { if x != nil { return x.Name } return "" } // The response message containing the greetings type HelloReply struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` } func (x *HelloReply) Reset() { *x = HelloReply{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_examples_helloworld_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *HelloReply) String() string { return protoimpl.X.MessageStringOf(x) } func (*HelloReply) ProtoMessage() {} func (x *HelloReply) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_examples_helloworld_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use HelloReply.ProtoReflect.Descriptor instead. func (*HelloReply) Descriptor() ([]byte, []int) { return file_internal_proto_examples_helloworld_proto_rawDescGZIP(), []int{1} } func (x *HelloReply) GetMessage() string { if x != nil { return x.Message } return "" } var File_internal_proto_examples_helloworld_proto protoreflect.FileDescriptor var file_internal_proto_examples_helloworld_proto_rawDesc = []byte{ 0x0a, 0x28, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xc4, 0x02, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x1a, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x14, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x4f, 0x0a, 0x13, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x14, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_examples_helloworld_proto_rawDescOnce sync.Once file_internal_proto_examples_helloworld_proto_rawDescData = file_internal_proto_examples_helloworld_proto_rawDesc ) func file_internal_proto_examples_helloworld_proto_rawDescGZIP() []byte { file_internal_proto_examples_helloworld_proto_rawDescOnce.Do(func() { file_internal_proto_examples_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_examples_helloworld_proto_rawDescData) }) return file_internal_proto_examples_helloworld_proto_rawDescData } var file_internal_proto_examples_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_internal_proto_examples_helloworld_proto_goTypes = []any{ (*HelloRequest)(nil), // 0: s2a.examples.HelloRequest (*HelloReply)(nil), // 1: s2a.examples.HelloReply } var file_internal_proto_examples_helloworld_proto_depIdxs = []int32{ 0, // 0: s2a.examples.Greeter.SayHello:input_type -> s2a.examples.HelloRequest 0, // 1: s2a.examples.Greeter.SayHelloManyRequests:input_type -> s2a.examples.HelloRequest 0, // 2: s2a.examples.Greeter.SayHelloManyReplies:input_type -> s2a.examples.HelloRequest 0, // 3: s2a.examples.Greeter.SayHelloConversation:input_type -> s2a.examples.HelloRequest 1, // 4: s2a.examples.Greeter.SayHello:output_type -> s2a.examples.HelloReply 1, // 5: s2a.examples.Greeter.SayHelloManyRequests:output_type -> s2a.examples.HelloReply 1, // 6: s2a.examples.Greeter.SayHelloManyReplies:output_type -> s2a.examples.HelloReply 1, // 7: s2a.examples.Greeter.SayHelloConversation:output_type -> s2a.examples.HelloReply 4, // [4:8] is the sub-list for method output_type 0, // [0:4] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name } func init() { file_internal_proto_examples_helloworld_proto_init() } func file_internal_proto_examples_helloworld_proto_init() { if File_internal_proto_examples_helloworld_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_examples_helloworld_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*HelloRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_examples_helloworld_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*HelloReply); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_examples_helloworld_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 1, }, GoTypes: file_internal_proto_examples_helloworld_proto_goTypes, DependencyIndexes: file_internal_proto_examples_helloworld_proto_depIdxs, MessageInfos: file_internal_proto_examples_helloworld_proto_msgTypes, }.Build() File_internal_proto_examples_helloworld_proto = out.File file_internal_proto_examples_helloworld_proto_rawDesc = nil file_internal_proto_examples_helloworld_proto_goTypes = nil file_internal_proto_examples_helloworld_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/examples/helloworld_go_proto/helloworld_grpc.pb.go000066400000000000000000000261561464711036600276270ustar00rootroot00000000000000// Copyright 2021 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. // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.4.0 // - protoc v3.21.12 // source: internal/proto/examples/helloworld.proto package helloworld_go_proto import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.62.0 or later. const _ = grpc.SupportPackageIsVersion8 const ( Greeter_SayHello_FullMethodName = "/s2a.examples.Greeter/SayHello" Greeter_SayHelloManyRequests_FullMethodName = "/s2a.examples.Greeter/SayHelloManyRequests" Greeter_SayHelloManyReplies_FullMethodName = "/s2a.examples.Greeter/SayHelloManyReplies" Greeter_SayHelloConversation_FullMethodName = "/s2a.examples.Greeter/SayHelloConversation" ) // GreeterClient is the client API for Greeter service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // // The greeting service definition. type GreeterClient interface { // A unary RPC. SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) // A client-side streaming RPC. SayHelloManyRequests(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloManyRequestsClient, error) // A server-side streaming RPC. SayHelloManyReplies(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (Greeter_SayHelloManyRepliesClient, error) // A bidirectional streaming RPC. SayHelloConversation(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloConversationClient, error) } type greeterClient struct { cc grpc.ClientConnInterface } func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { return &greeterClient{cc} } func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(HelloReply) err := c.cc.Invoke(ctx, Greeter_SayHello_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } return out, nil } func (c *greeterClient) SayHelloManyRequests(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloManyRequestsClient, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[0], Greeter_SayHelloManyRequests_FullMethodName, cOpts...) if err != nil { return nil, err } x := &greeterSayHelloManyRequestsClient{ClientStream: stream} return x, nil } type Greeter_SayHelloManyRequestsClient interface { Send(*HelloRequest) error CloseAndRecv() (*HelloReply, error) grpc.ClientStream } type greeterSayHelloManyRequestsClient struct { grpc.ClientStream } func (x *greeterSayHelloManyRequestsClient) Send(m *HelloRequest) error { return x.ClientStream.SendMsg(m) } func (x *greeterSayHelloManyRequestsClient) CloseAndRecv() (*HelloReply, error) { if err := x.ClientStream.CloseSend(); err != nil { return nil, err } m := new(HelloReply) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *greeterClient) SayHelloManyReplies(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (Greeter_SayHelloManyRepliesClient, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[1], Greeter_SayHelloManyReplies_FullMethodName, cOpts...) if err != nil { return nil, err } x := &greeterSayHelloManyRepliesClient{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } if err := x.ClientStream.CloseSend(); err != nil { return nil, err } return x, nil } type Greeter_SayHelloManyRepliesClient interface { Recv() (*HelloReply, error) grpc.ClientStream } type greeterSayHelloManyRepliesClient struct { grpc.ClientStream } func (x *greeterSayHelloManyRepliesClient) Recv() (*HelloReply, error) { m := new(HelloReply) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func (c *greeterClient) SayHelloConversation(ctx context.Context, opts ...grpc.CallOption) (Greeter_SayHelloConversationClient, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &Greeter_ServiceDesc.Streams[2], Greeter_SayHelloConversation_FullMethodName, cOpts...) if err != nil { return nil, err } x := &greeterSayHelloConversationClient{ClientStream: stream} return x, nil } type Greeter_SayHelloConversationClient interface { Send(*HelloRequest) error Recv() (*HelloReply, error) grpc.ClientStream } type greeterSayHelloConversationClient struct { grpc.ClientStream } func (x *greeterSayHelloConversationClient) Send(m *HelloRequest) error { return x.ClientStream.SendMsg(m) } func (x *greeterSayHelloConversationClient) Recv() (*HelloReply, error) { m := new(HelloReply) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // GreeterServer is the server API for Greeter service. // All implementations must embed UnimplementedGreeterServer // for forward compatibility // // The greeting service definition. type GreeterServer interface { // A unary RPC. SayHello(context.Context, *HelloRequest) (*HelloReply, error) // A client-side streaming RPC. SayHelloManyRequests(Greeter_SayHelloManyRequestsServer) error // A server-side streaming RPC. SayHelloManyReplies(*HelloRequest, Greeter_SayHelloManyRepliesServer) error // A bidirectional streaming RPC. SayHelloConversation(Greeter_SayHelloConversationServer) error mustEmbedUnimplementedGreeterServer() } // UnimplementedGreeterServer must be embedded to have forward compatible implementations. type UnimplementedGreeterServer struct { } func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") } func (UnimplementedGreeterServer) SayHelloManyRequests(Greeter_SayHelloManyRequestsServer) error { return status.Errorf(codes.Unimplemented, "method SayHelloManyRequests not implemented") } func (UnimplementedGreeterServer) SayHelloManyReplies(*HelloRequest, Greeter_SayHelloManyRepliesServer) error { return status.Errorf(codes.Unimplemented, "method SayHelloManyReplies not implemented") } func (UnimplementedGreeterServer) SayHelloConversation(Greeter_SayHelloConversationServer) error { return status.Errorf(codes.Unimplemented, "method SayHelloConversation not implemented") } func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} // UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to GreeterServer will // result in compilation errors. type UnsafeGreeterServer interface { mustEmbedUnimplementedGreeterServer() } func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { s.RegisterService(&Greeter_ServiceDesc, srv) } func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(HelloRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(GreeterServer).SayHello(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: Greeter_SayHello_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) } return interceptor(ctx, in, info, handler) } func _Greeter_SayHelloManyRequests_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(GreeterServer).SayHelloManyRequests(&greeterSayHelloManyRequestsServer{ServerStream: stream}) } type Greeter_SayHelloManyRequestsServer interface { SendAndClose(*HelloReply) error Recv() (*HelloRequest, error) grpc.ServerStream } type greeterSayHelloManyRequestsServer struct { grpc.ServerStream } func (x *greeterSayHelloManyRequestsServer) SendAndClose(m *HelloReply) error { return x.ServerStream.SendMsg(m) } func (x *greeterSayHelloManyRequestsServer) Recv() (*HelloRequest, error) { m := new(HelloRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } func _Greeter_SayHelloManyReplies_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(HelloRequest) if err := stream.RecvMsg(m); err != nil { return err } return srv.(GreeterServer).SayHelloManyReplies(m, &greeterSayHelloManyRepliesServer{ServerStream: stream}) } type Greeter_SayHelloManyRepliesServer interface { Send(*HelloReply) error grpc.ServerStream } type greeterSayHelloManyRepliesServer struct { grpc.ServerStream } func (x *greeterSayHelloManyRepliesServer) Send(m *HelloReply) error { return x.ServerStream.SendMsg(m) } func _Greeter_SayHelloConversation_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(GreeterServer).SayHelloConversation(&greeterSayHelloConversationServer{ServerStream: stream}) } type Greeter_SayHelloConversationServer interface { Send(*HelloReply) error Recv() (*HelloRequest, error) grpc.ServerStream } type greeterSayHelloConversationServer struct { grpc.ServerStream } func (x *greeterSayHelloConversationServer) Send(m *HelloReply) error { return x.ServerStream.SendMsg(m) } func (x *greeterSayHelloConversationServer) Recv() (*HelloRequest, error) { m := new(HelloRequest) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var Greeter_ServiceDesc = grpc.ServiceDesc{ ServiceName: "s2a.examples.Greeter", HandlerType: (*GreeterServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "SayHello", Handler: _Greeter_SayHello_Handler, }, }, Streams: []grpc.StreamDesc{ { StreamName: "SayHelloManyRequests", Handler: _Greeter_SayHelloManyRequests_Handler, ClientStreams: true, }, { StreamName: "SayHelloManyReplies", Handler: _Greeter_SayHelloManyReplies_Handler, ServerStreams: true, }, { StreamName: "SayHelloConversation", Handler: _Greeter_SayHelloConversation_Handler, ServerStreams: true, ClientStreams: true, }, }, Metadata: "internal/proto/examples/helloworld.proto", } s2a-go-0.1.8/internal/proto/s2a/000077500000000000000000000000001464711036600162645ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/s2a/s2a.proto000066400000000000000000000253221464711036600200420ustar00rootroot00000000000000// Copyright 2021 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. syntax = "proto3"; package s2a.proto; option go_package = "github.com/google/s2a/internal/proto/s2a_go_proto"; import "internal/proto/common/common.proto"; message AuthenticationMechanism { // (Optional) Application may specify an identity associated to an // authentication mechanism. Otherwise, S2A assumes that the authentication // mechanism is associated with the default identity. If the default identity // cannot be determined, session setup fails. Identity identity = 1; oneof mechanism_oneof { // A token that the application uses to authenticate itself to the S2A. string token = 2; } } message ClientSessionStartReq { // The application protocols supported by the client, e.g., "grpc". repeated string application_protocols = 1; // (Optional) The minimum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the minimum version it supports. TLSVersion min_tls_version = 2; // (Optional) The maximum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the maximum version it supports. TLSVersion max_tls_version = 3; // The TLS ciphersuites that the client is willing to support. repeated Ciphersuite tls_ciphersuites = 4; // (Optional) Describes which server identities are acceptable by the client. // If target identities are provided and none of them matches the peer // identity of the server, session setup fails. repeated Identity target_identities = 5; // (Optional) Application may specify a local identity. Otherwise, S2A chooses // the default local identity. If the default identity cannot be determined, // session setup fails. Identity local_identity = 6; // The target name that is used by S2A to configure SNI in the TLS handshake. // It is also used to perform server authorization check if avaiable. This // check is intended to verify that the peer authenticated identity is // authorized to run a service with the target name. // This field MUST only contain the host portion of the server address. It // MUST not contain the scheme or the port number. For example, if the server // address is dns://www.example.com:443, the value of this field should be // set to www.example.com. string target_name = 7; } message ServerSessionStartReq { // The application protocols supported by the server, e.g., "grpc". repeated string application_protocols = 1; // (Optional) The minimum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the minimum version it supports. TLSVersion min_tls_version = 2; // (Optional) The maximum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the maximum version it supports. TLSVersion max_tls_version = 3; // The TLS ciphersuites that the server is willing to support. repeated Ciphersuite tls_ciphersuites = 4; // (Optional) A list of local identities supported by the server, if // specified. Otherwise, S2A chooses the default local identity. If the // default identity cannot be determined, session setup fails. repeated Identity local_identities = 5; // The byte representation of the first handshake message received from the // client peer. It is possible that this first message is split into multiple // chunks. In this case, the first chunk is sent using this field and the // following chunks are sent using the in_bytes field of SessionNextReq // Specifically, if the client peer is using S2A, this field contains the // bytes in the out_frames field of SessionResp message that the client peer // received from its S2A after initiating the handshake. bytes in_bytes = 6; } message SessionNextReq { // The byte representation of session setup, i.e., handshake messages. // Specifically: // - All handshake messages sent from the server to the client. // - All, except for the first, handshake messages sent from the client to // the server. Note that the first message is communicated to S2A using the // in_bytes field of ServerSessionStartReq. // If the peer is using S2A, this field contains the bytes in the out_frames // field of SessionResp message that the peer received from its S2A. bytes in_bytes = 1; } message ResumptionTicketReq { // The byte representation of a NewSessionTicket message received from the // server. repeated bytes in_bytes = 1; // A connection identifier that was created and sent by S2A at the end of a // handshake. uint64 connection_id = 2; // The local identity that was used by S2A during session setup and included // in |SessionResult|. Identity local_identity = 3; } message SessionReq { oneof req_oneof { // The client session setup request message. ClientSessionStartReq client_start = 1; // The server session setup request message. ServerSessionStartReq server_start = 2; // The next session setup message request message. SessionNextReq next = 3; // The resumption ticket that is received from the server. This message is // only accepted by S2A if it is running as a client and if it is received // after session setup is complete. If S2A is running as a server and it // receives this message, the session is terminated. ResumptionTicketReq resumption_ticket = 4; } // (Optional) The authentication mechanisms that the client wishes to use to // authenticate to the S2A, ordered by preference. The S2A will always use the // first authentication mechanism that appears in the list and is supported by // the S2A. repeated AuthenticationMechanism auth_mechanisms = 5; } message SessionState { // The TLS version number that the S2A's handshaker module used to set up the // session. TLSVersion tls_version = 1; // The TLS ciphersuite negotiated by the S2A's handshaker module. Ciphersuite tls_ciphersuite = 2; // The sequence number of the next, incoming, TLS record. uint64 in_sequence = 3; // The sequence number of the next, outgoing, TLS record. uint64 out_sequence = 4; // The key for the inbound direction. bytes in_key = 5; // The key for the outbound direction. bytes out_key = 6; // The constant part of the record nonce for the outbound direction. bytes in_fixed_nonce = 7; // The constant part of the record nonce for the inbound direction. bytes out_fixed_nonce = 8; // A connection identifier that can be provided to S2A to perform operations // related to this connection. This identifier will be stored by the record // protocol, and included in the |ResumptionTicketReq| message that is later // sent back to S2A. This field is set only for client-side connections. uint64 connection_id = 9; // Set to true if a cached session was reused to do an abbreviated handshake. bool is_handshake_resumed = 10; } message SessionResult { // The application protocol negotiated for this session. string application_protocol = 1; // The session state at the end. This state contains all cryptographic // material required to initialize the record protocol object. SessionState state = 2; // The authenticated identity of the peer. Identity peer_identity = 4; // The local identity used during session setup. This could be: // - The local identity that the client specifies in ClientSessionStartReq. // - One of the local identities that the server specifies in // ServerSessionStartReq. // - If neither client or server specifies local identities, the S2A picks the // default one. In this case, this field will contain that identity. Identity local_identity = 5; // The SHA256 hash of the local certificate used in the handshake. bytes local_cert_fingerprint = 6; // The SHA256 hash of the peer certificate used in the handshake. bytes peer_cert_fingerprint = 7; } message SessionStatus { // The status code that is specific to the application and the implementation // of S2A, e.g., gRPC status code. uint32 code = 1; // The status details. string details = 2; } message SessionResp { // The local identity used during session setup. This could be: // - The local identity that the client specifies in ClientSessionStartReq. // - One of the local identities that the server specifies in // ServerSessionStartReq. // - If neither client or server specifies local identities, the S2A picks the // default one. In this case, this field will contain that identity. // If the SessionResult is populated, then this must coincide with the local // identity specified in the SessionResult; otherwise, the handshake must // fail. Identity local_identity = 1; // The byte representation of the frames that should be sent to the peer. May // be empty if nothing needs to be sent to the peer or if in_bytes in the // SessionReq is incomplete. All bytes in a non-empty out_frames must be sent // to the peer even if the session setup status is not OK as these frames may // contain appropriate alerts. bytes out_frames = 2; // Number of bytes in the in_bytes field that are consumed by S2A. It is // possible that part of in_bytes is unrelated to the session setup process. uint32 bytes_consumed = 3; // This is set if the session is successfully set up. out_frames may // still be set to frames that needs to be forwarded to the peer. SessionResult result = 4; // Status of session setup at the current stage. SessionStatus status = 5; } service S2AService { // S2A service accepts a stream of session setup requests and returns a stream // of session setup responses. The client of this service is expected to send // exactly one client_start or server_start message followed by at least one // next message. Applications running TLS clients can send requests with // resumption_ticket messages only after the session is successfully set up. // // Every time S2A client sends a request, this service sends a response. // However, clients do not have to wait for service response before sending // the next request. rpc SetUpSession(stream SessionReq) returns (stream SessionResp) {} } s2a-go-0.1.8/internal/proto/s2a_context/000077500000000000000000000000001464711036600200305ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/s2a_context/s2a_context.proto000066400000000000000000000036141464711036600233520ustar00rootroot00000000000000// Copyright 2021 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. syntax = "proto3"; package s2a.proto; option go_package = "github.com/google/s2a/internal/proto/s2a_context_go_proto"; import "internal/proto/common/common.proto"; message S2AContext { // The application protocol negotiated for this connection, e.g., 'grpc'. string application_protocol = 1; // The TLS version number that the S2A's handshaker module used to set up the // session. TLSVersion tls_version = 2; // The TLS ciphersuite negotiated by the S2A's handshaker module. Ciphersuite ciphersuite = 3; // The authenticated identity of the peer. Identity peer_identity = 4; // The local identity used during session setup. This could be: // - The local identity that the client specifies in ClientSessionStartReq. // - One of the local identities that the server specifies in // ServerSessionStartReq. // - If neither client or server specifies local identities, the S2A picks the // default one. In this case, this field will contain that identity. Identity local_identity = 5; // The SHA256 hash of the peer certificate used in the handshake. bytes peer_cert_fingerprint = 6; // The SHA256 hash of the local certificate used in the handshake. bytes local_cert_fingerprint = 7; // Set to true if a cached session was reused to resume the handshake. bool is_handshake_resumed = 8; } s2a-go-0.1.8/internal/proto/s2a_context_go_proto/000077500000000000000000000000001464711036600217405ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/s2a_context_go_proto/s2a_context.pb.go000066400000000000000000000277731464711036600251400ustar00rootroot00000000000000// Copyright 2021 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/s2a_context/s2a_context.proto package s2a_context_go_proto import ( common_go_proto "github.com/google/s2a-go/internal/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type S2AContext struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The application protocol negotiated for this connection, e.g., 'grpc'. ApplicationProtocol string `protobuf:"bytes,1,opt,name=application_protocol,json=applicationProtocol,proto3" json:"application_protocol,omitempty"` // The TLS version number that the S2A's handshaker module used to set up the // session. TlsVersion common_go_proto.TLSVersion `protobuf:"varint,2,opt,name=tls_version,json=tlsVersion,proto3,enum=s2a.proto.TLSVersion" json:"tls_version,omitempty"` // The TLS ciphersuite negotiated by the S2A's handshaker module. Ciphersuite common_go_proto.Ciphersuite `protobuf:"varint,3,opt,name=ciphersuite,proto3,enum=s2a.proto.Ciphersuite" json:"ciphersuite,omitempty"` // The authenticated identity of the peer. PeerIdentity *common_go_proto.Identity `protobuf:"bytes,4,opt,name=peer_identity,json=peerIdentity,proto3" json:"peer_identity,omitempty"` // The local identity used during session setup. This could be: // - The local identity that the client specifies in ClientSessionStartReq. // - One of the local identities that the server specifies in // ServerSessionStartReq. // - If neither client or server specifies local identities, the S2A picks the // default one. In this case, this field will contain that identity. LocalIdentity *common_go_proto.Identity `protobuf:"bytes,5,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` // The SHA256 hash of the peer certificate used in the handshake. PeerCertFingerprint []byte `protobuf:"bytes,6,opt,name=peer_cert_fingerprint,json=peerCertFingerprint,proto3" json:"peer_cert_fingerprint,omitempty"` // The SHA256 hash of the local certificate used in the handshake. LocalCertFingerprint []byte `protobuf:"bytes,7,opt,name=local_cert_fingerprint,json=localCertFingerprint,proto3" json:"local_cert_fingerprint,omitempty"` // Set to true if a cached session was reused to resume the handshake. IsHandshakeResumed bool `protobuf:"varint,8,opt,name=is_handshake_resumed,json=isHandshakeResumed,proto3" json:"is_handshake_resumed,omitempty"` } func (x *S2AContext) Reset() { *x = S2AContext{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_context_s2a_context_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *S2AContext) String() string { return protoimpl.X.MessageStringOf(x) } func (*S2AContext) ProtoMessage() {} func (x *S2AContext) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_context_s2a_context_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use S2AContext.ProtoReflect.Descriptor instead. func (*S2AContext) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_context_s2a_context_proto_rawDescGZIP(), []int{0} } func (x *S2AContext) GetApplicationProtocol() string { if x != nil { return x.ApplicationProtocol } return "" } func (x *S2AContext) GetTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.TlsVersion } return common_go_proto.TLSVersion(0) } func (x *S2AContext) GetCiphersuite() common_go_proto.Ciphersuite { if x != nil { return x.Ciphersuite } return common_go_proto.Ciphersuite(0) } func (x *S2AContext) GetPeerIdentity() *common_go_proto.Identity { if x != nil { return x.PeerIdentity } return nil } func (x *S2AContext) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } func (x *S2AContext) GetPeerCertFingerprint() []byte { if x != nil { return x.PeerCertFingerprint } return nil } func (x *S2AContext) GetLocalCertFingerprint() []byte { if x != nil { return x.LocalCertFingerprint } return nil } func (x *S2AContext) GetIsHandshakeResumed() bool { if x != nil { return x.IsHandshakeResumed } return false } var File_internal_proto_s2a_context_s2a_context_proto protoreflect.FileDescriptor var file_internal_proto_s2a_context_s2a_context_proto_rawDesc = []byte{ 0x0a, 0x2c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x03, 0x0a, 0x0a, 0x53, 0x32, 0x41, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x31, 0x0a, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x74, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x70, 0x65, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x70, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x73, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x73, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_s2a_context_s2a_context_proto_rawDescOnce sync.Once file_internal_proto_s2a_context_s2a_context_proto_rawDescData = file_internal_proto_s2a_context_s2a_context_proto_rawDesc ) func file_internal_proto_s2a_context_s2a_context_proto_rawDescGZIP() []byte { file_internal_proto_s2a_context_s2a_context_proto_rawDescOnce.Do(func() { file_internal_proto_s2a_context_s2a_context_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_s2a_context_s2a_context_proto_rawDescData) }) return file_internal_proto_s2a_context_s2a_context_proto_rawDescData } var file_internal_proto_s2a_context_s2a_context_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_internal_proto_s2a_context_s2a_context_proto_goTypes = []any{ (*S2AContext)(nil), // 0: s2a.proto.S2AContext (common_go_proto.TLSVersion)(0), // 1: s2a.proto.TLSVersion (common_go_proto.Ciphersuite)(0), // 2: s2a.proto.Ciphersuite (*common_go_proto.Identity)(nil), // 3: s2a.proto.Identity } var file_internal_proto_s2a_context_s2a_context_proto_depIdxs = []int32{ 1, // 0: s2a.proto.S2AContext.tls_version:type_name -> s2a.proto.TLSVersion 2, // 1: s2a.proto.S2AContext.ciphersuite:type_name -> s2a.proto.Ciphersuite 3, // 2: s2a.proto.S2AContext.peer_identity:type_name -> s2a.proto.Identity 3, // 3: s2a.proto.S2AContext.local_identity:type_name -> s2a.proto.Identity 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_internal_proto_s2a_context_s2a_context_proto_init() } func file_internal_proto_s2a_context_s2a_context_proto_init() { if File_internal_proto_s2a_context_s2a_context_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_s2a_context_s2a_context_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*S2AContext); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_s2a_context_s2a_context_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_internal_proto_s2a_context_s2a_context_proto_goTypes, DependencyIndexes: file_internal_proto_s2a_context_s2a_context_proto_depIdxs, MessageInfos: file_internal_proto_s2a_context_s2a_context_proto_msgTypes, }.Build() File_internal_proto_s2a_context_s2a_context_proto = out.File file_internal_proto_s2a_context_s2a_context_proto_rawDesc = nil file_internal_proto_s2a_context_s2a_context_proto_goTypes = nil file_internal_proto_s2a_context_s2a_context_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/s2a_go_proto/000077500000000000000000000000001464711036600201745ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/s2a_go_proto/s2a.pb.go000066400000000000000000001600511464711036600216130ustar00rootroot00000000000000// Copyright 2021 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/s2a/s2a.proto package s2a_go_proto import ( common_go_proto "github.com/google/s2a-go/internal/proto/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type AuthenticationMechanism struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // (Optional) Application may specify an identity associated to an // authentication mechanism. Otherwise, S2A assumes that the authentication // mechanism is associated with the default identity. If the default identity // cannot be determined, session setup fails. Identity *common_go_proto.Identity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` // Types that are assignable to MechanismOneof: // // *AuthenticationMechanism_Token MechanismOneof isAuthenticationMechanism_MechanismOneof `protobuf_oneof:"mechanism_oneof"` } func (x *AuthenticationMechanism) Reset() { *x = AuthenticationMechanism{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AuthenticationMechanism) String() string { return protoimpl.X.MessageStringOf(x) } func (*AuthenticationMechanism) ProtoMessage() {} func (x *AuthenticationMechanism) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AuthenticationMechanism.ProtoReflect.Descriptor instead. func (*AuthenticationMechanism) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{0} } func (x *AuthenticationMechanism) GetIdentity() *common_go_proto.Identity { if x != nil { return x.Identity } return nil } func (m *AuthenticationMechanism) GetMechanismOneof() isAuthenticationMechanism_MechanismOneof { if m != nil { return m.MechanismOneof } return nil } func (x *AuthenticationMechanism) GetToken() string { if x, ok := x.GetMechanismOneof().(*AuthenticationMechanism_Token); ok { return x.Token } return "" } type isAuthenticationMechanism_MechanismOneof interface { isAuthenticationMechanism_MechanismOneof() } type AuthenticationMechanism_Token struct { // A token that the application uses to authenticate itself to the S2A. Token string `protobuf:"bytes,2,opt,name=token,proto3,oneof"` } func (*AuthenticationMechanism_Token) isAuthenticationMechanism_MechanismOneof() {} type ClientSessionStartReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The application protocols supported by the client, e.g., "grpc". ApplicationProtocols []string `protobuf:"bytes,1,rep,name=application_protocols,json=applicationProtocols,proto3" json:"application_protocols,omitempty"` // (Optional) The minimum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the minimum version it supports. MinTlsVersion common_go_proto.TLSVersion `protobuf:"varint,2,opt,name=min_tls_version,json=minTlsVersion,proto3,enum=s2a.proto.TLSVersion" json:"min_tls_version,omitempty"` // (Optional) The maximum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the maximum version it supports. MaxTlsVersion common_go_proto.TLSVersion `protobuf:"varint,3,opt,name=max_tls_version,json=maxTlsVersion,proto3,enum=s2a.proto.TLSVersion" json:"max_tls_version,omitempty"` // The TLS ciphersuites that the client is willing to support. TlsCiphersuites []common_go_proto.Ciphersuite `protobuf:"varint,4,rep,packed,name=tls_ciphersuites,json=tlsCiphersuites,proto3,enum=s2a.proto.Ciphersuite" json:"tls_ciphersuites,omitempty"` // (Optional) Describes which server identities are acceptable by the client. // If target identities are provided and none of them matches the peer // identity of the server, session setup fails. TargetIdentities []*common_go_proto.Identity `protobuf:"bytes,5,rep,name=target_identities,json=targetIdentities,proto3" json:"target_identities,omitempty"` // (Optional) Application may specify a local identity. Otherwise, S2A chooses // the default local identity. If the default identity cannot be determined, // session setup fails. LocalIdentity *common_go_proto.Identity `protobuf:"bytes,6,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` // The target name that is used by S2A to configure SNI in the TLS handshake. // It is also used to perform server authorization check if avaiable. This // check is intended to verify that the peer authenticated identity is // authorized to run a service with the target name. // This field MUST only contain the host portion of the server address. It // MUST not contain the scheme or the port number. For example, if the server // address is dns://www.example.com:443, the value of this field should be // set to www.example.com. TargetName string `protobuf:"bytes,7,opt,name=target_name,json=targetName,proto3" json:"target_name,omitempty"` } func (x *ClientSessionStartReq) Reset() { *x = ClientSessionStartReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ClientSessionStartReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*ClientSessionStartReq) ProtoMessage() {} func (x *ClientSessionStartReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ClientSessionStartReq.ProtoReflect.Descriptor instead. func (*ClientSessionStartReq) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{1} } func (x *ClientSessionStartReq) GetApplicationProtocols() []string { if x != nil { return x.ApplicationProtocols } return nil } func (x *ClientSessionStartReq) GetMinTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MinTlsVersion } return common_go_proto.TLSVersion(0) } func (x *ClientSessionStartReq) GetMaxTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MaxTlsVersion } return common_go_proto.TLSVersion(0) } func (x *ClientSessionStartReq) GetTlsCiphersuites() []common_go_proto.Ciphersuite { if x != nil { return x.TlsCiphersuites } return nil } func (x *ClientSessionStartReq) GetTargetIdentities() []*common_go_proto.Identity { if x != nil { return x.TargetIdentities } return nil } func (x *ClientSessionStartReq) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } func (x *ClientSessionStartReq) GetTargetName() string { if x != nil { return x.TargetName } return "" } type ServerSessionStartReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The application protocols supported by the server, e.g., "grpc". ApplicationProtocols []string `protobuf:"bytes,1,rep,name=application_protocols,json=applicationProtocols,proto3" json:"application_protocols,omitempty"` // (Optional) The minimum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the minimum version it supports. MinTlsVersion common_go_proto.TLSVersion `protobuf:"varint,2,opt,name=min_tls_version,json=minTlsVersion,proto3,enum=s2a.proto.TLSVersion" json:"min_tls_version,omitempty"` // (Optional) The maximum TLS version number that the S2A's handshaker module // will use to set up the session. If this field is not provided, S2A will use // the maximum version it supports. MaxTlsVersion common_go_proto.TLSVersion `protobuf:"varint,3,opt,name=max_tls_version,json=maxTlsVersion,proto3,enum=s2a.proto.TLSVersion" json:"max_tls_version,omitempty"` // The TLS ciphersuites that the server is willing to support. TlsCiphersuites []common_go_proto.Ciphersuite `protobuf:"varint,4,rep,packed,name=tls_ciphersuites,json=tlsCiphersuites,proto3,enum=s2a.proto.Ciphersuite" json:"tls_ciphersuites,omitempty"` // (Optional) A list of local identities supported by the server, if // specified. Otherwise, S2A chooses the default local identity. If the // default identity cannot be determined, session setup fails. LocalIdentities []*common_go_proto.Identity `protobuf:"bytes,5,rep,name=local_identities,json=localIdentities,proto3" json:"local_identities,omitempty"` // The byte representation of the first handshake message received from the // client peer. It is possible that this first message is split into multiple // chunks. In this case, the first chunk is sent using this field and the // following chunks are sent using the in_bytes field of SessionNextReq // Specifically, if the client peer is using S2A, this field contains the // bytes in the out_frames field of SessionResp message that the client peer // received from its S2A after initiating the handshake. InBytes []byte `protobuf:"bytes,6,opt,name=in_bytes,json=inBytes,proto3" json:"in_bytes,omitempty"` } func (x *ServerSessionStartReq) Reset() { *x = ServerSessionStartReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ServerSessionStartReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*ServerSessionStartReq) ProtoMessage() {} func (x *ServerSessionStartReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ServerSessionStartReq.ProtoReflect.Descriptor instead. func (*ServerSessionStartReq) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{2} } func (x *ServerSessionStartReq) GetApplicationProtocols() []string { if x != nil { return x.ApplicationProtocols } return nil } func (x *ServerSessionStartReq) GetMinTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MinTlsVersion } return common_go_proto.TLSVersion(0) } func (x *ServerSessionStartReq) GetMaxTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MaxTlsVersion } return common_go_proto.TLSVersion(0) } func (x *ServerSessionStartReq) GetTlsCiphersuites() []common_go_proto.Ciphersuite { if x != nil { return x.TlsCiphersuites } return nil } func (x *ServerSessionStartReq) GetLocalIdentities() []*common_go_proto.Identity { if x != nil { return x.LocalIdentities } return nil } func (x *ServerSessionStartReq) GetInBytes() []byte { if x != nil { return x.InBytes } return nil } type SessionNextReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The byte representation of session setup, i.e., handshake messages. // Specifically: // - All handshake messages sent from the server to the client. // - All, except for the first, handshake messages sent from the client to // the server. Note that the first message is communicated to S2A using the // in_bytes field of ServerSessionStartReq. // // If the peer is using S2A, this field contains the bytes in the out_frames // field of SessionResp message that the peer received from its S2A. InBytes []byte `protobuf:"bytes,1,opt,name=in_bytes,json=inBytes,proto3" json:"in_bytes,omitempty"` } func (x *SessionNextReq) Reset() { *x = SessionNextReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionNextReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionNextReq) ProtoMessage() {} func (x *SessionNextReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionNextReq.ProtoReflect.Descriptor instead. func (*SessionNextReq) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{3} } func (x *SessionNextReq) GetInBytes() []byte { if x != nil { return x.InBytes } return nil } type ResumptionTicketReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The byte representation of a NewSessionTicket message received from the // server. InBytes [][]byte `protobuf:"bytes,1,rep,name=in_bytes,json=inBytes,proto3" json:"in_bytes,omitempty"` // A connection identifier that was created and sent by S2A at the end of a // handshake. ConnectionId uint64 `protobuf:"varint,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` // The local identity that was used by S2A during session setup and included // in |SessionResult|. LocalIdentity *common_go_proto.Identity `protobuf:"bytes,3,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` } func (x *ResumptionTicketReq) Reset() { *x = ResumptionTicketReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ResumptionTicketReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*ResumptionTicketReq) ProtoMessage() {} func (x *ResumptionTicketReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ResumptionTicketReq.ProtoReflect.Descriptor instead. func (*ResumptionTicketReq) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{4} } func (x *ResumptionTicketReq) GetInBytes() [][]byte { if x != nil { return x.InBytes } return nil } func (x *ResumptionTicketReq) GetConnectionId() uint64 { if x != nil { return x.ConnectionId } return 0 } func (x *ResumptionTicketReq) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } type SessionReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to ReqOneof: // // *SessionReq_ClientStart // *SessionReq_ServerStart // *SessionReq_Next // *SessionReq_ResumptionTicket ReqOneof isSessionReq_ReqOneof `protobuf_oneof:"req_oneof"` // (Optional) The authentication mechanisms that the client wishes to use to // authenticate to the S2A, ordered by preference. The S2A will always use the // first authentication mechanism that appears in the list and is supported by // the S2A. AuthMechanisms []*AuthenticationMechanism `protobuf:"bytes,5,rep,name=auth_mechanisms,json=authMechanisms,proto3" json:"auth_mechanisms,omitempty"` } func (x *SessionReq) Reset() { *x = SessionReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionReq) ProtoMessage() {} func (x *SessionReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionReq.ProtoReflect.Descriptor instead. func (*SessionReq) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{5} } func (m *SessionReq) GetReqOneof() isSessionReq_ReqOneof { if m != nil { return m.ReqOneof } return nil } func (x *SessionReq) GetClientStart() *ClientSessionStartReq { if x, ok := x.GetReqOneof().(*SessionReq_ClientStart); ok { return x.ClientStart } return nil } func (x *SessionReq) GetServerStart() *ServerSessionStartReq { if x, ok := x.GetReqOneof().(*SessionReq_ServerStart); ok { return x.ServerStart } return nil } func (x *SessionReq) GetNext() *SessionNextReq { if x, ok := x.GetReqOneof().(*SessionReq_Next); ok { return x.Next } return nil } func (x *SessionReq) GetResumptionTicket() *ResumptionTicketReq { if x, ok := x.GetReqOneof().(*SessionReq_ResumptionTicket); ok { return x.ResumptionTicket } return nil } func (x *SessionReq) GetAuthMechanisms() []*AuthenticationMechanism { if x != nil { return x.AuthMechanisms } return nil } type isSessionReq_ReqOneof interface { isSessionReq_ReqOneof() } type SessionReq_ClientStart struct { // The client session setup request message. ClientStart *ClientSessionStartReq `protobuf:"bytes,1,opt,name=client_start,json=clientStart,proto3,oneof"` } type SessionReq_ServerStart struct { // The server session setup request message. ServerStart *ServerSessionStartReq `protobuf:"bytes,2,opt,name=server_start,json=serverStart,proto3,oneof"` } type SessionReq_Next struct { // The next session setup message request message. Next *SessionNextReq `protobuf:"bytes,3,opt,name=next,proto3,oneof"` } type SessionReq_ResumptionTicket struct { // The resumption ticket that is received from the server. This message is // only accepted by S2A if it is running as a client and if it is received // after session setup is complete. If S2A is running as a server and it // receives this message, the session is terminated. ResumptionTicket *ResumptionTicketReq `protobuf:"bytes,4,opt,name=resumption_ticket,json=resumptionTicket,proto3,oneof"` } func (*SessionReq_ClientStart) isSessionReq_ReqOneof() {} func (*SessionReq_ServerStart) isSessionReq_ReqOneof() {} func (*SessionReq_Next) isSessionReq_ReqOneof() {} func (*SessionReq_ResumptionTicket) isSessionReq_ReqOneof() {} type SessionState struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The TLS version number that the S2A's handshaker module used to set up the // session. TlsVersion common_go_proto.TLSVersion `protobuf:"varint,1,opt,name=tls_version,json=tlsVersion,proto3,enum=s2a.proto.TLSVersion" json:"tls_version,omitempty"` // The TLS ciphersuite negotiated by the S2A's handshaker module. TlsCiphersuite common_go_proto.Ciphersuite `protobuf:"varint,2,opt,name=tls_ciphersuite,json=tlsCiphersuite,proto3,enum=s2a.proto.Ciphersuite" json:"tls_ciphersuite,omitempty"` // The sequence number of the next, incoming, TLS record. InSequence uint64 `protobuf:"varint,3,opt,name=in_sequence,json=inSequence,proto3" json:"in_sequence,omitempty"` // The sequence number of the next, outgoing, TLS record. OutSequence uint64 `protobuf:"varint,4,opt,name=out_sequence,json=outSequence,proto3" json:"out_sequence,omitempty"` // The key for the inbound direction. InKey []byte `protobuf:"bytes,5,opt,name=in_key,json=inKey,proto3" json:"in_key,omitempty"` // The key for the outbound direction. OutKey []byte `protobuf:"bytes,6,opt,name=out_key,json=outKey,proto3" json:"out_key,omitempty"` // The constant part of the record nonce for the outbound direction. InFixedNonce []byte `protobuf:"bytes,7,opt,name=in_fixed_nonce,json=inFixedNonce,proto3" json:"in_fixed_nonce,omitempty"` // The constant part of the record nonce for the inbound direction. OutFixedNonce []byte `protobuf:"bytes,8,opt,name=out_fixed_nonce,json=outFixedNonce,proto3" json:"out_fixed_nonce,omitempty"` // A connection identifier that can be provided to S2A to perform operations // related to this connection. This identifier will be stored by the record // protocol, and included in the |ResumptionTicketReq| message that is later // sent back to S2A. This field is set only for client-side connections. ConnectionId uint64 `protobuf:"varint,9,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` // Set to true if a cached session was reused to do an abbreviated handshake. IsHandshakeResumed bool `protobuf:"varint,10,opt,name=is_handshake_resumed,json=isHandshakeResumed,proto3" json:"is_handshake_resumed,omitempty"` } func (x *SessionState) Reset() { *x = SessionState{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionState) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionState) ProtoMessage() {} func (x *SessionState) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionState.ProtoReflect.Descriptor instead. func (*SessionState) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{6} } func (x *SessionState) GetTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.TlsVersion } return common_go_proto.TLSVersion(0) } func (x *SessionState) GetTlsCiphersuite() common_go_proto.Ciphersuite { if x != nil { return x.TlsCiphersuite } return common_go_proto.Ciphersuite(0) } func (x *SessionState) GetInSequence() uint64 { if x != nil { return x.InSequence } return 0 } func (x *SessionState) GetOutSequence() uint64 { if x != nil { return x.OutSequence } return 0 } func (x *SessionState) GetInKey() []byte { if x != nil { return x.InKey } return nil } func (x *SessionState) GetOutKey() []byte { if x != nil { return x.OutKey } return nil } func (x *SessionState) GetInFixedNonce() []byte { if x != nil { return x.InFixedNonce } return nil } func (x *SessionState) GetOutFixedNonce() []byte { if x != nil { return x.OutFixedNonce } return nil } func (x *SessionState) GetConnectionId() uint64 { if x != nil { return x.ConnectionId } return 0 } func (x *SessionState) GetIsHandshakeResumed() bool { if x != nil { return x.IsHandshakeResumed } return false } type SessionResult struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The application protocol negotiated for this session. ApplicationProtocol string `protobuf:"bytes,1,opt,name=application_protocol,json=applicationProtocol,proto3" json:"application_protocol,omitempty"` // The session state at the end. This state contains all cryptographic // material required to initialize the record protocol object. State *SessionState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` // The authenticated identity of the peer. PeerIdentity *common_go_proto.Identity `protobuf:"bytes,4,opt,name=peer_identity,json=peerIdentity,proto3" json:"peer_identity,omitempty"` // The local identity used during session setup. This could be: // - The local identity that the client specifies in ClientSessionStartReq. // - One of the local identities that the server specifies in // ServerSessionStartReq. // - If neither client or server specifies local identities, the S2A picks the // default one. In this case, this field will contain that identity. LocalIdentity *common_go_proto.Identity `protobuf:"bytes,5,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` // The SHA256 hash of the local certificate used in the handshake. LocalCertFingerprint []byte `protobuf:"bytes,6,opt,name=local_cert_fingerprint,json=localCertFingerprint,proto3" json:"local_cert_fingerprint,omitempty"` // The SHA256 hash of the peer certificate used in the handshake. PeerCertFingerprint []byte `protobuf:"bytes,7,opt,name=peer_cert_fingerprint,json=peerCertFingerprint,proto3" json:"peer_cert_fingerprint,omitempty"` } func (x *SessionResult) Reset() { *x = SessionResult{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionResult) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionResult) ProtoMessage() {} func (x *SessionResult) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionResult.ProtoReflect.Descriptor instead. func (*SessionResult) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{7} } func (x *SessionResult) GetApplicationProtocol() string { if x != nil { return x.ApplicationProtocol } return "" } func (x *SessionResult) GetState() *SessionState { if x != nil { return x.State } return nil } func (x *SessionResult) GetPeerIdentity() *common_go_proto.Identity { if x != nil { return x.PeerIdentity } return nil } func (x *SessionResult) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } func (x *SessionResult) GetLocalCertFingerprint() []byte { if x != nil { return x.LocalCertFingerprint } return nil } func (x *SessionResult) GetPeerCertFingerprint() []byte { if x != nil { return x.PeerCertFingerprint } return nil } type SessionStatus struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The status code that is specific to the application and the implementation // of S2A, e.g., gRPC status code. Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // The status details. Details string `protobuf:"bytes,2,opt,name=details,proto3" json:"details,omitempty"` } func (x *SessionStatus) Reset() { *x = SessionStatus{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionStatus) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionStatus) ProtoMessage() {} func (x *SessionStatus) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionStatus.ProtoReflect.Descriptor instead. func (*SessionStatus) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{8} } func (x *SessionStatus) GetCode() uint32 { if x != nil { return x.Code } return 0 } func (x *SessionStatus) GetDetails() string { if x != nil { return x.Details } return "" } type SessionResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The local identity used during session setup. This could be: // - The local identity that the client specifies in ClientSessionStartReq. // - One of the local identities that the server specifies in // ServerSessionStartReq. // - If neither client or server specifies local identities, the S2A picks the // default one. In this case, this field will contain that identity. // // If the SessionResult is populated, then this must coincide with the local // identity specified in the SessionResult; otherwise, the handshake must // fail. LocalIdentity *common_go_proto.Identity `protobuf:"bytes,1,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` // The byte representation of the frames that should be sent to the peer. May // be empty if nothing needs to be sent to the peer or if in_bytes in the // SessionReq is incomplete. All bytes in a non-empty out_frames must be sent // to the peer even if the session setup status is not OK as these frames may // contain appropriate alerts. OutFrames []byte `protobuf:"bytes,2,opt,name=out_frames,json=outFrames,proto3" json:"out_frames,omitempty"` // Number of bytes in the in_bytes field that are consumed by S2A. It is // possible that part of in_bytes is unrelated to the session setup process. BytesConsumed uint32 `protobuf:"varint,3,opt,name=bytes_consumed,json=bytesConsumed,proto3" json:"bytes_consumed,omitempty"` // This is set if the session is successfully set up. out_frames may // still be set to frames that needs to be forwarded to the peer. Result *SessionResult `protobuf:"bytes,4,opt,name=result,proto3" json:"result,omitempty"` // Status of session setup at the current stage. Status *SessionStatus `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` } func (x *SessionResp) Reset() { *x = SessionResp{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionResp) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionResp) ProtoMessage() {} func (x *SessionResp) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_s2a_s2a_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionResp.ProtoReflect.Descriptor instead. func (*SessionResp) Descriptor() ([]byte, []int) { return file_internal_proto_s2a_s2a_proto_rawDescGZIP(), []int{9} } func (x *SessionResp) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } func (x *SessionResp) GetOutFrames() []byte { if x != nil { return x.OutFrames } return nil } func (x *SessionResp) GetBytesConsumed() uint32 { if x != nil { return x.BytesConsumed } return 0 } func (x *SessionResp) GetResult() *SessionResult { if x != nil { return x.Result } return nil } func (x *SessionResp) GetStatus() *SessionStatus { if x != nil { return x.Status } return nil } var File_internal_proto_s2a_s2a_proto protoreflect.FileDescriptor var file_internal_proto_s2a_s2a_proto_rawDesc = []byte{ 0x0a, 0x1c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x17, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x12, 0x2f, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0xac, 0x03, 0x0a, 0x15, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x12, 0x33, 0x0a, 0x15, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x3d, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x10, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0f, 0x74, 0x6c, 0x73, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xe8, 0x02, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x12, 0x33, 0x0a, 0x15, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x3d, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x10, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0f, 0x74, 0x6c, 0x73, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x2b, 0x0a, 0x0e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xf4, 0x02, 0x0a, 0x0a, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x45, 0x0a, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x45, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6e, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x65, 0x78, 0x74, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x4b, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0xa0, 0x03, 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x74, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0f, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0e, 0x74, 0x6c, 0x73, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6e, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x69, 0x6e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x73, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x73, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x22, 0xd1, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x31, 0x0a, 0x14, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x70, 0x65, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x70, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x3d, 0x0a, 0x0d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0xf3, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0x51, 0x0a, 0x0a, 0x53, 0x32, 0x41, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x55, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_s2a_s2a_proto_rawDescOnce sync.Once file_internal_proto_s2a_s2a_proto_rawDescData = file_internal_proto_s2a_s2a_proto_rawDesc ) func file_internal_proto_s2a_s2a_proto_rawDescGZIP() []byte { file_internal_proto_s2a_s2a_proto_rawDescOnce.Do(func() { file_internal_proto_s2a_s2a_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_s2a_s2a_proto_rawDescData) }) return file_internal_proto_s2a_s2a_proto_rawDescData } var file_internal_proto_s2a_s2a_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_internal_proto_s2a_s2a_proto_goTypes = []any{ (*AuthenticationMechanism)(nil), // 0: s2a.proto.AuthenticationMechanism (*ClientSessionStartReq)(nil), // 1: s2a.proto.ClientSessionStartReq (*ServerSessionStartReq)(nil), // 2: s2a.proto.ServerSessionStartReq (*SessionNextReq)(nil), // 3: s2a.proto.SessionNextReq (*ResumptionTicketReq)(nil), // 4: s2a.proto.ResumptionTicketReq (*SessionReq)(nil), // 5: s2a.proto.SessionReq (*SessionState)(nil), // 6: s2a.proto.SessionState (*SessionResult)(nil), // 7: s2a.proto.SessionResult (*SessionStatus)(nil), // 8: s2a.proto.SessionStatus (*SessionResp)(nil), // 9: s2a.proto.SessionResp (*common_go_proto.Identity)(nil), // 10: s2a.proto.Identity (common_go_proto.TLSVersion)(0), // 11: s2a.proto.TLSVersion (common_go_proto.Ciphersuite)(0), // 12: s2a.proto.Ciphersuite } var file_internal_proto_s2a_s2a_proto_depIdxs = []int32{ 10, // 0: s2a.proto.AuthenticationMechanism.identity:type_name -> s2a.proto.Identity 11, // 1: s2a.proto.ClientSessionStartReq.min_tls_version:type_name -> s2a.proto.TLSVersion 11, // 2: s2a.proto.ClientSessionStartReq.max_tls_version:type_name -> s2a.proto.TLSVersion 12, // 3: s2a.proto.ClientSessionStartReq.tls_ciphersuites:type_name -> s2a.proto.Ciphersuite 10, // 4: s2a.proto.ClientSessionStartReq.target_identities:type_name -> s2a.proto.Identity 10, // 5: s2a.proto.ClientSessionStartReq.local_identity:type_name -> s2a.proto.Identity 11, // 6: s2a.proto.ServerSessionStartReq.min_tls_version:type_name -> s2a.proto.TLSVersion 11, // 7: s2a.proto.ServerSessionStartReq.max_tls_version:type_name -> s2a.proto.TLSVersion 12, // 8: s2a.proto.ServerSessionStartReq.tls_ciphersuites:type_name -> s2a.proto.Ciphersuite 10, // 9: s2a.proto.ServerSessionStartReq.local_identities:type_name -> s2a.proto.Identity 10, // 10: s2a.proto.ResumptionTicketReq.local_identity:type_name -> s2a.proto.Identity 1, // 11: s2a.proto.SessionReq.client_start:type_name -> s2a.proto.ClientSessionStartReq 2, // 12: s2a.proto.SessionReq.server_start:type_name -> s2a.proto.ServerSessionStartReq 3, // 13: s2a.proto.SessionReq.next:type_name -> s2a.proto.SessionNextReq 4, // 14: s2a.proto.SessionReq.resumption_ticket:type_name -> s2a.proto.ResumptionTicketReq 0, // 15: s2a.proto.SessionReq.auth_mechanisms:type_name -> s2a.proto.AuthenticationMechanism 11, // 16: s2a.proto.SessionState.tls_version:type_name -> s2a.proto.TLSVersion 12, // 17: s2a.proto.SessionState.tls_ciphersuite:type_name -> s2a.proto.Ciphersuite 6, // 18: s2a.proto.SessionResult.state:type_name -> s2a.proto.SessionState 10, // 19: s2a.proto.SessionResult.peer_identity:type_name -> s2a.proto.Identity 10, // 20: s2a.proto.SessionResult.local_identity:type_name -> s2a.proto.Identity 10, // 21: s2a.proto.SessionResp.local_identity:type_name -> s2a.proto.Identity 7, // 22: s2a.proto.SessionResp.result:type_name -> s2a.proto.SessionResult 8, // 23: s2a.proto.SessionResp.status:type_name -> s2a.proto.SessionStatus 5, // 24: s2a.proto.S2AService.SetUpSession:input_type -> s2a.proto.SessionReq 9, // 25: s2a.proto.S2AService.SetUpSession:output_type -> s2a.proto.SessionResp 25, // [25:26] is the sub-list for method output_type 24, // [24:25] is the sub-list for method input_type 24, // [24:24] is the sub-list for extension type_name 24, // [24:24] is the sub-list for extension extendee 0, // [0:24] is the sub-list for field type_name } func init() { file_internal_proto_s2a_s2a_proto_init() } func file_internal_proto_s2a_s2a_proto_init() { if File_internal_proto_s2a_s2a_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_s2a_s2a_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*AuthenticationMechanism); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*ClientSessionStartReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*ServerSessionStartReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*SessionNextReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*ResumptionTicketReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*SessionReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*SessionState); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*SessionResult); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[8].Exporter = func(v any, i int) any { switch v := v.(*SessionStatus); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_s2a_s2a_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*SessionResp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_internal_proto_s2a_s2a_proto_msgTypes[0].OneofWrappers = []any{ (*AuthenticationMechanism_Token)(nil), } file_internal_proto_s2a_s2a_proto_msgTypes[5].OneofWrappers = []any{ (*SessionReq_ClientStart)(nil), (*SessionReq_ServerStart)(nil), (*SessionReq_Next)(nil), (*SessionReq_ResumptionTicket)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_s2a_s2a_proto_rawDesc, NumEnums: 0, NumMessages: 10, NumExtensions: 0, NumServices: 1, }, GoTypes: file_internal_proto_s2a_s2a_proto_goTypes, DependencyIndexes: file_internal_proto_s2a_s2a_proto_depIdxs, MessageInfos: file_internal_proto_s2a_s2a_proto_msgTypes, }.Build() File_internal_proto_s2a_s2a_proto = out.File file_internal_proto_s2a_s2a_proto_rawDesc = nil file_internal_proto_s2a_s2a_proto_goTypes = nil file_internal_proto_s2a_s2a_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/s2a_go_proto/s2a_grpc.pb.go000066400000000000000000000140051464711036600226230ustar00rootroot00000000000000// Copyright 2021 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. // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.4.0 // - protoc v3.21.12 // source: internal/proto/s2a/s2a.proto package s2a_go_proto import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.62.0 or later. const _ = grpc.SupportPackageIsVersion8 const ( S2AService_SetUpSession_FullMethodName = "/s2a.proto.S2AService/SetUpSession" ) // S2AServiceClient is the client API for S2AService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type S2AServiceClient interface { // S2A service accepts a stream of session setup requests and returns a stream // of session setup responses. The client of this service is expected to send // exactly one client_start or server_start message followed by at least one // next message. Applications running TLS clients can send requests with // resumption_ticket messages only after the session is successfully set up. // // Every time S2A client sends a request, this service sends a response. // However, clients do not have to wait for service response before sending // the next request. SetUpSession(ctx context.Context, opts ...grpc.CallOption) (S2AService_SetUpSessionClient, error) } type s2AServiceClient struct { cc grpc.ClientConnInterface } func NewS2AServiceClient(cc grpc.ClientConnInterface) S2AServiceClient { return &s2AServiceClient{cc} } func (c *s2AServiceClient) SetUpSession(ctx context.Context, opts ...grpc.CallOption) (S2AService_SetUpSessionClient, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &S2AService_ServiceDesc.Streams[0], S2AService_SetUpSession_FullMethodName, cOpts...) if err != nil { return nil, err } x := &s2AServiceSetUpSessionClient{ClientStream: stream} return x, nil } type S2AService_SetUpSessionClient interface { Send(*SessionReq) error Recv() (*SessionResp, error) grpc.ClientStream } type s2AServiceSetUpSessionClient struct { grpc.ClientStream } func (x *s2AServiceSetUpSessionClient) Send(m *SessionReq) error { return x.ClientStream.SendMsg(m) } func (x *s2AServiceSetUpSessionClient) Recv() (*SessionResp, error) { m := new(SessionResp) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // S2AServiceServer is the server API for S2AService service. // All implementations must embed UnimplementedS2AServiceServer // for forward compatibility type S2AServiceServer interface { // S2A service accepts a stream of session setup requests and returns a stream // of session setup responses. The client of this service is expected to send // exactly one client_start or server_start message followed by at least one // next message. Applications running TLS clients can send requests with // resumption_ticket messages only after the session is successfully set up. // // Every time S2A client sends a request, this service sends a response. // However, clients do not have to wait for service response before sending // the next request. SetUpSession(S2AService_SetUpSessionServer) error mustEmbedUnimplementedS2AServiceServer() } // UnimplementedS2AServiceServer must be embedded to have forward compatible implementations. type UnimplementedS2AServiceServer struct { } func (UnimplementedS2AServiceServer) SetUpSession(S2AService_SetUpSessionServer) error { return status.Errorf(codes.Unimplemented, "method SetUpSession not implemented") } func (UnimplementedS2AServiceServer) mustEmbedUnimplementedS2AServiceServer() {} // UnsafeS2AServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to S2AServiceServer will // result in compilation errors. type UnsafeS2AServiceServer interface { mustEmbedUnimplementedS2AServiceServer() } func RegisterS2AServiceServer(s grpc.ServiceRegistrar, srv S2AServiceServer) { s.RegisterService(&S2AService_ServiceDesc, srv) } func _S2AService_SetUpSession_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(S2AServiceServer).SetUpSession(&s2AServiceSetUpSessionServer{ServerStream: stream}) } type S2AService_SetUpSessionServer interface { Send(*SessionResp) error Recv() (*SessionReq, error) grpc.ServerStream } type s2AServiceSetUpSessionServer struct { grpc.ServerStream } func (x *s2AServiceSetUpSessionServer) Send(m *SessionResp) error { return x.ServerStream.SendMsg(m) } func (x *s2AServiceSetUpSessionServer) Recv() (*SessionReq, error) { m := new(SessionReq) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // S2AService_ServiceDesc is the grpc.ServiceDesc for S2AService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var S2AService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "s2a.proto.S2AService", HandlerType: (*S2AServiceServer)(nil), Methods: []grpc.MethodDesc{}, Streams: []grpc.StreamDesc{ { StreamName: "SetUpSession", Handler: _S2AService_SetUpSession_Handler, ServerStreams: true, ClientStreams: true, }, }, Metadata: "internal/proto/s2a/s2a.proto", } s2a-go-0.1.8/internal/proto/v2/000077500000000000000000000000001464711036600161265ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/common/000077500000000000000000000000001464711036600174165ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/common/common.proto000066400000000000000000000043041464711036600217740ustar00rootroot00000000000000// 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. syntax = "proto3"; package s2a.proto.v2; option go_package = "github.com/google/s2a/internal/proto/v2/common_go_proto"; // The TLS 1.0-1.2 ciphersuites that the application can negotiate when using // S2A. enum Ciphersuite { CIPHERSUITE_UNSPECIFIED = 0; CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 1; CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 2; CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 3; CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 4; CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 5; CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 6; } // The TLS versions supported by S2A's handshaker module. enum TLSVersion { TLS_VERSION_UNSPECIFIED = 0; TLS_VERSION_1_0 = 1; TLS_VERSION_1_1 = 2; TLS_VERSION_1_2 = 3; TLS_VERSION_1_3 = 4; } // The side in the TLS connection. enum ConnectionSide { CONNECTION_SIDE_UNSPECIFIED = 0; CONNECTION_SIDE_CLIENT = 1; CONNECTION_SIDE_SERVER = 2; } // The ALPN protocols that the application can negotiate during a TLS handshake. enum AlpnProtocol { ALPN_PROTOCOL_UNSPECIFIED = 0; ALPN_PROTOCOL_GRPC = 1; ALPN_PROTOCOL_HTTP2 = 2; ALPN_PROTOCOL_HTTP1_1 = 3; } message Identity { oneof identity_oneof { // The SPIFFE ID of a connection endpoint. string spiffe_id = 1; // The hostname of a connection endpoint. string hostname = 2; // The UID of a connection endpoint. string uid = 4; // The username of a connection endpoint. string username = 5; // The GCP ID of a connection endpoint. string gcp_id = 6; } // Additional identity-specific attributes. map attributes = 3; } s2a-go-0.1.8/internal/proto/v2/common_go_proto/000077500000000000000000000000001464711036600213265ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/common_go_proto/common.pb.go000066400000000000000000000520661464711036600235560ustar00rootroot00000000000000// 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/v2/common/common.proto package common_go_proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) // The TLS 1.0-1.2 ciphersuites that the application can negotiate when using // S2A. type Ciphersuite int32 const ( Ciphersuite_CIPHERSUITE_UNSPECIFIED Ciphersuite = 0 Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 Ciphersuite = 1 Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 Ciphersuite = 2 Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 Ciphersuite = 3 Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256 Ciphersuite = 4 Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Ciphersuite = 5 Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 Ciphersuite = 6 ) // Enum value maps for Ciphersuite. var ( Ciphersuite_name = map[int32]string{ 0: "CIPHERSUITE_UNSPECIFIED", 1: "CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 2: "CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 3: "CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 4: "CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 5: "CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 6: "CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", } Ciphersuite_value = map[string]int32{ "CIPHERSUITE_UNSPECIFIED": 0, "CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": 1, "CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": 2, "CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": 3, "CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256": 4, "CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384": 5, "CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": 6, } ) func (x Ciphersuite) Enum() *Ciphersuite { p := new(Ciphersuite) *p = x return p } func (x Ciphersuite) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Ciphersuite) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_common_common_proto_enumTypes[0].Descriptor() } func (Ciphersuite) Type() protoreflect.EnumType { return &file_internal_proto_v2_common_common_proto_enumTypes[0] } func (x Ciphersuite) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Ciphersuite.Descriptor instead. func (Ciphersuite) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_common_common_proto_rawDescGZIP(), []int{0} } // The TLS versions supported by S2A's handshaker module. type TLSVersion int32 const ( TLSVersion_TLS_VERSION_UNSPECIFIED TLSVersion = 0 TLSVersion_TLS_VERSION_1_0 TLSVersion = 1 TLSVersion_TLS_VERSION_1_1 TLSVersion = 2 TLSVersion_TLS_VERSION_1_2 TLSVersion = 3 TLSVersion_TLS_VERSION_1_3 TLSVersion = 4 ) // Enum value maps for TLSVersion. var ( TLSVersion_name = map[int32]string{ 0: "TLS_VERSION_UNSPECIFIED", 1: "TLS_VERSION_1_0", 2: "TLS_VERSION_1_1", 3: "TLS_VERSION_1_2", 4: "TLS_VERSION_1_3", } TLSVersion_value = map[string]int32{ "TLS_VERSION_UNSPECIFIED": 0, "TLS_VERSION_1_0": 1, "TLS_VERSION_1_1": 2, "TLS_VERSION_1_2": 3, "TLS_VERSION_1_3": 4, } ) func (x TLSVersion) Enum() *TLSVersion { p := new(TLSVersion) *p = x return p } func (x TLSVersion) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (TLSVersion) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_common_common_proto_enumTypes[1].Descriptor() } func (TLSVersion) Type() protoreflect.EnumType { return &file_internal_proto_v2_common_common_proto_enumTypes[1] } func (x TLSVersion) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use TLSVersion.Descriptor instead. func (TLSVersion) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_common_common_proto_rawDescGZIP(), []int{1} } // The side in the TLS connection. type ConnectionSide int32 const ( ConnectionSide_CONNECTION_SIDE_UNSPECIFIED ConnectionSide = 0 ConnectionSide_CONNECTION_SIDE_CLIENT ConnectionSide = 1 ConnectionSide_CONNECTION_SIDE_SERVER ConnectionSide = 2 ) // Enum value maps for ConnectionSide. var ( ConnectionSide_name = map[int32]string{ 0: "CONNECTION_SIDE_UNSPECIFIED", 1: "CONNECTION_SIDE_CLIENT", 2: "CONNECTION_SIDE_SERVER", } ConnectionSide_value = map[string]int32{ "CONNECTION_SIDE_UNSPECIFIED": 0, "CONNECTION_SIDE_CLIENT": 1, "CONNECTION_SIDE_SERVER": 2, } ) func (x ConnectionSide) Enum() *ConnectionSide { p := new(ConnectionSide) *p = x return p } func (x ConnectionSide) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ConnectionSide) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_common_common_proto_enumTypes[2].Descriptor() } func (ConnectionSide) Type() protoreflect.EnumType { return &file_internal_proto_v2_common_common_proto_enumTypes[2] } func (x ConnectionSide) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ConnectionSide.Descriptor instead. func (ConnectionSide) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_common_common_proto_rawDescGZIP(), []int{2} } // The ALPN protocols that the application can negotiate during a TLS handshake. type AlpnProtocol int32 const ( AlpnProtocol_ALPN_PROTOCOL_UNSPECIFIED AlpnProtocol = 0 AlpnProtocol_ALPN_PROTOCOL_GRPC AlpnProtocol = 1 AlpnProtocol_ALPN_PROTOCOL_HTTP2 AlpnProtocol = 2 AlpnProtocol_ALPN_PROTOCOL_HTTP1_1 AlpnProtocol = 3 ) // Enum value maps for AlpnProtocol. var ( AlpnProtocol_name = map[int32]string{ 0: "ALPN_PROTOCOL_UNSPECIFIED", 1: "ALPN_PROTOCOL_GRPC", 2: "ALPN_PROTOCOL_HTTP2", 3: "ALPN_PROTOCOL_HTTP1_1", } AlpnProtocol_value = map[string]int32{ "ALPN_PROTOCOL_UNSPECIFIED": 0, "ALPN_PROTOCOL_GRPC": 1, "ALPN_PROTOCOL_HTTP2": 2, "ALPN_PROTOCOL_HTTP1_1": 3, } ) func (x AlpnProtocol) Enum() *AlpnProtocol { p := new(AlpnProtocol) *p = x return p } func (x AlpnProtocol) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (AlpnProtocol) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_common_common_proto_enumTypes[3].Descriptor() } func (AlpnProtocol) Type() protoreflect.EnumType { return &file_internal_proto_v2_common_common_proto_enumTypes[3] } func (x AlpnProtocol) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use AlpnProtocol.Descriptor instead. func (AlpnProtocol) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_common_common_proto_rawDescGZIP(), []int{3} } type Identity struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to IdentityOneof: // // *Identity_SpiffeId // *Identity_Hostname // *Identity_Uid // *Identity_Username // *Identity_GcpId IdentityOneof isIdentity_IdentityOneof `protobuf_oneof:"identity_oneof"` // Additional identity-specific attributes. Attributes map[string]string `protobuf:"bytes,3,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Identity) Reset() { *x = Identity{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_common_common_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Identity) String() string { return protoimpl.X.MessageStringOf(x) } func (*Identity) ProtoMessage() {} func (x *Identity) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_common_common_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Identity.ProtoReflect.Descriptor instead. func (*Identity) Descriptor() ([]byte, []int) { return file_internal_proto_v2_common_common_proto_rawDescGZIP(), []int{0} } func (m *Identity) GetIdentityOneof() isIdentity_IdentityOneof { if m != nil { return m.IdentityOneof } return nil } func (x *Identity) GetSpiffeId() string { if x, ok := x.GetIdentityOneof().(*Identity_SpiffeId); ok { return x.SpiffeId } return "" } func (x *Identity) GetHostname() string { if x, ok := x.GetIdentityOneof().(*Identity_Hostname); ok { return x.Hostname } return "" } func (x *Identity) GetUid() string { if x, ok := x.GetIdentityOneof().(*Identity_Uid); ok { return x.Uid } return "" } func (x *Identity) GetUsername() string { if x, ok := x.GetIdentityOneof().(*Identity_Username); ok { return x.Username } return "" } func (x *Identity) GetGcpId() string { if x, ok := x.GetIdentityOneof().(*Identity_GcpId); ok { return x.GcpId } return "" } func (x *Identity) GetAttributes() map[string]string { if x != nil { return x.Attributes } return nil } type isIdentity_IdentityOneof interface { isIdentity_IdentityOneof() } type Identity_SpiffeId struct { // The SPIFFE ID of a connection endpoint. SpiffeId string `protobuf:"bytes,1,opt,name=spiffe_id,json=spiffeId,proto3,oneof"` } type Identity_Hostname struct { // The hostname of a connection endpoint. Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3,oneof"` } type Identity_Uid struct { // The UID of a connection endpoint. Uid string `protobuf:"bytes,4,opt,name=uid,proto3,oneof"` } type Identity_Username struct { // The username of a connection endpoint. Username string `protobuf:"bytes,5,opt,name=username,proto3,oneof"` } type Identity_GcpId struct { // The GCP ID of a connection endpoint. GcpId string `protobuf:"bytes,6,opt,name=gcp_id,json=gcpId,proto3,oneof"` } func (*Identity_SpiffeId) isIdentity_IdentityOneof() {} func (*Identity_Hostname) isIdentity_IdentityOneof() {} func (*Identity_Uid) isIdentity_IdentityOneof() {} func (*Identity_Username) isIdentity_IdentityOneof() {} func (*Identity_GcpId) isIdentity_IdentityOneof() {} var File_internal_proto_v2_common_common_proto protoreflect.FileDescriptor var file_internal_proto_v2_common_common_proto_rawDesc = []byte{ 0x0a, 0x25, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x22, 0xab, 0x02, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x09, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x06, 0x67, 0x63, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x67, 0x63, 0x70, 0x49, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x2a, 0xee, 0x02, 0x0a, 0x0b, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x33, 0x0a, 0x2f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x33, 0x0a, 0x2f, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x39, 0x0a, 0x35, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x03, 0x12, 0x31, 0x0a, 0x2d, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x04, 0x12, 0x31, 0x0a, 0x2d, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x05, 0x12, 0x37, 0x0a, 0x33, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x53, 0x55, 0x49, 0x54, 0x45, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x45, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x06, 0x2a, 0x7d, 0x0a, 0x0a, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x30, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x31, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x32, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x4c, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x33, 0x10, 0x04, 0x2a, 0x69, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x2a, 0x79, 0x0a, 0x0c, 0x41, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4c, 0x50, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x4c, 0x50, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x52, 0x50, 0x43, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x4c, 0x50, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x32, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x4c, 0x50, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x48, 0x54, 0x54, 0x50, 0x31, 0x5f, 0x31, 0x10, 0x03, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_v2_common_common_proto_rawDescOnce sync.Once file_internal_proto_v2_common_common_proto_rawDescData = file_internal_proto_v2_common_common_proto_rawDesc ) func file_internal_proto_v2_common_common_proto_rawDescGZIP() []byte { file_internal_proto_v2_common_common_proto_rawDescOnce.Do(func() { file_internal_proto_v2_common_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_v2_common_common_proto_rawDescData) }) return file_internal_proto_v2_common_common_proto_rawDescData } var file_internal_proto_v2_common_common_proto_enumTypes = make([]protoimpl.EnumInfo, 4) var file_internal_proto_v2_common_common_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_internal_proto_v2_common_common_proto_goTypes = []any{ (Ciphersuite)(0), // 0: s2a.proto.v2.Ciphersuite (TLSVersion)(0), // 1: s2a.proto.v2.TLSVersion (ConnectionSide)(0), // 2: s2a.proto.v2.ConnectionSide (AlpnProtocol)(0), // 3: s2a.proto.v2.AlpnProtocol (*Identity)(nil), // 4: s2a.proto.v2.Identity nil, // 5: s2a.proto.v2.Identity.AttributesEntry } var file_internal_proto_v2_common_common_proto_depIdxs = []int32{ 5, // 0: s2a.proto.v2.Identity.attributes:type_name -> s2a.proto.v2.Identity.AttributesEntry 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_internal_proto_v2_common_common_proto_init() } func file_internal_proto_v2_common_common_proto_init() { if File_internal_proto_v2_common_common_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_v2_common_common_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*Identity); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_internal_proto_v2_common_common_proto_msgTypes[0].OneofWrappers = []any{ (*Identity_SpiffeId)(nil), (*Identity_Hostname)(nil), (*Identity_Uid)(nil), (*Identity_Username)(nil), (*Identity_GcpId)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_v2_common_common_proto_rawDesc, NumEnums: 4, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, GoTypes: file_internal_proto_v2_common_common_proto_goTypes, DependencyIndexes: file_internal_proto_v2_common_common_proto_depIdxs, EnumInfos: file_internal_proto_v2_common_common_proto_enumTypes, MessageInfos: file_internal_proto_v2_common_common_proto_msgTypes, }.Build() File_internal_proto_v2_common_common_proto = out.File file_internal_proto_v2_common_common_proto_rawDesc = nil file_internal_proto_v2_common_common_proto_goTypes = nil file_internal_proto_v2_common_common_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/v2/s2a/000077500000000000000000000000001464711036600166135ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/s2a/s2a.proto000066400000000000000000000315641464711036600203760ustar00rootroot00000000000000// 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. syntax = "proto3"; package s2a.proto.v2; option go_package = "github.com/google/s2a/internal/proto/v2/s2a_go_proto"; import "internal/proto/v2/common/common.proto"; import "internal/proto/v2/s2a_context/s2a_context.proto"; enum SignatureAlgorithm { S2A_SSL_SIGN_UNSPECIFIED = 0; // RSA Public-Key Cryptography Standards #1. S2A_SSL_SIGN_RSA_PKCS1_SHA256 = 1; S2A_SSL_SIGN_RSA_PKCS1_SHA384 = 2; S2A_SSL_SIGN_RSA_PKCS1_SHA512 = 3; // ECDSA. S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256 = 4; S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384 = 5; S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512 = 6; // RSA Probabilistic Signature Scheme. S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256 = 7; S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384 = 8; S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512 = 9; // ED25519. S2A_SSL_SIGN_ED25519 = 10; } message AlpnPolicy { // If true, the application MUST perform ALPN negotiation. bool enable_alpn_negotiation = 1; // The ordered list of ALPN protocols that specify how the application SHOULD // negotiate ALPN during the TLS handshake. // // The application MAY ignore any ALPN protocols in this list that are not // supported by the application. repeated AlpnProtocol alpn_protocols = 2; } message AuthenticationMechanism { reserved 1; // Applications may specify an identity associated to an authentication // mechanism. Otherwise, S2A assumes that the authentication mechanism is // associated with the default identity. If the default identity cannot be // determined, the request is rejected. Identity identity = 3; oneof mechanism_oneof { // A token that the application uses to authenticate itself to S2A. string token = 2; } } message Status { // The status code that is specific to the application and the implementation // of S2A, e.g., gRPC status code. uint32 code = 1; // The status details. string details = 2; } message GetTlsConfigurationReq { // The role of the application in the TLS connection. ConnectionSide connection_side = 1; // The server name indication (SNI) extension, which MAY be populated when a // server is offloading to S2A. The SNI is used to determine the server // identity if the local identity in the request is empty. string sni = 2; } message GetTlsConfigurationResp { // Next ID: 8 message ClientTlsConfiguration { reserved 4, 5; // The certificate chain that the client MUST use for the TLS handshake. // It's a list of PEM-encoded certificates, ordered from leaf to root, // excluding the root. repeated string certificate_chain = 1; // The minimum TLS version number that the client MUST use for the TLS // handshake. If this field is not provided, the client MUST use the default // minimum version of the client's TLS library. TLSVersion min_tls_version = 2; // The maximum TLS version number that the client MUST use for the TLS // handshake. If this field is not provided, the client MUST use the default // maximum version of the client's TLS library. TLSVersion max_tls_version = 3; // The ordered list of TLS 1.0-1.2 ciphersuites that the client MAY offer to // negotiate in the TLS handshake. repeated Ciphersuite ciphersuites = 6; // The policy that dictates how the client negotiates ALPN during the TLS // handshake. AlpnPolicy alpn_policy = 7; } // Next ID: 12 message ServerTlsConfiguration { reserved 4, 5; enum RequestClientCertificate { UNSPECIFIED = 0; DONT_REQUEST_CLIENT_CERTIFICATE = 1; REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY = 2; REQUEST_CLIENT_CERTIFICATE_AND_VERIFY = 3; REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY = 4; REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY = 5; } // The certificate chain that the server MUST use for the TLS handshake. // It's a list of PEM-encoded certificates, ordered from leaf to root, // excluding the root. repeated string certificate_chain = 1; // The minimum TLS version number that the server MUST use for the TLS // handshake. If this field is not provided, the server MUST use the default // minimum version of the server's TLS library. TLSVersion min_tls_version = 2; // The maximum TLS version number that the server MUST use for the TLS // handshake. If this field is not provided, the server MUST use the default // maximum version of the server's TLS library. TLSVersion max_tls_version = 3; // The ordered list of TLS 1.0-1.2 ciphersuites that the server MAY offer to // negotiate in the TLS handshake. repeated Ciphersuite ciphersuites = 10; // Whether to enable TLS resumption. bool tls_resumption_enabled = 6; // Whether the server MUST request a client certificate (i.e. to negotiate // TLS vs. mTLS). RequestClientCertificate request_client_certificate = 7; // Returns the maximum number of extra bytes that // |OffloadResumptionKeyOperation| can add to the number of unencrypted // bytes to form the encrypted bytes. uint32 max_overhead_of_ticket_aead = 9; // The policy that dictates how the server negotiates ALPN during the TLS // handshake. AlpnPolicy alpn_policy = 11; } oneof tls_configuration { ClientTlsConfiguration client_tls_configuration = 1; ServerTlsConfiguration server_tls_configuration = 2; } } message OffloadPrivateKeyOperationReq { enum PrivateKeyOperation { UNSPECIFIED = 0; // When performing a TLS 1.2 or 1.3 handshake, the (partial) transcript of // the TLS handshake must be signed to prove possession of the private key. // // See https://www.rfc-editor.org/rfc/rfc8446.html#section-4.4.3. SIGN = 1; // When performing a TLS 1.2 handshake using an RSA algorithm, the key // exchange algorithm involves the client generating a premaster secret, // encrypting it using the server's public key, and sending this encrypted // blob to the server in a ClientKeyExchange message. // // See https://www.rfc-editor.org/rfc/rfc4346#section-7.4.7.1. DECRYPT = 2; } // The operation the private key is used for. PrivateKeyOperation operation = 1; // The signature algorithm to be used for signing operations. SignatureAlgorithm signature_algorithm = 2; // The input bytes to be signed or decrypted. oneof in_bytes { // Raw bytes to be hashed and signed, or decrypted. bytes raw_bytes = 4; // A SHA256 hash to be signed. Must be 32 bytes. bytes sha256_digest = 5; // A SHA384 hash to be signed. Must be 48 bytes. bytes sha384_digest = 6; // A SHA512 hash to be signed. Must be 64 bytes. bytes sha512_digest = 7; } } message OffloadPrivateKeyOperationResp { // The signed or decrypted output bytes. bytes out_bytes = 1; } message OffloadResumptionKeyOperationReq { enum ResumptionKeyOperation { UNSPECIFIED = 0; ENCRYPT = 1; DECRYPT = 2; } // The operation the resumption key is used for. ResumptionKeyOperation operation = 1; // The bytes to be encrypted or decrypted. bytes in_bytes = 2; } message OffloadResumptionKeyOperationResp { // The encrypted or decrypted bytes. bytes out_bytes = 1; } message ValidatePeerCertificateChainReq { enum VerificationMode { // The default verification mode supported by S2A. UNSPECIFIED = 0; // The SPIFFE verification mode selects the set of trusted certificates to // use for path building based on the SPIFFE trust domain in the peer's leaf // certificate. SPIFFE = 1; // The connect-to-Google verification mode uses the trust bundle for // connecting to Google, e.g. *.mtls.googleapis.com endpoints. CONNECT_TO_GOOGLE = 2; // Internal use only. RESERVED_CUSTOM_VERIFICATION_MODE_3 = 3; // Internal use only. RESERVED_CUSTOM_VERIFICATION_MODE_4 = 4; // Internal use only. RESERVED_CUSTOM_VERIFICATION_MODE_5 = 5; } message ClientPeer { // The certificate chain to be verified. The chain MUST be a list of // DER-encoded certificates, ordered from leaf to root, excluding the root. repeated bytes certificate_chain = 1; } message ServerPeer { // The certificate chain to be verified. The chain MUST be a list of // DER-encoded certificates, ordered from leaf to root, excluding the root. repeated bytes certificate_chain = 1; // The expected hostname of the server. string server_hostname = 2; // The UnrestrictedClientPolicy specified by the user. bytes serialized_unrestricted_client_policy = 3; } // The verification mode that S2A MUST use to validate the peer certificate // chain. VerificationMode mode = 1; oneof peer_oneof { ClientPeer client_peer = 2; ServerPeer server_peer = 3; } } message ValidatePeerCertificateChainResp { enum ValidationResult { UNSPECIFIED = 0; SUCCESS = 1; FAILURE = 2; } // The result of validating the peer certificate chain. ValidationResult validation_result = 1; // The validation details. This field is only populated when the validation // result is NOT SUCCESS. string validation_details = 2; // The S2A context contains information from the peer certificate chain. // // The S2A context MAY be populated even if validation of the peer certificate // chain fails. S2AContext context = 3; } message SessionReq { reserved 1; // The identity corresponding to the TLS configurations that MUST be used for // the TLS handshake. // // If a managed identity already exists, the local identity and authentication // mechanisms are ignored. If a managed identity doesn't exist and the local // identity is not populated, S2A will try to deduce the managed identity to // use from the SNI extension. If that also fails, S2A uses the default // identity (if one exists). Identity local_identity = 7; // The authentication mechanisms that the application wishes to use to // authenticate to S2A, ordered by preference. S2A will always use the first // authentication mechanism that matches the managed identity. repeated AuthenticationMechanism authentication_mechanisms = 2; oneof req_oneof { // Requests the certificate chain and TLS configuration corresponding to the // local identity, which the application MUST use to negotiate the TLS // handshake. GetTlsConfigurationReq get_tls_configuration_req = 3; // Signs or decrypts the input bytes using a private key corresponding to // the local identity in the request. // // WARNING: More than one OffloadPrivateKeyOperationReq may be sent to the // S2Av2 by a server during a TLS 1.2 handshake. OffloadPrivateKeyOperationReq offload_private_key_operation_req = 4; // Encrypts or decrypts the input bytes using a resumption key corresponding // to the local identity in the request. OffloadResumptionKeyOperationReq offload_resumption_key_operation_req = 5; // Verifies the peer's certificate chain using // (a) trust bundles corresponding to the local identity in the request, and // (b) the verification mode in the request. ValidatePeerCertificateChainReq validate_peer_certificate_chain_req = 6; } } message SessionResp { // Status of the session response. // // The status field is populated so that if an error occurs when making an // individual request, then communication with the S2A may continue. If an // error is returned directly (e.g. at the gRPC layer), then it may result // that the bidirectional stream being closed. Status status = 1; oneof resp_oneof { // Contains the certificate chain and TLS configurations corresponding to // the local identity. GetTlsConfigurationResp get_tls_configuration_resp = 2; // Contains the signed or encrypted output bytes using the private key // corresponding to the local identity. OffloadPrivateKeyOperationResp offload_private_key_operation_resp = 3; // Contains the encrypted or decrypted output bytes using the resumption key // corresponding to the local identity. OffloadResumptionKeyOperationResp offload_resumption_key_operation_resp = 4; // Contains the validation result, peer identity and fingerprints of peer // certificates. ValidatePeerCertificateChainResp validate_peer_certificate_chain_resp = 5; } } service S2AService { // SetUpSession is a bidirectional stream used by applications to offload // operations from the TLS handshake. rpc SetUpSession(stream SessionReq) returns (stream SessionResp) {} } s2a-go-0.1.8/internal/proto/v2/s2a_context/000077500000000000000000000000001464711036600203575ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/s2a_context/s2a_context.proto000066400000000000000000000041561464711036600237030ustar00rootroot00000000000000// 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. syntax = "proto3"; package s2a.proto.v2; option go_package = "github.com/google/s2a/internal/proto/v2/s2a_context_go_proto"; import "internal/proto/v2/common/common.proto"; message S2AContext { reserved 5, 7, 8; // The SPIFFE ID from the peer leaf certificate, if present. // // This field is only populated if the leaf certificate is a valid SPIFFE // SVID; in particular, there is a unique URI SAN and this URI SAN is a valid // SPIFFE ID. string leaf_cert_spiffe_id = 1; // The URIs that are present in the SubjectAltName extension of the peer leaf // certificate. // // Note that the extracted URIs are not validated and may not be properly // formatted. repeated string leaf_cert_uris = 2; // The DNSNames that are present in the SubjectAltName extension of the peer // leaf certificate. repeated string leaf_cert_dnsnames = 3; // The (ordered) list of fingerprints in the certificate chain used to verify // the given leaf certificate. The order MUST be from leaf certificate // fingerprint to root certificate fingerprint. // // A fingerprint is the base-64 encoding of the SHA256 hash of the // DER-encoding of a certificate. The list MAY be populated even if the peer // certificate chain was NOT validated successfully. repeated string peer_certificate_chain_fingerprints = 4; // The local identity used during session setup. Identity local_identity = 9; // The SHA256 hash of the DER-encoding of the local leaf certificate used in // the handshake. bytes local_leaf_cert_fingerprint = 6; } s2a-go-0.1.8/internal/proto/v2/s2a_context_go_proto/000077500000000000000000000000001464711036600222675ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/s2a_context_go_proto/s2a_context.pb.go000066400000000000000000000257401464711036600254570ustar00rootroot00000000000000// 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/v2/s2a_context/s2a_context.proto package s2a_context_go_proto import ( common_go_proto "github.com/google/s2a-go/internal/proto/v2/common_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type S2AContext struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The SPIFFE ID from the peer leaf certificate, if present. // // This field is only populated if the leaf certificate is a valid SPIFFE // SVID; in particular, there is a unique URI SAN and this URI SAN is a valid // SPIFFE ID. LeafCertSpiffeId string `protobuf:"bytes,1,opt,name=leaf_cert_spiffe_id,json=leafCertSpiffeId,proto3" json:"leaf_cert_spiffe_id,omitempty"` // The URIs that are present in the SubjectAltName extension of the peer leaf // certificate. // // Note that the extracted URIs are not validated and may not be properly // formatted. LeafCertUris []string `protobuf:"bytes,2,rep,name=leaf_cert_uris,json=leafCertUris,proto3" json:"leaf_cert_uris,omitempty"` // The DNSNames that are present in the SubjectAltName extension of the peer // leaf certificate. LeafCertDnsnames []string `protobuf:"bytes,3,rep,name=leaf_cert_dnsnames,json=leafCertDnsnames,proto3" json:"leaf_cert_dnsnames,omitempty"` // The (ordered) list of fingerprints in the certificate chain used to verify // the given leaf certificate. The order MUST be from leaf certificate // fingerprint to root certificate fingerprint. // // A fingerprint is the base-64 encoding of the SHA256 hash of the // DER-encoding of a certificate. The list MAY be populated even if the peer // certificate chain was NOT validated successfully. PeerCertificateChainFingerprints []string `protobuf:"bytes,4,rep,name=peer_certificate_chain_fingerprints,json=peerCertificateChainFingerprints,proto3" json:"peer_certificate_chain_fingerprints,omitempty"` // The local identity used during session setup. LocalIdentity *common_go_proto.Identity `protobuf:"bytes,9,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` // The SHA256 hash of the DER-encoding of the local leaf certificate used in // the handshake. LocalLeafCertFingerprint []byte `protobuf:"bytes,6,opt,name=local_leaf_cert_fingerprint,json=localLeafCertFingerprint,proto3" json:"local_leaf_cert_fingerprint,omitempty"` } func (x *S2AContext) Reset() { *x = S2AContext{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_context_s2a_context_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *S2AContext) String() string { return protoimpl.X.MessageStringOf(x) } func (*S2AContext) ProtoMessage() {} func (x *S2AContext) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_context_s2a_context_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use S2AContext.ProtoReflect.Descriptor instead. func (*S2AContext) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescGZIP(), []int{0} } func (x *S2AContext) GetLeafCertSpiffeId() string { if x != nil { return x.LeafCertSpiffeId } return "" } func (x *S2AContext) GetLeafCertUris() []string { if x != nil { return x.LeafCertUris } return nil } func (x *S2AContext) GetLeafCertDnsnames() []string { if x != nil { return x.LeafCertDnsnames } return nil } func (x *S2AContext) GetPeerCertificateChainFingerprints() []string { if x != nil { return x.PeerCertificateChainFingerprints } return nil } func (x *S2AContext) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } func (x *S2AContext) GetLocalLeafCertFingerprint() []byte { if x != nil { return x.LocalLeafCertFingerprint } return nil } var File_internal_proto_v2_s2a_context_s2a_context_proto protoreflect.FileDescriptor var file_internal_proto_v2_s2a_context_s2a_context_proto_rawDesc = []byte{ 0x0a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x1a, 0x25, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xee, 0x02, 0x0a, 0x0a, 0x53, 0x32, 0x41, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x53, 0x70, 0x69, 0x66, 0x66, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x55, 0x72, 0x69, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x64, 0x6e, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x44, 0x6e, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x23, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x20, 0x70, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x3d, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x1b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescOnce sync.Once file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescData = file_internal_proto_v2_s2a_context_s2a_context_proto_rawDesc ) func file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescGZIP() []byte { file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescOnce.Do(func() { file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescData) }) return file_internal_proto_v2_s2a_context_s2a_context_proto_rawDescData } var file_internal_proto_v2_s2a_context_s2a_context_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_internal_proto_v2_s2a_context_s2a_context_proto_goTypes = []any{ (*S2AContext)(nil), // 0: s2a.proto.v2.S2AContext (*common_go_proto.Identity)(nil), // 1: s2a.proto.v2.Identity } var file_internal_proto_v2_s2a_context_s2a_context_proto_depIdxs = []int32{ 1, // 0: s2a.proto.v2.S2AContext.local_identity:type_name -> s2a.proto.v2.Identity 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_internal_proto_v2_s2a_context_s2a_context_proto_init() } func file_internal_proto_v2_s2a_context_s2a_context_proto_init() { if File_internal_proto_v2_s2a_context_s2a_context_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_v2_s2a_context_s2a_context_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*S2AContext); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_v2_s2a_context_s2a_context_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_internal_proto_v2_s2a_context_s2a_context_proto_goTypes, DependencyIndexes: file_internal_proto_v2_s2a_context_s2a_context_proto_depIdxs, MessageInfos: file_internal_proto_v2_s2a_context_s2a_context_proto_msgTypes, }.Build() File_internal_proto_v2_s2a_context_s2a_context_proto = out.File file_internal_proto_v2_s2a_context_s2a_context_proto_rawDesc = nil file_internal_proto_v2_s2a_context_s2a_context_proto_goTypes = nil file_internal_proto_v2_s2a_context_s2a_context_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/v2/s2a_go_proto/000077500000000000000000000000001464711036600205235ustar00rootroot00000000000000s2a-go-0.1.8/internal/proto/v2/s2a_go_proto/s2a.pb.go000066400000000000000000003426101464711036600221450ustar00rootroot00000000000000// 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. // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 // protoc v3.21.12 // source: internal/proto/v2/s2a/s2a.proto package s2a_go_proto import ( common_go_proto "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2a_context_go_proto "github.com/google/s2a-go/internal/proto/v2/s2a_context_go_proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) const ( // Verify that this generated code is sufficiently up-to-date. _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) // Verify that runtime/protoimpl is sufficiently up-to-date. _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) type SignatureAlgorithm int32 const ( SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED SignatureAlgorithm = 0 // RSA Public-Key Cryptography Standards #1. SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256 SignatureAlgorithm = 1 SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384 SignatureAlgorithm = 2 SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512 SignatureAlgorithm = 3 // ECDSA. SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256 SignatureAlgorithm = 4 SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384 SignatureAlgorithm = 5 SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512 SignatureAlgorithm = 6 // RSA Probabilistic Signature Scheme. SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256 SignatureAlgorithm = 7 SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384 SignatureAlgorithm = 8 SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512 SignatureAlgorithm = 9 // ED25519. SignatureAlgorithm_S2A_SSL_SIGN_ED25519 SignatureAlgorithm = 10 ) // Enum value maps for SignatureAlgorithm. var ( SignatureAlgorithm_name = map[int32]string{ 0: "S2A_SSL_SIGN_UNSPECIFIED", 1: "S2A_SSL_SIGN_RSA_PKCS1_SHA256", 2: "S2A_SSL_SIGN_RSA_PKCS1_SHA384", 3: "S2A_SSL_SIGN_RSA_PKCS1_SHA512", 4: "S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256", 5: "S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384", 6: "S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512", 7: "S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256", 8: "S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384", 9: "S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512", 10: "S2A_SSL_SIGN_ED25519", } SignatureAlgorithm_value = map[string]int32{ "S2A_SSL_SIGN_UNSPECIFIED": 0, "S2A_SSL_SIGN_RSA_PKCS1_SHA256": 1, "S2A_SSL_SIGN_RSA_PKCS1_SHA384": 2, "S2A_SSL_SIGN_RSA_PKCS1_SHA512": 3, "S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256": 4, "S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384": 5, "S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512": 6, "S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256": 7, "S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384": 8, "S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512": 9, "S2A_SSL_SIGN_ED25519": 10, } ) func (x SignatureAlgorithm) Enum() *SignatureAlgorithm { p := new(SignatureAlgorithm) *p = x return p } func (x SignatureAlgorithm) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (SignatureAlgorithm) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_s2a_s2a_proto_enumTypes[0].Descriptor() } func (SignatureAlgorithm) Type() protoreflect.EnumType { return &file_internal_proto_v2_s2a_s2a_proto_enumTypes[0] } func (x SignatureAlgorithm) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use SignatureAlgorithm.Descriptor instead. func (SignatureAlgorithm) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{0} } type GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate int32 const ( GetTlsConfigurationResp_ServerTlsConfiguration_UNSPECIFIED GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate = 0 GetTlsConfigurationResp_ServerTlsConfiguration_DONT_REQUEST_CLIENT_CERTIFICATE GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate = 1 GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate = 2 GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate = 3 GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate = 4 GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate = 5 ) // Enum value maps for GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate. var ( GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate_name = map[int32]string{ 0: "UNSPECIFIED", 1: "DONT_REQUEST_CLIENT_CERTIFICATE", 2: "REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY", 3: "REQUEST_CLIENT_CERTIFICATE_AND_VERIFY", 4: "REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY", 5: "REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY", } GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate_value = map[string]int32{ "UNSPECIFIED": 0, "DONT_REQUEST_CLIENT_CERTIFICATE": 1, "REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY": 2, "REQUEST_CLIENT_CERTIFICATE_AND_VERIFY": 3, "REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY": 4, "REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY": 5, } ) func (x GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) Enum() *GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate { p := new(GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) *p = x return p } func (x GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_s2a_s2a_proto_enumTypes[1].Descriptor() } func (GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) Type() protoreflect.EnumType { return &file_internal_proto_v2_s2a_s2a_proto_enumTypes[1] } func (x GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate.Descriptor instead. func (GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{4, 1, 0} } type OffloadPrivateKeyOperationReq_PrivateKeyOperation int32 const ( OffloadPrivateKeyOperationReq_UNSPECIFIED OffloadPrivateKeyOperationReq_PrivateKeyOperation = 0 // When performing a TLS 1.2 or 1.3 handshake, the (partial) transcript of // the TLS handshake must be signed to prove possession of the private key. // // See https://www.rfc-editor.org/rfc/rfc8446.html#section-4.4.3. OffloadPrivateKeyOperationReq_SIGN OffloadPrivateKeyOperationReq_PrivateKeyOperation = 1 // When performing a TLS 1.2 handshake using an RSA algorithm, the key // exchange algorithm involves the client generating a premaster secret, // encrypting it using the server's public key, and sending this encrypted // blob to the server in a ClientKeyExchange message. // // See https://www.rfc-editor.org/rfc/rfc4346#section-7.4.7.1. OffloadPrivateKeyOperationReq_DECRYPT OffloadPrivateKeyOperationReq_PrivateKeyOperation = 2 ) // Enum value maps for OffloadPrivateKeyOperationReq_PrivateKeyOperation. var ( OffloadPrivateKeyOperationReq_PrivateKeyOperation_name = map[int32]string{ 0: "UNSPECIFIED", 1: "SIGN", 2: "DECRYPT", } OffloadPrivateKeyOperationReq_PrivateKeyOperation_value = map[string]int32{ "UNSPECIFIED": 0, "SIGN": 1, "DECRYPT": 2, } ) func (x OffloadPrivateKeyOperationReq_PrivateKeyOperation) Enum() *OffloadPrivateKeyOperationReq_PrivateKeyOperation { p := new(OffloadPrivateKeyOperationReq_PrivateKeyOperation) *p = x return p } func (x OffloadPrivateKeyOperationReq_PrivateKeyOperation) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (OffloadPrivateKeyOperationReq_PrivateKeyOperation) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_s2a_s2a_proto_enumTypes[2].Descriptor() } func (OffloadPrivateKeyOperationReq_PrivateKeyOperation) Type() protoreflect.EnumType { return &file_internal_proto_v2_s2a_s2a_proto_enumTypes[2] } func (x OffloadPrivateKeyOperationReq_PrivateKeyOperation) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use OffloadPrivateKeyOperationReq_PrivateKeyOperation.Descriptor instead. func (OffloadPrivateKeyOperationReq_PrivateKeyOperation) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{5, 0} } type OffloadResumptionKeyOperationReq_ResumptionKeyOperation int32 const ( OffloadResumptionKeyOperationReq_UNSPECIFIED OffloadResumptionKeyOperationReq_ResumptionKeyOperation = 0 OffloadResumptionKeyOperationReq_ENCRYPT OffloadResumptionKeyOperationReq_ResumptionKeyOperation = 1 OffloadResumptionKeyOperationReq_DECRYPT OffloadResumptionKeyOperationReq_ResumptionKeyOperation = 2 ) // Enum value maps for OffloadResumptionKeyOperationReq_ResumptionKeyOperation. var ( OffloadResumptionKeyOperationReq_ResumptionKeyOperation_name = map[int32]string{ 0: "UNSPECIFIED", 1: "ENCRYPT", 2: "DECRYPT", } OffloadResumptionKeyOperationReq_ResumptionKeyOperation_value = map[string]int32{ "UNSPECIFIED": 0, "ENCRYPT": 1, "DECRYPT": 2, } ) func (x OffloadResumptionKeyOperationReq_ResumptionKeyOperation) Enum() *OffloadResumptionKeyOperationReq_ResumptionKeyOperation { p := new(OffloadResumptionKeyOperationReq_ResumptionKeyOperation) *p = x return p } func (x OffloadResumptionKeyOperationReq_ResumptionKeyOperation) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (OffloadResumptionKeyOperationReq_ResumptionKeyOperation) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_s2a_s2a_proto_enumTypes[3].Descriptor() } func (OffloadResumptionKeyOperationReq_ResumptionKeyOperation) Type() protoreflect.EnumType { return &file_internal_proto_v2_s2a_s2a_proto_enumTypes[3] } func (x OffloadResumptionKeyOperationReq_ResumptionKeyOperation) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use OffloadResumptionKeyOperationReq_ResumptionKeyOperation.Descriptor instead. func (OffloadResumptionKeyOperationReq_ResumptionKeyOperation) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{7, 0} } type ValidatePeerCertificateChainReq_VerificationMode int32 const ( // The default verification mode supported by S2A. ValidatePeerCertificateChainReq_UNSPECIFIED ValidatePeerCertificateChainReq_VerificationMode = 0 // The SPIFFE verification mode selects the set of trusted certificates to // use for path building based on the SPIFFE trust domain in the peer's leaf // certificate. ValidatePeerCertificateChainReq_SPIFFE ValidatePeerCertificateChainReq_VerificationMode = 1 // The connect-to-Google verification mode uses the trust bundle for // connecting to Google, e.g. *.mtls.googleapis.com endpoints. ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE ValidatePeerCertificateChainReq_VerificationMode = 2 // Internal use only. ValidatePeerCertificateChainReq_RESERVED_CUSTOM_VERIFICATION_MODE_3 ValidatePeerCertificateChainReq_VerificationMode = 3 // Internal use only. ValidatePeerCertificateChainReq_RESERVED_CUSTOM_VERIFICATION_MODE_4 ValidatePeerCertificateChainReq_VerificationMode = 4 // Internal use only. ValidatePeerCertificateChainReq_RESERVED_CUSTOM_VERIFICATION_MODE_5 ValidatePeerCertificateChainReq_VerificationMode = 5 ) // Enum value maps for ValidatePeerCertificateChainReq_VerificationMode. var ( ValidatePeerCertificateChainReq_VerificationMode_name = map[int32]string{ 0: "UNSPECIFIED", 1: "SPIFFE", 2: "CONNECT_TO_GOOGLE", 3: "RESERVED_CUSTOM_VERIFICATION_MODE_3", 4: "RESERVED_CUSTOM_VERIFICATION_MODE_4", 5: "RESERVED_CUSTOM_VERIFICATION_MODE_5", } ValidatePeerCertificateChainReq_VerificationMode_value = map[string]int32{ "UNSPECIFIED": 0, "SPIFFE": 1, "CONNECT_TO_GOOGLE": 2, "RESERVED_CUSTOM_VERIFICATION_MODE_3": 3, "RESERVED_CUSTOM_VERIFICATION_MODE_4": 4, "RESERVED_CUSTOM_VERIFICATION_MODE_5": 5, } ) func (x ValidatePeerCertificateChainReq_VerificationMode) Enum() *ValidatePeerCertificateChainReq_VerificationMode { p := new(ValidatePeerCertificateChainReq_VerificationMode) *p = x return p } func (x ValidatePeerCertificateChainReq_VerificationMode) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ValidatePeerCertificateChainReq_VerificationMode) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_s2a_s2a_proto_enumTypes[4].Descriptor() } func (ValidatePeerCertificateChainReq_VerificationMode) Type() protoreflect.EnumType { return &file_internal_proto_v2_s2a_s2a_proto_enumTypes[4] } func (x ValidatePeerCertificateChainReq_VerificationMode) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ValidatePeerCertificateChainReq_VerificationMode.Descriptor instead. func (ValidatePeerCertificateChainReq_VerificationMode) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{9, 0} } type ValidatePeerCertificateChainResp_ValidationResult int32 const ( ValidatePeerCertificateChainResp_UNSPECIFIED ValidatePeerCertificateChainResp_ValidationResult = 0 ValidatePeerCertificateChainResp_SUCCESS ValidatePeerCertificateChainResp_ValidationResult = 1 ValidatePeerCertificateChainResp_FAILURE ValidatePeerCertificateChainResp_ValidationResult = 2 ) // Enum value maps for ValidatePeerCertificateChainResp_ValidationResult. var ( ValidatePeerCertificateChainResp_ValidationResult_name = map[int32]string{ 0: "UNSPECIFIED", 1: "SUCCESS", 2: "FAILURE", } ValidatePeerCertificateChainResp_ValidationResult_value = map[string]int32{ "UNSPECIFIED": 0, "SUCCESS": 1, "FAILURE": 2, } ) func (x ValidatePeerCertificateChainResp_ValidationResult) Enum() *ValidatePeerCertificateChainResp_ValidationResult { p := new(ValidatePeerCertificateChainResp_ValidationResult) *p = x return p } func (x ValidatePeerCertificateChainResp_ValidationResult) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ValidatePeerCertificateChainResp_ValidationResult) Descriptor() protoreflect.EnumDescriptor { return file_internal_proto_v2_s2a_s2a_proto_enumTypes[5].Descriptor() } func (ValidatePeerCertificateChainResp_ValidationResult) Type() protoreflect.EnumType { return &file_internal_proto_v2_s2a_s2a_proto_enumTypes[5] } func (x ValidatePeerCertificateChainResp_ValidationResult) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ValidatePeerCertificateChainResp_ValidationResult.Descriptor instead. func (ValidatePeerCertificateChainResp_ValidationResult) EnumDescriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{10, 0} } type AlpnPolicy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // If true, the application MUST perform ALPN negotiation. EnableAlpnNegotiation bool `protobuf:"varint,1,opt,name=enable_alpn_negotiation,json=enableAlpnNegotiation,proto3" json:"enable_alpn_negotiation,omitempty"` // The ordered list of ALPN protocols that specify how the application SHOULD // negotiate ALPN during the TLS handshake. // // The application MAY ignore any ALPN protocols in this list that are not // supported by the application. AlpnProtocols []common_go_proto.AlpnProtocol `protobuf:"varint,2,rep,packed,name=alpn_protocols,json=alpnProtocols,proto3,enum=s2a.proto.v2.AlpnProtocol" json:"alpn_protocols,omitempty"` } func (x *AlpnPolicy) Reset() { *x = AlpnPolicy{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AlpnPolicy) String() string { return protoimpl.X.MessageStringOf(x) } func (*AlpnPolicy) ProtoMessage() {} func (x *AlpnPolicy) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AlpnPolicy.ProtoReflect.Descriptor instead. func (*AlpnPolicy) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{0} } func (x *AlpnPolicy) GetEnableAlpnNegotiation() bool { if x != nil { return x.EnableAlpnNegotiation } return false } func (x *AlpnPolicy) GetAlpnProtocols() []common_go_proto.AlpnProtocol { if x != nil { return x.AlpnProtocols } return nil } type AuthenticationMechanism struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Applications may specify an identity associated to an authentication // mechanism. Otherwise, S2A assumes that the authentication mechanism is // associated with the default identity. If the default identity cannot be // determined, the request is rejected. Identity *common_go_proto.Identity `protobuf:"bytes,3,opt,name=identity,proto3" json:"identity,omitempty"` // Types that are assignable to MechanismOneof: // // *AuthenticationMechanism_Token MechanismOneof isAuthenticationMechanism_MechanismOneof `protobuf_oneof:"mechanism_oneof"` } func (x *AuthenticationMechanism) Reset() { *x = AuthenticationMechanism{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *AuthenticationMechanism) String() string { return protoimpl.X.MessageStringOf(x) } func (*AuthenticationMechanism) ProtoMessage() {} func (x *AuthenticationMechanism) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use AuthenticationMechanism.ProtoReflect.Descriptor instead. func (*AuthenticationMechanism) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{1} } func (x *AuthenticationMechanism) GetIdentity() *common_go_proto.Identity { if x != nil { return x.Identity } return nil } func (m *AuthenticationMechanism) GetMechanismOneof() isAuthenticationMechanism_MechanismOneof { if m != nil { return m.MechanismOneof } return nil } func (x *AuthenticationMechanism) GetToken() string { if x, ok := x.GetMechanismOneof().(*AuthenticationMechanism_Token); ok { return x.Token } return "" } type isAuthenticationMechanism_MechanismOneof interface { isAuthenticationMechanism_MechanismOneof() } type AuthenticationMechanism_Token struct { // A token that the application uses to authenticate itself to S2A. Token string `protobuf:"bytes,2,opt,name=token,proto3,oneof"` } func (*AuthenticationMechanism_Token) isAuthenticationMechanism_MechanismOneof() {} type Status struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The status code that is specific to the application and the implementation // of S2A, e.g., gRPC status code. Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // The status details. Details string `protobuf:"bytes,2,opt,name=details,proto3" json:"details,omitempty"` } func (x *Status) Reset() { *x = Status{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Status) String() string { return protoimpl.X.MessageStringOf(x) } func (*Status) ProtoMessage() {} func (x *Status) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Status.ProtoReflect.Descriptor instead. func (*Status) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{2} } func (x *Status) GetCode() uint32 { if x != nil { return x.Code } return 0 } func (x *Status) GetDetails() string { if x != nil { return x.Details } return "" } type GetTlsConfigurationReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The role of the application in the TLS connection. ConnectionSide common_go_proto.ConnectionSide `protobuf:"varint,1,opt,name=connection_side,json=connectionSide,proto3,enum=s2a.proto.v2.ConnectionSide" json:"connection_side,omitempty"` // The server name indication (SNI) extension, which MAY be populated when a // server is offloading to S2A. The SNI is used to determine the server // identity if the local identity in the request is empty. Sni string `protobuf:"bytes,2,opt,name=sni,proto3" json:"sni,omitempty"` } func (x *GetTlsConfigurationReq) Reset() { *x = GetTlsConfigurationReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetTlsConfigurationReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetTlsConfigurationReq) ProtoMessage() {} func (x *GetTlsConfigurationReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use GetTlsConfigurationReq.ProtoReflect.Descriptor instead. func (*GetTlsConfigurationReq) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{3} } func (x *GetTlsConfigurationReq) GetConnectionSide() common_go_proto.ConnectionSide { if x != nil { return x.ConnectionSide } return common_go_proto.ConnectionSide(0) } func (x *GetTlsConfigurationReq) GetSni() string { if x != nil { return x.Sni } return "" } type GetTlsConfigurationResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to TlsConfiguration: // // *GetTlsConfigurationResp_ClientTlsConfiguration_ // *GetTlsConfigurationResp_ServerTlsConfiguration_ TlsConfiguration isGetTlsConfigurationResp_TlsConfiguration `protobuf_oneof:"tls_configuration"` } func (x *GetTlsConfigurationResp) Reset() { *x = GetTlsConfigurationResp{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetTlsConfigurationResp) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetTlsConfigurationResp) ProtoMessage() {} func (x *GetTlsConfigurationResp) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use GetTlsConfigurationResp.ProtoReflect.Descriptor instead. func (*GetTlsConfigurationResp) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{4} } func (m *GetTlsConfigurationResp) GetTlsConfiguration() isGetTlsConfigurationResp_TlsConfiguration { if m != nil { return m.TlsConfiguration } return nil } func (x *GetTlsConfigurationResp) GetClientTlsConfiguration() *GetTlsConfigurationResp_ClientTlsConfiguration { if x, ok := x.GetTlsConfiguration().(*GetTlsConfigurationResp_ClientTlsConfiguration_); ok { return x.ClientTlsConfiguration } return nil } func (x *GetTlsConfigurationResp) GetServerTlsConfiguration() *GetTlsConfigurationResp_ServerTlsConfiguration { if x, ok := x.GetTlsConfiguration().(*GetTlsConfigurationResp_ServerTlsConfiguration_); ok { return x.ServerTlsConfiguration } return nil } type isGetTlsConfigurationResp_TlsConfiguration interface { isGetTlsConfigurationResp_TlsConfiguration() } type GetTlsConfigurationResp_ClientTlsConfiguration_ struct { ClientTlsConfiguration *GetTlsConfigurationResp_ClientTlsConfiguration `protobuf:"bytes,1,opt,name=client_tls_configuration,json=clientTlsConfiguration,proto3,oneof"` } type GetTlsConfigurationResp_ServerTlsConfiguration_ struct { ServerTlsConfiguration *GetTlsConfigurationResp_ServerTlsConfiguration `protobuf:"bytes,2,opt,name=server_tls_configuration,json=serverTlsConfiguration,proto3,oneof"` } func (*GetTlsConfigurationResp_ClientTlsConfiguration_) isGetTlsConfigurationResp_TlsConfiguration() { } func (*GetTlsConfigurationResp_ServerTlsConfiguration_) isGetTlsConfigurationResp_TlsConfiguration() { } type OffloadPrivateKeyOperationReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The operation the private key is used for. Operation OffloadPrivateKeyOperationReq_PrivateKeyOperation `protobuf:"varint,1,opt,name=operation,proto3,enum=s2a.proto.v2.OffloadPrivateKeyOperationReq_PrivateKeyOperation" json:"operation,omitempty"` // The signature algorithm to be used for signing operations. SignatureAlgorithm SignatureAlgorithm `protobuf:"varint,2,opt,name=signature_algorithm,json=signatureAlgorithm,proto3,enum=s2a.proto.v2.SignatureAlgorithm" json:"signature_algorithm,omitempty"` // The input bytes to be signed or decrypted. // // Types that are assignable to InBytes: // // *OffloadPrivateKeyOperationReq_RawBytes // *OffloadPrivateKeyOperationReq_Sha256Digest // *OffloadPrivateKeyOperationReq_Sha384Digest // *OffloadPrivateKeyOperationReq_Sha512Digest InBytes isOffloadPrivateKeyOperationReq_InBytes `protobuf_oneof:"in_bytes"` } func (x *OffloadPrivateKeyOperationReq) Reset() { *x = OffloadPrivateKeyOperationReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OffloadPrivateKeyOperationReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*OffloadPrivateKeyOperationReq) ProtoMessage() {} func (x *OffloadPrivateKeyOperationReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use OffloadPrivateKeyOperationReq.ProtoReflect.Descriptor instead. func (*OffloadPrivateKeyOperationReq) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{5} } func (x *OffloadPrivateKeyOperationReq) GetOperation() OffloadPrivateKeyOperationReq_PrivateKeyOperation { if x != nil { return x.Operation } return OffloadPrivateKeyOperationReq_UNSPECIFIED } func (x *OffloadPrivateKeyOperationReq) GetSignatureAlgorithm() SignatureAlgorithm { if x != nil { return x.SignatureAlgorithm } return SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED } func (m *OffloadPrivateKeyOperationReq) GetInBytes() isOffloadPrivateKeyOperationReq_InBytes { if m != nil { return m.InBytes } return nil } func (x *OffloadPrivateKeyOperationReq) GetRawBytes() []byte { if x, ok := x.GetInBytes().(*OffloadPrivateKeyOperationReq_RawBytes); ok { return x.RawBytes } return nil } func (x *OffloadPrivateKeyOperationReq) GetSha256Digest() []byte { if x, ok := x.GetInBytes().(*OffloadPrivateKeyOperationReq_Sha256Digest); ok { return x.Sha256Digest } return nil } func (x *OffloadPrivateKeyOperationReq) GetSha384Digest() []byte { if x, ok := x.GetInBytes().(*OffloadPrivateKeyOperationReq_Sha384Digest); ok { return x.Sha384Digest } return nil } func (x *OffloadPrivateKeyOperationReq) GetSha512Digest() []byte { if x, ok := x.GetInBytes().(*OffloadPrivateKeyOperationReq_Sha512Digest); ok { return x.Sha512Digest } return nil } type isOffloadPrivateKeyOperationReq_InBytes interface { isOffloadPrivateKeyOperationReq_InBytes() } type OffloadPrivateKeyOperationReq_RawBytes struct { // Raw bytes to be hashed and signed, or decrypted. RawBytes []byte `protobuf:"bytes,4,opt,name=raw_bytes,json=rawBytes,proto3,oneof"` } type OffloadPrivateKeyOperationReq_Sha256Digest struct { // A SHA256 hash to be signed. Must be 32 bytes. Sha256Digest []byte `protobuf:"bytes,5,opt,name=sha256_digest,json=sha256Digest,proto3,oneof"` } type OffloadPrivateKeyOperationReq_Sha384Digest struct { // A SHA384 hash to be signed. Must be 48 bytes. Sha384Digest []byte `protobuf:"bytes,6,opt,name=sha384_digest,json=sha384Digest,proto3,oneof"` } type OffloadPrivateKeyOperationReq_Sha512Digest struct { // A SHA512 hash to be signed. Must be 64 bytes. Sha512Digest []byte `protobuf:"bytes,7,opt,name=sha512_digest,json=sha512Digest,proto3,oneof"` } func (*OffloadPrivateKeyOperationReq_RawBytes) isOffloadPrivateKeyOperationReq_InBytes() {} func (*OffloadPrivateKeyOperationReq_Sha256Digest) isOffloadPrivateKeyOperationReq_InBytes() {} func (*OffloadPrivateKeyOperationReq_Sha384Digest) isOffloadPrivateKeyOperationReq_InBytes() {} func (*OffloadPrivateKeyOperationReq_Sha512Digest) isOffloadPrivateKeyOperationReq_InBytes() {} type OffloadPrivateKeyOperationResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The signed or decrypted output bytes. OutBytes []byte `protobuf:"bytes,1,opt,name=out_bytes,json=outBytes,proto3" json:"out_bytes,omitempty"` } func (x *OffloadPrivateKeyOperationResp) Reset() { *x = OffloadPrivateKeyOperationResp{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OffloadPrivateKeyOperationResp) String() string { return protoimpl.X.MessageStringOf(x) } func (*OffloadPrivateKeyOperationResp) ProtoMessage() {} func (x *OffloadPrivateKeyOperationResp) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use OffloadPrivateKeyOperationResp.ProtoReflect.Descriptor instead. func (*OffloadPrivateKeyOperationResp) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{6} } func (x *OffloadPrivateKeyOperationResp) GetOutBytes() []byte { if x != nil { return x.OutBytes } return nil } type OffloadResumptionKeyOperationReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The operation the resumption key is used for. Operation OffloadResumptionKeyOperationReq_ResumptionKeyOperation `protobuf:"varint,1,opt,name=operation,proto3,enum=s2a.proto.v2.OffloadResumptionKeyOperationReq_ResumptionKeyOperation" json:"operation,omitempty"` // The bytes to be encrypted or decrypted. InBytes []byte `protobuf:"bytes,2,opt,name=in_bytes,json=inBytes,proto3" json:"in_bytes,omitempty"` } func (x *OffloadResumptionKeyOperationReq) Reset() { *x = OffloadResumptionKeyOperationReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OffloadResumptionKeyOperationReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*OffloadResumptionKeyOperationReq) ProtoMessage() {} func (x *OffloadResumptionKeyOperationReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use OffloadResumptionKeyOperationReq.ProtoReflect.Descriptor instead. func (*OffloadResumptionKeyOperationReq) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{7} } func (x *OffloadResumptionKeyOperationReq) GetOperation() OffloadResumptionKeyOperationReq_ResumptionKeyOperation { if x != nil { return x.Operation } return OffloadResumptionKeyOperationReq_UNSPECIFIED } func (x *OffloadResumptionKeyOperationReq) GetInBytes() []byte { if x != nil { return x.InBytes } return nil } type OffloadResumptionKeyOperationResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The encrypted or decrypted bytes. OutBytes []byte `protobuf:"bytes,1,opt,name=out_bytes,json=outBytes,proto3" json:"out_bytes,omitempty"` } func (x *OffloadResumptionKeyOperationResp) Reset() { *x = OffloadResumptionKeyOperationResp{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OffloadResumptionKeyOperationResp) String() string { return protoimpl.X.MessageStringOf(x) } func (*OffloadResumptionKeyOperationResp) ProtoMessage() {} func (x *OffloadResumptionKeyOperationResp) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use OffloadResumptionKeyOperationResp.ProtoReflect.Descriptor instead. func (*OffloadResumptionKeyOperationResp) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{8} } func (x *OffloadResumptionKeyOperationResp) GetOutBytes() []byte { if x != nil { return x.OutBytes } return nil } type ValidatePeerCertificateChainReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The verification mode that S2A MUST use to validate the peer certificate // chain. Mode ValidatePeerCertificateChainReq_VerificationMode `protobuf:"varint,1,opt,name=mode,proto3,enum=s2a.proto.v2.ValidatePeerCertificateChainReq_VerificationMode" json:"mode,omitempty"` // Types that are assignable to PeerOneof: // // *ValidatePeerCertificateChainReq_ClientPeer_ // *ValidatePeerCertificateChainReq_ServerPeer_ PeerOneof isValidatePeerCertificateChainReq_PeerOneof `protobuf_oneof:"peer_oneof"` } func (x *ValidatePeerCertificateChainReq) Reset() { *x = ValidatePeerCertificateChainReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ValidatePeerCertificateChainReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*ValidatePeerCertificateChainReq) ProtoMessage() {} func (x *ValidatePeerCertificateChainReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ValidatePeerCertificateChainReq.ProtoReflect.Descriptor instead. func (*ValidatePeerCertificateChainReq) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{9} } func (x *ValidatePeerCertificateChainReq) GetMode() ValidatePeerCertificateChainReq_VerificationMode { if x != nil { return x.Mode } return ValidatePeerCertificateChainReq_UNSPECIFIED } func (m *ValidatePeerCertificateChainReq) GetPeerOneof() isValidatePeerCertificateChainReq_PeerOneof { if m != nil { return m.PeerOneof } return nil } func (x *ValidatePeerCertificateChainReq) GetClientPeer() *ValidatePeerCertificateChainReq_ClientPeer { if x, ok := x.GetPeerOneof().(*ValidatePeerCertificateChainReq_ClientPeer_); ok { return x.ClientPeer } return nil } func (x *ValidatePeerCertificateChainReq) GetServerPeer() *ValidatePeerCertificateChainReq_ServerPeer { if x, ok := x.GetPeerOneof().(*ValidatePeerCertificateChainReq_ServerPeer_); ok { return x.ServerPeer } return nil } type isValidatePeerCertificateChainReq_PeerOneof interface { isValidatePeerCertificateChainReq_PeerOneof() } type ValidatePeerCertificateChainReq_ClientPeer_ struct { ClientPeer *ValidatePeerCertificateChainReq_ClientPeer `protobuf:"bytes,2,opt,name=client_peer,json=clientPeer,proto3,oneof"` } type ValidatePeerCertificateChainReq_ServerPeer_ struct { ServerPeer *ValidatePeerCertificateChainReq_ServerPeer `protobuf:"bytes,3,opt,name=server_peer,json=serverPeer,proto3,oneof"` } func (*ValidatePeerCertificateChainReq_ClientPeer_) isValidatePeerCertificateChainReq_PeerOneof() {} func (*ValidatePeerCertificateChainReq_ServerPeer_) isValidatePeerCertificateChainReq_PeerOneof() {} type ValidatePeerCertificateChainResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The result of validating the peer certificate chain. ValidationResult ValidatePeerCertificateChainResp_ValidationResult `protobuf:"varint,1,opt,name=validation_result,json=validationResult,proto3,enum=s2a.proto.v2.ValidatePeerCertificateChainResp_ValidationResult" json:"validation_result,omitempty"` // The validation details. This field is only populated when the validation // result is NOT SUCCESS. ValidationDetails string `protobuf:"bytes,2,opt,name=validation_details,json=validationDetails,proto3" json:"validation_details,omitempty"` // The S2A context contains information from the peer certificate chain. // // The S2A context MAY be populated even if validation of the peer certificate // chain fails. Context *s2a_context_go_proto.S2AContext `protobuf:"bytes,3,opt,name=context,proto3" json:"context,omitempty"` } func (x *ValidatePeerCertificateChainResp) Reset() { *x = ValidatePeerCertificateChainResp{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ValidatePeerCertificateChainResp) String() string { return protoimpl.X.MessageStringOf(x) } func (*ValidatePeerCertificateChainResp) ProtoMessage() {} func (x *ValidatePeerCertificateChainResp) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ValidatePeerCertificateChainResp.ProtoReflect.Descriptor instead. func (*ValidatePeerCertificateChainResp) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{10} } func (x *ValidatePeerCertificateChainResp) GetValidationResult() ValidatePeerCertificateChainResp_ValidationResult { if x != nil { return x.ValidationResult } return ValidatePeerCertificateChainResp_UNSPECIFIED } func (x *ValidatePeerCertificateChainResp) GetValidationDetails() string { if x != nil { return x.ValidationDetails } return "" } func (x *ValidatePeerCertificateChainResp) GetContext() *s2a_context_go_proto.S2AContext { if x != nil { return x.Context } return nil } type SessionReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The identity corresponding to the TLS configurations that MUST be used for // the TLS handshake. // // If a managed identity already exists, the local identity and authentication // mechanisms are ignored. If a managed identity doesn't exist and the local // identity is not populated, S2A will try to deduce the managed identity to // use from the SNI extension. If that also fails, S2A uses the default // identity (if one exists). LocalIdentity *common_go_proto.Identity `protobuf:"bytes,7,opt,name=local_identity,json=localIdentity,proto3" json:"local_identity,omitempty"` // The authentication mechanisms that the application wishes to use to // authenticate to S2A, ordered by preference. S2A will always use the first // authentication mechanism that matches the managed identity. AuthenticationMechanisms []*AuthenticationMechanism `protobuf:"bytes,2,rep,name=authentication_mechanisms,json=authenticationMechanisms,proto3" json:"authentication_mechanisms,omitempty"` // Types that are assignable to ReqOneof: // // *SessionReq_GetTlsConfigurationReq // *SessionReq_OffloadPrivateKeyOperationReq // *SessionReq_OffloadResumptionKeyOperationReq // *SessionReq_ValidatePeerCertificateChainReq ReqOneof isSessionReq_ReqOneof `protobuf_oneof:"req_oneof"` } func (x *SessionReq) Reset() { *x = SessionReq{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionReq) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionReq) ProtoMessage() {} func (x *SessionReq) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionReq.ProtoReflect.Descriptor instead. func (*SessionReq) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{11} } func (x *SessionReq) GetLocalIdentity() *common_go_proto.Identity { if x != nil { return x.LocalIdentity } return nil } func (x *SessionReq) GetAuthenticationMechanisms() []*AuthenticationMechanism { if x != nil { return x.AuthenticationMechanisms } return nil } func (m *SessionReq) GetReqOneof() isSessionReq_ReqOneof { if m != nil { return m.ReqOneof } return nil } func (x *SessionReq) GetGetTlsConfigurationReq() *GetTlsConfigurationReq { if x, ok := x.GetReqOneof().(*SessionReq_GetTlsConfigurationReq); ok { return x.GetTlsConfigurationReq } return nil } func (x *SessionReq) GetOffloadPrivateKeyOperationReq() *OffloadPrivateKeyOperationReq { if x, ok := x.GetReqOneof().(*SessionReq_OffloadPrivateKeyOperationReq); ok { return x.OffloadPrivateKeyOperationReq } return nil } func (x *SessionReq) GetOffloadResumptionKeyOperationReq() *OffloadResumptionKeyOperationReq { if x, ok := x.GetReqOneof().(*SessionReq_OffloadResumptionKeyOperationReq); ok { return x.OffloadResumptionKeyOperationReq } return nil } func (x *SessionReq) GetValidatePeerCertificateChainReq() *ValidatePeerCertificateChainReq { if x, ok := x.GetReqOneof().(*SessionReq_ValidatePeerCertificateChainReq); ok { return x.ValidatePeerCertificateChainReq } return nil } type isSessionReq_ReqOneof interface { isSessionReq_ReqOneof() } type SessionReq_GetTlsConfigurationReq struct { // Requests the certificate chain and TLS configuration corresponding to the // local identity, which the application MUST use to negotiate the TLS // handshake. GetTlsConfigurationReq *GetTlsConfigurationReq `protobuf:"bytes,3,opt,name=get_tls_configuration_req,json=getTlsConfigurationReq,proto3,oneof"` } type SessionReq_OffloadPrivateKeyOperationReq struct { // Signs or decrypts the input bytes using a private key corresponding to // the local identity in the request. // // WARNING: More than one OffloadPrivateKeyOperationReq may be sent to the // S2Av2 by a server during a TLS 1.2 handshake. OffloadPrivateKeyOperationReq *OffloadPrivateKeyOperationReq `protobuf:"bytes,4,opt,name=offload_private_key_operation_req,json=offloadPrivateKeyOperationReq,proto3,oneof"` } type SessionReq_OffloadResumptionKeyOperationReq struct { // Encrypts or decrypts the input bytes using a resumption key corresponding // to the local identity in the request. OffloadResumptionKeyOperationReq *OffloadResumptionKeyOperationReq `protobuf:"bytes,5,opt,name=offload_resumption_key_operation_req,json=offloadResumptionKeyOperationReq,proto3,oneof"` } type SessionReq_ValidatePeerCertificateChainReq struct { // Verifies the peer's certificate chain using // (a) trust bundles corresponding to the local identity in the request, and // (b) the verification mode in the request. ValidatePeerCertificateChainReq *ValidatePeerCertificateChainReq `protobuf:"bytes,6,opt,name=validate_peer_certificate_chain_req,json=validatePeerCertificateChainReq,proto3,oneof"` } func (*SessionReq_GetTlsConfigurationReq) isSessionReq_ReqOneof() {} func (*SessionReq_OffloadPrivateKeyOperationReq) isSessionReq_ReqOneof() {} func (*SessionReq_OffloadResumptionKeyOperationReq) isSessionReq_ReqOneof() {} func (*SessionReq_ValidatePeerCertificateChainReq) isSessionReq_ReqOneof() {} type SessionResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Status of the session response. // // The status field is populated so that if an error occurs when making an // individual request, then communication with the S2A may continue. If an // error is returned directly (e.g. at the gRPC layer), then it may result // that the bidirectional stream being closed. Status *Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` // Types that are assignable to RespOneof: // // *SessionResp_GetTlsConfigurationResp // *SessionResp_OffloadPrivateKeyOperationResp // *SessionResp_OffloadResumptionKeyOperationResp // *SessionResp_ValidatePeerCertificateChainResp RespOneof isSessionResp_RespOneof `protobuf_oneof:"resp_oneof"` } func (x *SessionResp) Reset() { *x = SessionResp{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SessionResp) String() string { return protoimpl.X.MessageStringOf(x) } func (*SessionResp) ProtoMessage() {} func (x *SessionResp) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use SessionResp.ProtoReflect.Descriptor instead. func (*SessionResp) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{12} } func (x *SessionResp) GetStatus() *Status { if x != nil { return x.Status } return nil } func (m *SessionResp) GetRespOneof() isSessionResp_RespOneof { if m != nil { return m.RespOneof } return nil } func (x *SessionResp) GetGetTlsConfigurationResp() *GetTlsConfigurationResp { if x, ok := x.GetRespOneof().(*SessionResp_GetTlsConfigurationResp); ok { return x.GetTlsConfigurationResp } return nil } func (x *SessionResp) GetOffloadPrivateKeyOperationResp() *OffloadPrivateKeyOperationResp { if x, ok := x.GetRespOneof().(*SessionResp_OffloadPrivateKeyOperationResp); ok { return x.OffloadPrivateKeyOperationResp } return nil } func (x *SessionResp) GetOffloadResumptionKeyOperationResp() *OffloadResumptionKeyOperationResp { if x, ok := x.GetRespOneof().(*SessionResp_OffloadResumptionKeyOperationResp); ok { return x.OffloadResumptionKeyOperationResp } return nil } func (x *SessionResp) GetValidatePeerCertificateChainResp() *ValidatePeerCertificateChainResp { if x, ok := x.GetRespOneof().(*SessionResp_ValidatePeerCertificateChainResp); ok { return x.ValidatePeerCertificateChainResp } return nil } type isSessionResp_RespOneof interface { isSessionResp_RespOneof() } type SessionResp_GetTlsConfigurationResp struct { // Contains the certificate chain and TLS configurations corresponding to // the local identity. GetTlsConfigurationResp *GetTlsConfigurationResp `protobuf:"bytes,2,opt,name=get_tls_configuration_resp,json=getTlsConfigurationResp,proto3,oneof"` } type SessionResp_OffloadPrivateKeyOperationResp struct { // Contains the signed or encrypted output bytes using the private key // corresponding to the local identity. OffloadPrivateKeyOperationResp *OffloadPrivateKeyOperationResp `protobuf:"bytes,3,opt,name=offload_private_key_operation_resp,json=offloadPrivateKeyOperationResp,proto3,oneof"` } type SessionResp_OffloadResumptionKeyOperationResp struct { // Contains the encrypted or decrypted output bytes using the resumption key // corresponding to the local identity. OffloadResumptionKeyOperationResp *OffloadResumptionKeyOperationResp `protobuf:"bytes,4,opt,name=offload_resumption_key_operation_resp,json=offloadResumptionKeyOperationResp,proto3,oneof"` } type SessionResp_ValidatePeerCertificateChainResp struct { // Contains the validation result, peer identity and fingerprints of peer // certificates. ValidatePeerCertificateChainResp *ValidatePeerCertificateChainResp `protobuf:"bytes,5,opt,name=validate_peer_certificate_chain_resp,json=validatePeerCertificateChainResp,proto3,oneof"` } func (*SessionResp_GetTlsConfigurationResp) isSessionResp_RespOneof() {} func (*SessionResp_OffloadPrivateKeyOperationResp) isSessionResp_RespOneof() {} func (*SessionResp_OffloadResumptionKeyOperationResp) isSessionResp_RespOneof() {} func (*SessionResp_ValidatePeerCertificateChainResp) isSessionResp_RespOneof() {} // Next ID: 8 type GetTlsConfigurationResp_ClientTlsConfiguration struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The certificate chain that the client MUST use for the TLS handshake. // It's a list of PEM-encoded certificates, ordered from leaf to root, // excluding the root. CertificateChain []string `protobuf:"bytes,1,rep,name=certificate_chain,json=certificateChain,proto3" json:"certificate_chain,omitempty"` // The minimum TLS version number that the client MUST use for the TLS // handshake. If this field is not provided, the client MUST use the default // minimum version of the client's TLS library. MinTlsVersion common_go_proto.TLSVersion `protobuf:"varint,2,opt,name=min_tls_version,json=minTlsVersion,proto3,enum=s2a.proto.v2.TLSVersion" json:"min_tls_version,omitempty"` // The maximum TLS version number that the client MUST use for the TLS // handshake. If this field is not provided, the client MUST use the default // maximum version of the client's TLS library. MaxTlsVersion common_go_proto.TLSVersion `protobuf:"varint,3,opt,name=max_tls_version,json=maxTlsVersion,proto3,enum=s2a.proto.v2.TLSVersion" json:"max_tls_version,omitempty"` // The ordered list of TLS 1.0-1.2 ciphersuites that the client MAY offer to // negotiate in the TLS handshake. Ciphersuites []common_go_proto.Ciphersuite `protobuf:"varint,6,rep,packed,name=ciphersuites,proto3,enum=s2a.proto.v2.Ciphersuite" json:"ciphersuites,omitempty"` // The policy that dictates how the client negotiates ALPN during the TLS // handshake. AlpnPolicy *AlpnPolicy `protobuf:"bytes,7,opt,name=alpn_policy,json=alpnPolicy,proto3" json:"alpn_policy,omitempty"` } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) Reset() { *x = GetTlsConfigurationResp_ClientTlsConfiguration{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetTlsConfigurationResp_ClientTlsConfiguration) ProtoMessage() {} func (x *GetTlsConfigurationResp_ClientTlsConfiguration) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use GetTlsConfigurationResp_ClientTlsConfiguration.ProtoReflect.Descriptor instead. func (*GetTlsConfigurationResp_ClientTlsConfiguration) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{4, 0} } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) GetCertificateChain() []string { if x != nil { return x.CertificateChain } return nil } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) GetMinTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MinTlsVersion } return common_go_proto.TLSVersion(0) } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) GetMaxTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MaxTlsVersion } return common_go_proto.TLSVersion(0) } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) GetCiphersuites() []common_go_proto.Ciphersuite { if x != nil { return x.Ciphersuites } return nil } func (x *GetTlsConfigurationResp_ClientTlsConfiguration) GetAlpnPolicy() *AlpnPolicy { if x != nil { return x.AlpnPolicy } return nil } // Next ID: 12 type GetTlsConfigurationResp_ServerTlsConfiguration struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The certificate chain that the server MUST use for the TLS handshake. // It's a list of PEM-encoded certificates, ordered from leaf to root, // excluding the root. CertificateChain []string `protobuf:"bytes,1,rep,name=certificate_chain,json=certificateChain,proto3" json:"certificate_chain,omitempty"` // The minimum TLS version number that the server MUST use for the TLS // handshake. If this field is not provided, the server MUST use the default // minimum version of the server's TLS library. MinTlsVersion common_go_proto.TLSVersion `protobuf:"varint,2,opt,name=min_tls_version,json=minTlsVersion,proto3,enum=s2a.proto.v2.TLSVersion" json:"min_tls_version,omitempty"` // The maximum TLS version number that the server MUST use for the TLS // handshake. If this field is not provided, the server MUST use the default // maximum version of the server's TLS library. MaxTlsVersion common_go_proto.TLSVersion `protobuf:"varint,3,opt,name=max_tls_version,json=maxTlsVersion,proto3,enum=s2a.proto.v2.TLSVersion" json:"max_tls_version,omitempty"` // The ordered list of TLS 1.0-1.2 ciphersuites that the server MAY offer to // negotiate in the TLS handshake. Ciphersuites []common_go_proto.Ciphersuite `protobuf:"varint,10,rep,packed,name=ciphersuites,proto3,enum=s2a.proto.v2.Ciphersuite" json:"ciphersuites,omitempty"` // Whether to enable TLS resumption. TlsResumptionEnabled bool `protobuf:"varint,6,opt,name=tls_resumption_enabled,json=tlsResumptionEnabled,proto3" json:"tls_resumption_enabled,omitempty"` // Whether the server MUST request a client certificate (i.e. to negotiate // TLS vs. mTLS). RequestClientCertificate GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate `protobuf:"varint,7,opt,name=request_client_certificate,json=requestClientCertificate,proto3,enum=s2a.proto.v2.GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate" json:"request_client_certificate,omitempty"` // Returns the maximum number of extra bytes that // |OffloadResumptionKeyOperation| can add to the number of unencrypted // bytes to form the encrypted bytes. MaxOverheadOfTicketAead uint32 `protobuf:"varint,9,opt,name=max_overhead_of_ticket_aead,json=maxOverheadOfTicketAead,proto3" json:"max_overhead_of_ticket_aead,omitempty"` // The policy that dictates how the server negotiates ALPN during the TLS // handshake. AlpnPolicy *AlpnPolicy `protobuf:"bytes,11,opt,name=alpn_policy,json=alpnPolicy,proto3" json:"alpn_policy,omitempty"` } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) Reset() { *x = GetTlsConfigurationResp_ServerTlsConfiguration{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) String() string { return protoimpl.X.MessageStringOf(x) } func (*GetTlsConfigurationResp_ServerTlsConfiguration) ProtoMessage() {} func (x *GetTlsConfigurationResp_ServerTlsConfiguration) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use GetTlsConfigurationResp_ServerTlsConfiguration.ProtoReflect.Descriptor instead. func (*GetTlsConfigurationResp_ServerTlsConfiguration) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{4, 1} } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetCertificateChain() []string { if x != nil { return x.CertificateChain } return nil } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetMinTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MinTlsVersion } return common_go_proto.TLSVersion(0) } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetMaxTlsVersion() common_go_proto.TLSVersion { if x != nil { return x.MaxTlsVersion } return common_go_proto.TLSVersion(0) } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetCiphersuites() []common_go_proto.Ciphersuite { if x != nil { return x.Ciphersuites } return nil } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetTlsResumptionEnabled() bool { if x != nil { return x.TlsResumptionEnabled } return false } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetRequestClientCertificate() GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate { if x != nil { return x.RequestClientCertificate } return GetTlsConfigurationResp_ServerTlsConfiguration_UNSPECIFIED } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetMaxOverheadOfTicketAead() uint32 { if x != nil { return x.MaxOverheadOfTicketAead } return 0 } func (x *GetTlsConfigurationResp_ServerTlsConfiguration) GetAlpnPolicy() *AlpnPolicy { if x != nil { return x.AlpnPolicy } return nil } type ValidatePeerCertificateChainReq_ClientPeer struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The certificate chain to be verified. The chain MUST be a list of // DER-encoded certificates, ordered from leaf to root, excluding the root. CertificateChain [][]byte `protobuf:"bytes,1,rep,name=certificate_chain,json=certificateChain,proto3" json:"certificate_chain,omitempty"` } func (x *ValidatePeerCertificateChainReq_ClientPeer) Reset() { *x = ValidatePeerCertificateChainReq_ClientPeer{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ValidatePeerCertificateChainReq_ClientPeer) String() string { return protoimpl.X.MessageStringOf(x) } func (*ValidatePeerCertificateChainReq_ClientPeer) ProtoMessage() {} func (x *ValidatePeerCertificateChainReq_ClientPeer) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ValidatePeerCertificateChainReq_ClientPeer.ProtoReflect.Descriptor instead. func (*ValidatePeerCertificateChainReq_ClientPeer) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{9, 0} } func (x *ValidatePeerCertificateChainReq_ClientPeer) GetCertificateChain() [][]byte { if x != nil { return x.CertificateChain } return nil } type ValidatePeerCertificateChainReq_ServerPeer struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The certificate chain to be verified. The chain MUST be a list of // DER-encoded certificates, ordered from leaf to root, excluding the root. CertificateChain [][]byte `protobuf:"bytes,1,rep,name=certificate_chain,json=certificateChain,proto3" json:"certificate_chain,omitempty"` // The expected hostname of the server. ServerHostname string `protobuf:"bytes,2,opt,name=server_hostname,json=serverHostname,proto3" json:"server_hostname,omitempty"` // The UnrestrictedClientPolicy specified by the user. SerializedUnrestrictedClientPolicy []byte `protobuf:"bytes,3,opt,name=serialized_unrestricted_client_policy,json=serializedUnrestrictedClientPolicy,proto3" json:"serialized_unrestricted_client_policy,omitempty"` } func (x *ValidatePeerCertificateChainReq_ServerPeer) Reset() { *x = ValidatePeerCertificateChainReq_ServerPeer{} if protoimpl.UnsafeEnabled { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ValidatePeerCertificateChainReq_ServerPeer) String() string { return protoimpl.X.MessageStringOf(x) } func (*ValidatePeerCertificateChainReq_ServerPeer) ProtoMessage() {} func (x *ValidatePeerCertificateChainReq_ServerPeer) ProtoReflect() protoreflect.Message { mi := &file_internal_proto_v2_s2a_s2a_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ValidatePeerCertificateChainReq_ServerPeer.ProtoReflect.Descriptor instead. func (*ValidatePeerCertificateChainReq_ServerPeer) Descriptor() ([]byte, []int) { return file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP(), []int{9, 1} } func (x *ValidatePeerCertificateChainReq_ServerPeer) GetCertificateChain() [][]byte { if x != nil { return x.CertificateChain } return nil } func (x *ValidatePeerCertificateChainReq_ServerPeer) GetServerHostname() string { if x != nil { return x.ServerHostname } return "" } func (x *ValidatePeerCertificateChainReq_ServerPeer) GetSerializedUnrestrictedClientPolicy() []byte { if x != nil { return x.SerializedUnrestrictedClientPolicy } return nil } var File_internal_proto_v2_s2a_s2a_proto protoreflect.FileDescriptor var file_internal_proto_v2_s2a_s2a_proto_rawDesc = []byte{ 0x0a, 0x1f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x1a, 0x25, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 0x0a, 0x0a, 0x41, 0x6c, 0x70, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x6e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6c, 0x70, 0x6e, 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0e, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0d, 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x22, 0x7e, 0x0a, 0x17, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x12, 0x32, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x36, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x71, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x45, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x64, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x6e, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x6e, 0x69, 0x22, 0xf1, 0x0b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x78, 0x0a, 0x18, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x16, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x78, 0x0a, 0x18, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x16, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xcf, 0x02, 0x0a, 0x16, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x6c, 0x70, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x1a, 0xfa, 0x06, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x4c, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x54, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x74, 0x6c, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x74, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x93, 0x01, 0x0a, 0x1a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x55, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x18, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x1b, 0x6d, 0x61, 0x78, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x61, 0x65, 0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x6d, 0x61, 0x78, 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x61, 0x64, 0x4f, 0x66, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x65, 0x61, 0x64, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x6c, 0x70, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x6c, 0x70, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x61, 0x6c, 0x70, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x9e, 0x02, 0x0a, 0x18, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x4f, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x2e, 0x0a, 0x2a, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x55, 0x54, 0x5f, 0x44, 0x4f, 0x4e, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x02, 0x12, 0x29, 0x0a, 0x25, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x03, 0x12, 0x3a, 0x0a, 0x36, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x55, 0x54, 0x5f, 0x44, 0x4f, 0x4e, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x04, 0x12, 0x35, 0x0a, 0x31, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x42, 0x13, 0x0a, 0x11, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb0, 0x03, 0x0a, 0x1d, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x5d, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3f, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x13, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1d, 0x0a, 0x09, 0x72, 0x61, 0x77, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x08, 0x72, 0x61, 0x77, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x33, 0x38, 0x34, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x33, 0x38, 0x34, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x35, 0x31, 0x32, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x35, 0x31, 0x32, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x3d, 0x0a, 0x13, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x49, 0x47, 0x4e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x43, 0x52, 0x59, 0x50, 0x54, 0x10, 0x02, 0x42, 0x0a, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x1e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x20, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x63, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x45, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x43, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x43, 0x52, 0x59, 0x50, 0x54, 0x10, 0x02, 0x22, 0x40, 0x0a, 0x21, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xf4, 0x05, 0x0a, 0x1f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x52, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x5b, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x65, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x65, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x65, 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x1a, 0xb5, 0x01, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x51, 0x0a, 0x25, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x22, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x55, 0x6e, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xc1, 0x01, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x50, 0x49, 0x46, 0x46, 0x45, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x4f, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x5f, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x33, 0x10, 0x03, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x5f, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x34, 0x10, 0x04, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x5f, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x35, 0x10, 0x05, 0x42, 0x0c, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0xb2, 0x02, 0x0a, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x6c, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3f, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x32, 0x41, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x3d, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x02, 0x22, 0xa0, 0x05, 0x0a, 0x0a, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x3d, 0x0a, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x62, 0x0a, 0x19, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x52, 0x18, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73, 0x12, 0x61, 0x0a, 0x19, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x16, 0x67, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x77, 0x0a, 0x21, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x1d, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x80, 0x01, 0x0a, 0x24, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x20, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x7d, 0x0a, 0x23, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x1f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x42, 0x0b, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0xb4, 0x04, 0x0a, 0x0b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x64, 0x0a, 0x1a, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x48, 0x00, 0x52, 0x17, 0x67, 0x65, 0x74, 0x54, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x7a, 0x0a, 0x22, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x48, 0x00, 0x52, 0x1e, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x83, 0x01, 0x0a, 0x25, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x48, 0x00, 0x52, 0x21, 0x6f, 0x66, 0x66, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x80, 0x01, 0x0a, 0x24, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x48, 0x00, 0x52, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0c, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x70, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x2a, 0xa2, 0x03, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x4b, 0x43, 0x53, 0x31, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x4b, 0x43, 0x53, 0x31, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x4b, 0x43, 0x53, 0x31, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x03, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x53, 0x45, 0x43, 0x50, 0x32, 0x35, 0x36, 0x52, 0x31, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x04, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x53, 0x45, 0x43, 0x50, 0x33, 0x38, 0x34, 0x52, 0x31, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x05, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x53, 0x45, 0x43, 0x50, 0x35, 0x32, 0x31, 0x52, 0x31, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x06, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x5f, 0x52, 0x53, 0x41, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x07, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x5f, 0x52, 0x53, 0x41, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x33, 0x38, 0x34, 0x10, 0x08, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x5f, 0x52, 0x53, 0x41, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x10, 0x09, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x32, 0x41, 0x5f, 0x53, 0x53, 0x4c, 0x5f, 0x53, 0x49, 0x47, 0x4e, 0x5f, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x10, 0x0a, 0x32, 0x57, 0x0a, 0x0a, 0x53, 0x32, 0x41, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x55, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x73, 0x32, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x73, 0x32, 0x61, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x32, 0x61, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_internal_proto_v2_s2a_s2a_proto_rawDescOnce sync.Once file_internal_proto_v2_s2a_s2a_proto_rawDescData = file_internal_proto_v2_s2a_s2a_proto_rawDesc ) func file_internal_proto_v2_s2a_s2a_proto_rawDescGZIP() []byte { file_internal_proto_v2_s2a_s2a_proto_rawDescOnce.Do(func() { file_internal_proto_v2_s2a_s2a_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_proto_v2_s2a_s2a_proto_rawDescData) }) return file_internal_proto_v2_s2a_s2a_proto_rawDescData } var file_internal_proto_v2_s2a_s2a_proto_enumTypes = make([]protoimpl.EnumInfo, 6) var file_internal_proto_v2_s2a_s2a_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_internal_proto_v2_s2a_s2a_proto_goTypes = []any{ (SignatureAlgorithm)(0), // 0: s2a.proto.v2.SignatureAlgorithm (GetTlsConfigurationResp_ServerTlsConfiguration_RequestClientCertificate)(0), // 1: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.RequestClientCertificate (OffloadPrivateKeyOperationReq_PrivateKeyOperation)(0), // 2: s2a.proto.v2.OffloadPrivateKeyOperationReq.PrivateKeyOperation (OffloadResumptionKeyOperationReq_ResumptionKeyOperation)(0), // 3: s2a.proto.v2.OffloadResumptionKeyOperationReq.ResumptionKeyOperation (ValidatePeerCertificateChainReq_VerificationMode)(0), // 4: s2a.proto.v2.ValidatePeerCertificateChainReq.VerificationMode (ValidatePeerCertificateChainResp_ValidationResult)(0), // 5: s2a.proto.v2.ValidatePeerCertificateChainResp.ValidationResult (*AlpnPolicy)(nil), // 6: s2a.proto.v2.AlpnPolicy (*AuthenticationMechanism)(nil), // 7: s2a.proto.v2.AuthenticationMechanism (*Status)(nil), // 8: s2a.proto.v2.Status (*GetTlsConfigurationReq)(nil), // 9: s2a.proto.v2.GetTlsConfigurationReq (*GetTlsConfigurationResp)(nil), // 10: s2a.proto.v2.GetTlsConfigurationResp (*OffloadPrivateKeyOperationReq)(nil), // 11: s2a.proto.v2.OffloadPrivateKeyOperationReq (*OffloadPrivateKeyOperationResp)(nil), // 12: s2a.proto.v2.OffloadPrivateKeyOperationResp (*OffloadResumptionKeyOperationReq)(nil), // 13: s2a.proto.v2.OffloadResumptionKeyOperationReq (*OffloadResumptionKeyOperationResp)(nil), // 14: s2a.proto.v2.OffloadResumptionKeyOperationResp (*ValidatePeerCertificateChainReq)(nil), // 15: s2a.proto.v2.ValidatePeerCertificateChainReq (*ValidatePeerCertificateChainResp)(nil), // 16: s2a.proto.v2.ValidatePeerCertificateChainResp (*SessionReq)(nil), // 17: s2a.proto.v2.SessionReq (*SessionResp)(nil), // 18: s2a.proto.v2.SessionResp (*GetTlsConfigurationResp_ClientTlsConfiguration)(nil), // 19: s2a.proto.v2.GetTlsConfigurationResp.ClientTlsConfiguration (*GetTlsConfigurationResp_ServerTlsConfiguration)(nil), // 20: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration (*ValidatePeerCertificateChainReq_ClientPeer)(nil), // 21: s2a.proto.v2.ValidatePeerCertificateChainReq.ClientPeer (*ValidatePeerCertificateChainReq_ServerPeer)(nil), // 22: s2a.proto.v2.ValidatePeerCertificateChainReq.ServerPeer (common_go_proto.AlpnProtocol)(0), // 23: s2a.proto.v2.AlpnProtocol (*common_go_proto.Identity)(nil), // 24: s2a.proto.v2.Identity (common_go_proto.ConnectionSide)(0), // 25: s2a.proto.v2.ConnectionSide (*s2a_context_go_proto.S2AContext)(nil), // 26: s2a.proto.v2.S2AContext (common_go_proto.TLSVersion)(0), // 27: s2a.proto.v2.TLSVersion (common_go_proto.Ciphersuite)(0), // 28: s2a.proto.v2.Ciphersuite } var file_internal_proto_v2_s2a_s2a_proto_depIdxs = []int32{ 23, // 0: s2a.proto.v2.AlpnPolicy.alpn_protocols:type_name -> s2a.proto.v2.AlpnProtocol 24, // 1: s2a.proto.v2.AuthenticationMechanism.identity:type_name -> s2a.proto.v2.Identity 25, // 2: s2a.proto.v2.GetTlsConfigurationReq.connection_side:type_name -> s2a.proto.v2.ConnectionSide 19, // 3: s2a.proto.v2.GetTlsConfigurationResp.client_tls_configuration:type_name -> s2a.proto.v2.GetTlsConfigurationResp.ClientTlsConfiguration 20, // 4: s2a.proto.v2.GetTlsConfigurationResp.server_tls_configuration:type_name -> s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration 2, // 5: s2a.proto.v2.OffloadPrivateKeyOperationReq.operation:type_name -> s2a.proto.v2.OffloadPrivateKeyOperationReq.PrivateKeyOperation 0, // 6: s2a.proto.v2.OffloadPrivateKeyOperationReq.signature_algorithm:type_name -> s2a.proto.v2.SignatureAlgorithm 3, // 7: s2a.proto.v2.OffloadResumptionKeyOperationReq.operation:type_name -> s2a.proto.v2.OffloadResumptionKeyOperationReq.ResumptionKeyOperation 4, // 8: s2a.proto.v2.ValidatePeerCertificateChainReq.mode:type_name -> s2a.proto.v2.ValidatePeerCertificateChainReq.VerificationMode 21, // 9: s2a.proto.v2.ValidatePeerCertificateChainReq.client_peer:type_name -> s2a.proto.v2.ValidatePeerCertificateChainReq.ClientPeer 22, // 10: s2a.proto.v2.ValidatePeerCertificateChainReq.server_peer:type_name -> s2a.proto.v2.ValidatePeerCertificateChainReq.ServerPeer 5, // 11: s2a.proto.v2.ValidatePeerCertificateChainResp.validation_result:type_name -> s2a.proto.v2.ValidatePeerCertificateChainResp.ValidationResult 26, // 12: s2a.proto.v2.ValidatePeerCertificateChainResp.context:type_name -> s2a.proto.v2.S2AContext 24, // 13: s2a.proto.v2.SessionReq.local_identity:type_name -> s2a.proto.v2.Identity 7, // 14: s2a.proto.v2.SessionReq.authentication_mechanisms:type_name -> s2a.proto.v2.AuthenticationMechanism 9, // 15: s2a.proto.v2.SessionReq.get_tls_configuration_req:type_name -> s2a.proto.v2.GetTlsConfigurationReq 11, // 16: s2a.proto.v2.SessionReq.offload_private_key_operation_req:type_name -> s2a.proto.v2.OffloadPrivateKeyOperationReq 13, // 17: s2a.proto.v2.SessionReq.offload_resumption_key_operation_req:type_name -> s2a.proto.v2.OffloadResumptionKeyOperationReq 15, // 18: s2a.proto.v2.SessionReq.validate_peer_certificate_chain_req:type_name -> s2a.proto.v2.ValidatePeerCertificateChainReq 8, // 19: s2a.proto.v2.SessionResp.status:type_name -> s2a.proto.v2.Status 10, // 20: s2a.proto.v2.SessionResp.get_tls_configuration_resp:type_name -> s2a.proto.v2.GetTlsConfigurationResp 12, // 21: s2a.proto.v2.SessionResp.offload_private_key_operation_resp:type_name -> s2a.proto.v2.OffloadPrivateKeyOperationResp 14, // 22: s2a.proto.v2.SessionResp.offload_resumption_key_operation_resp:type_name -> s2a.proto.v2.OffloadResumptionKeyOperationResp 16, // 23: s2a.proto.v2.SessionResp.validate_peer_certificate_chain_resp:type_name -> s2a.proto.v2.ValidatePeerCertificateChainResp 27, // 24: s2a.proto.v2.GetTlsConfigurationResp.ClientTlsConfiguration.min_tls_version:type_name -> s2a.proto.v2.TLSVersion 27, // 25: s2a.proto.v2.GetTlsConfigurationResp.ClientTlsConfiguration.max_tls_version:type_name -> s2a.proto.v2.TLSVersion 28, // 26: s2a.proto.v2.GetTlsConfigurationResp.ClientTlsConfiguration.ciphersuites:type_name -> s2a.proto.v2.Ciphersuite 6, // 27: s2a.proto.v2.GetTlsConfigurationResp.ClientTlsConfiguration.alpn_policy:type_name -> s2a.proto.v2.AlpnPolicy 27, // 28: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.min_tls_version:type_name -> s2a.proto.v2.TLSVersion 27, // 29: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.max_tls_version:type_name -> s2a.proto.v2.TLSVersion 28, // 30: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.ciphersuites:type_name -> s2a.proto.v2.Ciphersuite 1, // 31: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.request_client_certificate:type_name -> s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.RequestClientCertificate 6, // 32: s2a.proto.v2.GetTlsConfigurationResp.ServerTlsConfiguration.alpn_policy:type_name -> s2a.proto.v2.AlpnPolicy 17, // 33: s2a.proto.v2.S2AService.SetUpSession:input_type -> s2a.proto.v2.SessionReq 18, // 34: s2a.proto.v2.S2AService.SetUpSession:output_type -> s2a.proto.v2.SessionResp 34, // [34:35] is the sub-list for method output_type 33, // [33:34] is the sub-list for method input_type 33, // [33:33] is the sub-list for extension type_name 33, // [33:33] is the sub-list for extension extendee 0, // [0:33] is the sub-list for field type_name } func init() { file_internal_proto_v2_s2a_s2a_proto_init() } func file_internal_proto_v2_s2a_s2a_proto_init() { if File_internal_proto_v2_s2a_s2a_proto != nil { return } if !protoimpl.UnsafeEnabled { file_internal_proto_v2_s2a_s2a_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*AlpnPolicy); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*AuthenticationMechanism); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*Status); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*GetTlsConfigurationReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*GetTlsConfigurationResp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*OffloadPrivateKeyOperationReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*OffloadPrivateKeyOperationResp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*OffloadResumptionKeyOperationReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[8].Exporter = func(v any, i int) any { switch v := v.(*OffloadResumptionKeyOperationResp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*ValidatePeerCertificateChainReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[10].Exporter = func(v any, i int) any { switch v := v.(*ValidatePeerCertificateChainResp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[11].Exporter = func(v any, i int) any { switch v := v.(*SessionReq); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[12].Exporter = func(v any, i int) any { switch v := v.(*SessionResp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[13].Exporter = func(v any, i int) any { switch v := v.(*GetTlsConfigurationResp_ClientTlsConfiguration); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[14].Exporter = func(v any, i int) any { switch v := v.(*GetTlsConfigurationResp_ServerTlsConfiguration); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[15].Exporter = func(v any, i int) any { switch v := v.(*ValidatePeerCertificateChainReq_ClientPeer); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[16].Exporter = func(v any, i int) any { switch v := v.(*ValidatePeerCertificateChainReq_ServerPeer); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } file_internal_proto_v2_s2a_s2a_proto_msgTypes[1].OneofWrappers = []any{ (*AuthenticationMechanism_Token)(nil), } file_internal_proto_v2_s2a_s2a_proto_msgTypes[4].OneofWrappers = []any{ (*GetTlsConfigurationResp_ClientTlsConfiguration_)(nil), (*GetTlsConfigurationResp_ServerTlsConfiguration_)(nil), } file_internal_proto_v2_s2a_s2a_proto_msgTypes[5].OneofWrappers = []any{ (*OffloadPrivateKeyOperationReq_RawBytes)(nil), (*OffloadPrivateKeyOperationReq_Sha256Digest)(nil), (*OffloadPrivateKeyOperationReq_Sha384Digest)(nil), (*OffloadPrivateKeyOperationReq_Sha512Digest)(nil), } file_internal_proto_v2_s2a_s2a_proto_msgTypes[9].OneofWrappers = []any{ (*ValidatePeerCertificateChainReq_ClientPeer_)(nil), (*ValidatePeerCertificateChainReq_ServerPeer_)(nil), } file_internal_proto_v2_s2a_s2a_proto_msgTypes[11].OneofWrappers = []any{ (*SessionReq_GetTlsConfigurationReq)(nil), (*SessionReq_OffloadPrivateKeyOperationReq)(nil), (*SessionReq_OffloadResumptionKeyOperationReq)(nil), (*SessionReq_ValidatePeerCertificateChainReq)(nil), } file_internal_proto_v2_s2a_s2a_proto_msgTypes[12].OneofWrappers = []any{ (*SessionResp_GetTlsConfigurationResp)(nil), (*SessionResp_OffloadPrivateKeyOperationResp)(nil), (*SessionResp_OffloadResumptionKeyOperationResp)(nil), (*SessionResp_ValidatePeerCertificateChainResp)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_proto_v2_s2a_s2a_proto_rawDesc, NumEnums: 6, NumMessages: 17, NumExtensions: 0, NumServices: 1, }, GoTypes: file_internal_proto_v2_s2a_s2a_proto_goTypes, DependencyIndexes: file_internal_proto_v2_s2a_s2a_proto_depIdxs, EnumInfos: file_internal_proto_v2_s2a_s2a_proto_enumTypes, MessageInfos: file_internal_proto_v2_s2a_s2a_proto_msgTypes, }.Build() File_internal_proto_v2_s2a_s2a_proto = out.File file_internal_proto_v2_s2a_s2a_proto_rawDesc = nil file_internal_proto_v2_s2a_s2a_proto_goTypes = nil file_internal_proto_v2_s2a_s2a_proto_depIdxs = nil } s2a-go-0.1.8/internal/proto/v2/s2a_go_proto/s2a_grpc.pb.go000066400000000000000000000122111464711036600231470ustar00rootroot00000000000000// 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. // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.4.0 // - protoc v3.21.12 // source: internal/proto/v2/s2a/s2a.proto package s2a_go_proto import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.62.0 or later. const _ = grpc.SupportPackageIsVersion8 const ( S2AService_SetUpSession_FullMethodName = "/s2a.proto.v2.S2AService/SetUpSession" ) // S2AServiceClient is the client API for S2AService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type S2AServiceClient interface { // SetUpSession is a bidirectional stream used by applications to offload // operations from the TLS handshake. SetUpSession(ctx context.Context, opts ...grpc.CallOption) (S2AService_SetUpSessionClient, error) } type s2AServiceClient struct { cc grpc.ClientConnInterface } func NewS2AServiceClient(cc grpc.ClientConnInterface) S2AServiceClient { return &s2AServiceClient{cc} } func (c *s2AServiceClient) SetUpSession(ctx context.Context, opts ...grpc.CallOption) (S2AService_SetUpSessionClient, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &S2AService_ServiceDesc.Streams[0], S2AService_SetUpSession_FullMethodName, cOpts...) if err != nil { return nil, err } x := &s2AServiceSetUpSessionClient{ClientStream: stream} return x, nil } type S2AService_SetUpSessionClient interface { Send(*SessionReq) error Recv() (*SessionResp, error) grpc.ClientStream } type s2AServiceSetUpSessionClient struct { grpc.ClientStream } func (x *s2AServiceSetUpSessionClient) Send(m *SessionReq) error { return x.ClientStream.SendMsg(m) } func (x *s2AServiceSetUpSessionClient) Recv() (*SessionResp, error) { m := new(SessionResp) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // S2AServiceServer is the server API for S2AService service. // All implementations must embed UnimplementedS2AServiceServer // for forward compatibility type S2AServiceServer interface { // SetUpSession is a bidirectional stream used by applications to offload // operations from the TLS handshake. SetUpSession(S2AService_SetUpSessionServer) error mustEmbedUnimplementedS2AServiceServer() } // UnimplementedS2AServiceServer must be embedded to have forward compatible implementations. type UnimplementedS2AServiceServer struct { } func (UnimplementedS2AServiceServer) SetUpSession(S2AService_SetUpSessionServer) error { return status.Errorf(codes.Unimplemented, "method SetUpSession not implemented") } func (UnimplementedS2AServiceServer) mustEmbedUnimplementedS2AServiceServer() {} // UnsafeS2AServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to S2AServiceServer will // result in compilation errors. type UnsafeS2AServiceServer interface { mustEmbedUnimplementedS2AServiceServer() } func RegisterS2AServiceServer(s grpc.ServiceRegistrar, srv S2AServiceServer) { s.RegisterService(&S2AService_ServiceDesc, srv) } func _S2AService_SetUpSession_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(S2AServiceServer).SetUpSession(&s2AServiceSetUpSessionServer{ServerStream: stream}) } type S2AService_SetUpSessionServer interface { Send(*SessionResp) error Recv() (*SessionReq, error) grpc.ServerStream } type s2AServiceSetUpSessionServer struct { grpc.ServerStream } func (x *s2AServiceSetUpSessionServer) Send(m *SessionResp) error { return x.ServerStream.SendMsg(m) } func (x *s2AServiceSetUpSessionServer) Recv() (*SessionReq, error) { m := new(SessionReq) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } return m, nil } // S2AService_ServiceDesc is the grpc.ServiceDesc for S2AService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var S2AService_ServiceDesc = grpc.ServiceDesc{ ServiceName: "s2a.proto.v2.S2AService", HandlerType: (*S2AServiceServer)(nil), Methods: []grpc.MethodDesc{}, Streams: []grpc.StreamDesc{ { StreamName: "SetUpSession", Handler: _S2AService_SetUpSession_Handler, ServerStreams: true, ClientStreams: true, }, }, Metadata: "internal/proto/v2/s2a/s2a.proto", } s2a-go-0.1.8/internal/record/000077500000000000000000000000001464711036600157125ustar00rootroot00000000000000s2a-go-0.1.8/internal/record/internal/000077500000000000000000000000001464711036600175265ustar00rootroot00000000000000s2a-go-0.1.8/internal/record/internal/aeadcrypter/000077500000000000000000000000001464711036600220315ustar00rootroot00000000000000s2a-go-0.1.8/internal/record/internal/aeadcrypter/aeadcrypter.go000066400000000000000000000024011464711036600246600ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter provides the interface for AEAD cipher implementations // used by S2A's record protocol. package aeadcrypter // S2AAEADCrypter is the interface for an AEAD cipher used by the S2A record // protocol. type S2AAEADCrypter interface { // Encrypt encrypts the plaintext and computes the tag of dst and plaintext. // dst and plaintext may fully overlap or not at all. Encrypt(dst, plaintext, nonce, aad []byte) ([]byte, error) // Decrypt decrypts ciphertext and verifies the tag. dst and ciphertext may // fully overlap or not at all. Decrypt(dst, ciphertext, nonce, aad []byte) ([]byte, error) // TagSize returns the tag size in bytes. TagSize() int } s2a-go-0.1.8/internal/record/internal/aeadcrypter/aesgcm.go000066400000000000000000000037731464711036600236310ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter import ( "crypto/aes" "crypto/cipher" "fmt" ) // Supported key sizes in bytes. const ( AES128GCMKeySize = 16 AES256GCMKeySize = 32 ) // aesgcm is the struct that holds an AES-GCM cipher for the S2A AEAD crypter. type aesgcm struct { aead cipher.AEAD } // NewAESGCM creates an AES-GCM crypter instance. Note that the key must be // either 128 bits or 256 bits. func NewAESGCM(key []byte) (S2AAEADCrypter, error) { if len(key) != AES128GCMKeySize && len(key) != AES256GCMKeySize { return nil, fmt.Errorf("%d or %d bytes, given: %d", AES128GCMKeySize, AES256GCMKeySize, len(key)) } c, err := aes.NewCipher(key) if err != nil { return nil, err } a, err := cipher.NewGCM(c) if err != nil { return nil, err } return &aesgcm{aead: a}, nil } // Encrypt is the encryption function. dst can contain bytes at the beginning of // the ciphertext that will not be encrypted but will be authenticated. If dst // has enough capacity to hold these bytes, the ciphertext and the tag, no // allocation and copy operations will be performed. dst and plaintext may // fully overlap or not at all. func (s *aesgcm) Encrypt(dst, plaintext, nonce, aad []byte) ([]byte, error) { return encrypt(s.aead, dst, plaintext, nonce, aad) } func (s *aesgcm) Decrypt(dst, ciphertext, nonce, aad []byte) ([]byte, error) { return decrypt(s.aead, dst, ciphertext, nonce, aad) } func (s *aesgcm) TagSize() int { return TagSize } s2a-go-0.1.8/internal/record/internal/aeadcrypter/aesgcm_test.go000066400000000000000000000461751464711036600246730ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter import ( "fmt" "testing" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) // getGCMCryptoPair outputs a sender/receiver pair on AES-GCM. func getGCMCryptoPair(key []byte, t *testing.T) (S2AAEADCrypter, S2AAEADCrypter) { sender, err := NewAESGCM(key) if err != nil { t.Fatalf("NewAESGCM(ClientSide, key) = %v", err) } receiver, err := NewAESGCM(key) if err != nil { t.Fatalf("NewAESGCM(ServerSide, key) = %v", err) } return sender, receiver } // wycheProofTestVectorFilter filters out unsupported wycheproof test vectors. func wycheProofTestVectorFilter(testGroup testutil.TestGroup) bool { // Filter these test groups out, since they are not supported in our // implementation of AES-GCM. return testGroup.IVSize != 96 || (testGroup.KeySize != 128 && testGroup.KeySize != 256) || testGroup.TagSize != 128 } func testGCMEncryptionDecryption(sender S2AAEADCrypter, receiver S2AAEADCrypter, tc *testutil.CryptoTestVector, t *testing.T) { // ciphertext is: encrypted text + tag. ciphertext := append(tc.Ciphertext, tc.Tag...) // Encrypt. var dst []byte if tc.AllocateDst { dst = make([]byte, len(tc.Plaintext)+sender.TagSize()) } got, err := sender.Encrypt(dst[:0], tc.Plaintext, tc.Nonce, tc.Aad) if testutil.IsFailure(tc.Result, err, got, ciphertext) { t.Errorf("key=%v\nEncrypt(\n dst = %v\n plaintext = %v\n nonce = %v\n aad = %v\n) = (\n %v\n %v\n), want %v", tc.Key, dst[:0], tc.Plaintext, tc.Nonce, tc.Aad, got, err, ciphertext) } // Decrypt. got, err = receiver.Decrypt(nil, ciphertext, tc.Nonce, tc.Aad) if testutil.IsFailure(tc.Result, err, got, tc.Plaintext) { t.Errorf("key=%v\nDecrypt(\n dst = nil\n ciphertext = %v\n nonce = %v\n aad = %v\n) = (\n %v\n %v\n), want %v", tc.Key, ciphertext, tc.Nonce, tc.Aad, got, err, tc.Plaintext) } } func testGCMEncryptRoundtrip(sender S2AAEADCrypter, receiver S2AAEADCrypter, t *testing.T) { // Construct a dummy nonce. nonce := make([]byte, NonceSize) // Encrypt. const plaintext = "This is plaintext." var err error // Reuse `buf` as both the input and output buffer. This is required to test // the case where the input and output buffers fully overlap. buf := []byte(plaintext) ciphertext, err := sender.Encrypt(buf[:0], buf, nonce, nil) if err != nil { t.Fatalf("Encrypt(%v, %v, %v, nil) failed: %v", buf[:0], buf, nonce, err) } // Decrypt first message. decryptedPlaintext, err := receiver.Decrypt(ciphertext[:0], ciphertext, nonce, nil) if err != nil { t.Fatalf("Decrypt(%v, %v, %v, nil) failed: %v", ciphertext[:0], ciphertext, nonce, err) } if string(decryptedPlaintext) != plaintext { t.Fatalf("Decrypt(%v, %v, %v, nil) = %v, want %v", ciphertext[:0], ciphertext, nonce, decryptedPlaintext, plaintext) } } // Test encrypt and decrypt using an invalid key size. func TestAESGCMInvalidKeySize(t *testing.T) { // Use 17 bytes, which is invalid key := make([]byte, 17) if _, err := NewAESGCM(key); err == nil { t.Error("expected an error when using invalid key size") } } // Test encrypt and decrypt on roundtrip messages for AES-GCM. func TestAESGCMEncryptRoundtrip(t *testing.T) { for _, keySize := range []int{AES128GCMKeySize, AES256GCMKeySize} { t.Run(fmt.Sprintf("keySize=%d", keySize), func(t *testing.T) { key := make([]byte, keySize) sender, receiver := getGCMCryptoPair(key, t) testGCMEncryptRoundtrip(sender, receiver, t) }) } } // Test encrypt and decrypt using test vectors for aes128gcm. func TestAESGCMEncrypt(t *testing.T) { for _, tc := range []testutil.CryptoTestVector{ { Desc: "nil plaintext and ciphertext", Key: testutil.Dehex("11754cd72aec309bf52f7687212e8957"), Tag: testutil.Dehex("250327c674aaf477aef2675748cf6971"), Nonce: testutil.Dehex("3c819d9a9bed087615030b65"), Result: testutil.ValidResult, }, { Desc: "invalid nonce size", Key: testutil.Dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"), Plaintext: testutil.Dehex("007c5e5b3e59df24a7c355584fc1518d"), Ciphertext: testutil.Dehex("0e1bde206a07a9c2c1b65300f8c64997"), Tag: testutil.Dehex("2b4401346697138c7a4891ee59867d0c"), Nonce: testutil.Dehex("00"), Result: testutil.InvalidResult, }, { Desc: "nil plaintext and ciphertext with dst allocation", Key: testutil.Dehex("11754cd72aec309bf52f7687212e8957"), Tag: testutil.Dehex("250327c674aaf477aef2675748cf6971"), Nonce: testutil.Dehex("3c819d9a9bed087615030b65"), Result: testutil.ValidResult, AllocateDst: true, }, { Desc: "basic test 1", Key: testutil.Dehex("7fddb57453c241d03efbed3ac44e371c"), Plaintext: testutil.Dehex("d5de42b461646c255c87bd2962d3b9a2"), Ciphertext: testutil.Dehex("2ccda4a5415cb91e135c2a0f78c9b2fd"), Tag: testutil.Dehex("b36d1df9b9d5e596f83e8b7f52971cb3"), Nonce: testutil.Dehex("ee283a3fc75575e33efd4887"), Result: testutil.ValidResult, }, { Desc: "basic test 2", Key: testutil.Dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"), Plaintext: testutil.Dehex("007c5e5b3e59df24a7c355584fc1518d"), Ciphertext: testutil.Dehex("0e1bde206a07a9c2c1b65300f8c64997"), Tag: testutil.Dehex("2b4401346697138c7a4891ee59867d0c"), Nonce: testutil.Dehex("54cc7dc2c37ec006bcc6d1da"), Result: testutil.ValidResult, }, { Desc: "basic dst allocation 1", Key: testutil.Dehex("7fddb57453c241d03efbed3ac44e371c"), Plaintext: testutil.Dehex("d5de42b461646c255c87bd2962d3b9a2"), Ciphertext: testutil.Dehex("2ccda4a5415cb91e135c2a0f78c9b2fd"), Tag: testutil.Dehex("b36d1df9b9d5e596f83e8b7f52971cb3"), Nonce: testutil.Dehex("ee283a3fc75575e33efd4887"), Result: testutil.ValidResult, AllocateDst: true, }, { Desc: "basic dst allocation 2", Key: testutil.Dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"), Plaintext: testutil.Dehex("007c5e5b3e59df24a7c355584fc1518d"), Ciphertext: testutil.Dehex("0e1bde206a07a9c2c1b65300f8c64997"), Tag: testutil.Dehex("2b4401346697138c7a4891ee59867d0c"), Nonce: testutil.Dehex("54cc7dc2c37ec006bcc6d1da"), Result: testutil.ValidResult, AllocateDst: true, }, { Desc: "basic dst allocation 3", Key: testutil.Dehex("5b9604fe14eadba931b0ccf34843dab9"), Plaintext: testutil.Dehex("001d0c231287c1182784554ca3a21908"), Ciphertext: testutil.Dehex("26073cc1d851beff176384dc9896d5ff"), Tag: testutil.Dehex("0a3ea7a5487cb5f7d70fb6c58d038554"), Nonce: testutil.Dehex("028318abc1824029138141a2"), Result: testutil.ValidResult, AllocateDst: true, }, } { t.Run(fmt.Sprintf("%s", tc.Desc), func(t *testing.T) { sender, receiver := getGCMCryptoPair(tc.Key, t) testGCMEncryptionDecryption(sender, receiver, &tc, t) }) } } func TestWycheProofTestVectors(t *testing.T) { for _, tc := range testutil.ParseWycheProofTestVectors("testdata/aes_gcm_wycheproof.json", wycheProofTestVectorFilter, t) { t.Run(fmt.Sprintf("%d/%s", tc.ID, tc.Desc), func(t *testing.T) { // Test encryption and decryption for AES-GCM. sender, receiver := getGCMCryptoPair(tc.Key, t) testGCMEncryptionDecryption(sender, receiver, &tc, t) }) } } // Test AES-GCM with NIST and IEEE test vectors. func TestAESGCMNISTAndIEEE(t *testing.T) { // NIST vectors from: // http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf // IEEE vectors from: // http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf for _, tc := range []testutil.CryptoTestVector{ { Desc: "NIST test vector 1", Key: testutil.Dehex("00000000000000000000000000000000"), Nonce: testutil.Dehex("000000000000000000000000"), Aad: testutil.Dehex(""), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("58e2fccefa7e3061367f1d57a4e7455a"), Result: testutil.ValidResult, }, { Desc: "NIST test vector 2", Key: testutil.Dehex("00000000000000000000000000000000"), Nonce: testutil.Dehex("000000000000000000000000"), Aad: testutil.Dehex(""), Plaintext: testutil.Dehex("00000000000000000000000000000000"), Ciphertext: testutil.Dehex("0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf"), Result: testutil.ValidResult, }, { Desc: "NIST test vector 3", Key: testutil.Dehex("feffe9928665731c6d6a8f9467308308"), Nonce: testutil.Dehex("cafebabefacedbaddecaf888"), Aad: testutil.Dehex(""), Plaintext: testutil.Dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"), Ciphertext: testutil.Dehex("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4"), Result: testutil.ValidResult, }, { Desc: "NIST test vector 4", Key: testutil.Dehex("feffe9928665731c6d6a8f9467308308"), Nonce: testutil.Dehex("cafebabefacedbaddecaf888"), Aad: testutil.Dehex("feedfacedeadbeeffeedfacedeadbeefabaddad2"), Plaintext: testutil.Dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"), Ciphertext: testutil.Dehex("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e0915bc94fbc3221a5db94fae95ae7121a47"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.1.1 54-byte auth", Key: testutil.Dehex("ad7a2bd03eac835a6f620fdcb506b345"), Nonce: testutil.Dehex("12153524c0895e81b2c28465"), Aad: testutil.Dehex("d609b1f056637a0d46df998d88e5222ab2c2846512153524c0895e8108000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340001"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("f09478a9b09007d06f46e9b6a1da25dd"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.1.2 54-byte auth", Key: testutil.Dehex("e3c08a8f06c6e3ad95a70557b23f75483ce33021a9c72b7025666204c69c0b72"), Nonce: testutil.Dehex("12153524c0895e81b2c28465"), Aad: testutil.Dehex("d609b1f056637a0d46df998d88e5222ab2c2846512153524c0895e8108000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340001"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("2f0bc5af409e06d609ea8b7d0fa5ea50"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.2.1 60-byte crypt", Key: testutil.Dehex("ad7a2bd03eac835a6f620fdcb506b345"), Nonce: testutil.Dehex("12153524c0895e81b2c28465"), Aad: testutil.Dehex("d609b1f056637a0d46df998d88e52e00b2c2846512153524c0895e81"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0002"), Ciphertext: testutil.Dehex("701afa1cc039c0d765128a665dab69243899bf7318ccdc81c9931da17fbe8edd7d17cb8b4c26fc81e3284f2b7fba713d4f8d55e7d3f06fd5a13c0c29b9d5b880"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.2.2 60-byte crypt", Key: testutil.Dehex("e3c08a8f06c6e3ad95a70557b23f75483ce33021a9c72b7025666204c69c0b72"), Nonce: testutil.Dehex("12153524c0895e81b2c28465"), Aad: testutil.Dehex("d609b1f056637a0d46df998d88e52e00b2c2846512153524c0895e81"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0002"), Ciphertext: testutil.Dehex("e2006eb42f5277022d9b19925bc419d7a592666c925fe2ef718eb4e308efeaa7c5273b394118860a5be2a97f56ab78365ca597cdbb3edb8d1a1151ea0af7b436"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.3.1 60-byte auth", Key: testutil.Dehex("071b113b0ca743fecccf3d051f737382"), Nonce: testutil.Dehex("f0761e8dcd3d000176d457ed"), Aad: testutil.Dehex("e20106d7cd0df0761e8dcd3d88e5400076d457ed08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0003"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("0c017bc73b227dfcc9bafa1c41acc353"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.3.2 60-byte auth", Key: testutil.Dehex("691d3ee909d7f54167fd1ca0b5d769081f2bde1aee655fdbab80bd5295ae6be7"), Nonce: testutil.Dehex("f0761e8dcd3d000176d457ed"), Aad: testutil.Dehex("e20106d7cd0df0761e8dcd3d88e5400076d457ed08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0003"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("35217c774bbc31b63166bcf9d4abed07"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.4.1 54-byte crypt", Key: testutil.Dehex("071b113b0ca743fecccf3d051f737382"), Nonce: testutil.Dehex("f0761e8dcd3d000176d457ed"), Aad: testutil.Dehex("e20106d7cd0df0761e8dcd3d88e54c2a76d457ed"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340004"), Ciphertext: testutil.Dehex("13b4c72b389dc5018e72a171dd85a5d3752274d3a019fbcaed09a425cd9b2e1c9b72eee7c9de7d52b3f3d6a5284f4a6d3fe22a5d6c2b960494c3"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.4.2 54-byte crypt", Key: testutil.Dehex("691d3ee909d7f54167fd1ca0b5d769081f2bde1aee655fdbab80bd5295ae6be7"), Nonce: testutil.Dehex("f0761e8dcd3d000176d457ed"), Aad: testutil.Dehex("e20106d7cd0df0761e8dcd3d88e54c2a76d457ed"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340004"), Ciphertext: testutil.Dehex("c1623f55730c93533097addad25664966125352b43adacbd61c5ef3ac90b5bee929ce4630ea79f6ce51912af39c2d1fdc2051f8b7b3c9d397ef2"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.5.1 65-byte auth", Key: testutil.Dehex("013fe00b5f11be7f866d0cbbc55a7a90"), Nonce: testutil.Dehex("7cfde9f9e33724c68932d612"), Aad: testutil.Dehex("84c5d513d2aaf6e5bbd2727788e523008932d6127cfde9f9e33724c608000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0005"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("217867e50c2dad74c28c3b50abdf695a"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.5.2 65-byte auth", Key: testutil.Dehex("83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a823"), Nonce: testutil.Dehex("7cfde9f9e33724c68932d612"), Aad: testutil.Dehex("84c5d513d2aaf6e5bbd2727788e523008932d6127cfde9f9e33724c608000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0005"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("6ee160e8faeca4b36c86b234920ca975"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.6.1 61-byte crypt", Key: testutil.Dehex("013fe00b5f11be7f866d0cbbc55a7a90"), Nonce: testutil.Dehex("7cfde9f9e33724c68932d612"), Aad: testutil.Dehex("84c5d513d2aaf6e5bbd2727788e52f008932d6127cfde9f9e33724c6"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b0006"), Ciphertext: testutil.Dehex("3a4de6fa32191014dbb303d92ee3a9e8a1b599c14d22fb080096e13811816a3c9c9bcf7c1b9b96da809204e29d0e2a7642bfd310a4837c816ccfa5ac23ab003988"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.6.2 61-byte crypt", Key: testutil.Dehex("83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a823"), Nonce: testutil.Dehex("7cfde9f9e33724c68932d612"), Aad: testutil.Dehex("84c5d513d2aaf6e5bbd2727788e52f008932d6127cfde9f9e33724c6"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b0006"), Ciphertext: testutil.Dehex("110222ff8050cbece66a813ad09a73ed7a9a089c106b959389168ed6e8698ea902eb1277dbec2e68e473155a15a7daeed4a10f4e05139c23df00b3aadc71f0596a"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.7.1 79-byte crypt", Key: testutil.Dehex("88ee087fd95da9fbf6725aa9d757b0cd"), Nonce: testutil.Dehex("7ae8e2ca4ec500012e58495c"), Aad: testutil.Dehex("68f2e77696ce7ae8e2ca4ec588e541002e58495c08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d0007"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("07922b8ebcf10bb2297588ca4c614523"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.7.2 79-byte crypt", Key: testutil.Dehex("4c973dbc7364621674f8b5b89e5c15511fced9216490fb1c1a2caa0ffe0407e5"), Nonce: testutil.Dehex("7ae8e2ca4ec500012e58495c"), Aad: testutil.Dehex("68f2e77696ce7ae8e2ca4ec588e541002e58495c08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d0007"), Plaintext: testutil.Dehex(""), Ciphertext: testutil.Dehex("00bda1b7e87608bcbf470f12157f4c07"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.8.1 61-byte crypt", Key: testutil.Dehex("88ee087fd95da9fbf6725aa9d757b0cd"), Nonce: testutil.Dehex("7ae8e2ca4ec500012e58495c"), Aad: testutil.Dehex("68f2e77696ce7ae8e2ca4ec588e54d002e58495c"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748490008"), Ciphertext: testutil.Dehex("c31f53d99e5687f7365119b832d2aae70741d593f1f9e2ab3455779b078eb8feacdfec1f8e3e5277f8180b43361f6512adb16d2e38548a2c719dba7228d84088f8757adb8aa788d8f65ad668be70e7"), Result: testutil.ValidResult, }, { Desc: "IEEE 2.8.2 61-byte crypt", Key: testutil.Dehex("4c973dbc7364621674f8b5b89e5c15511fced9216490fb1c1a2caa0ffe0407e5"), Nonce: testutil.Dehex("7ae8e2ca4ec500012e58495c"), Aad: testutil.Dehex("68f2e77696ce7ae8e2ca4ec588e54d002e58495c"), Plaintext: testutil.Dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748490008"), Ciphertext: testutil.Dehex("ba8ae31bc506486d6873e4fce460e7dc57591ff00611f31c3834fe1c04ad80b66803afcf5b27e6333fa67c99da47c2f0ced68d531bd741a943cff7a6713bd02611cd7daa01d61c5c886dc1a8170107"), Result: testutil.ValidResult, }, } { t.Run(tc.Desc, func(t *testing.T) { // Test encryption and decryption for AES-GCM. sender, receiver := getGCMCryptoPair(tc.Key, t) testGCMEncryptionDecryption(sender, receiver, &tc, t) }) } } s2a-go-0.1.8/internal/record/internal/aeadcrypter/chachapoly.go000066400000000000000000000037251464711036600245020ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter import ( "crypto/cipher" "fmt" "golang.org/x/crypto/chacha20poly1305" ) // Supported key size in bytes. const ( Chacha20Poly1305KeySize = 32 ) // chachapoly is the struct that holds a CHACHA-POLY cipher for the S2A AEAD // crypter. type chachapoly struct { aead cipher.AEAD } // NewChachaPoly creates a Chacha-Poly crypter instance. Note that the key must // be Chacha20Poly1305KeySize bytes in length. func NewChachaPoly(key []byte) (S2AAEADCrypter, error) { if len(key) != Chacha20Poly1305KeySize { return nil, fmt.Errorf("%d bytes, given: %d", Chacha20Poly1305KeySize, len(key)) } c, err := chacha20poly1305.New(key) if err != nil { return nil, err } return &chachapoly{aead: c}, nil } // Encrypt is the encryption function. dst can contain bytes at the beginning of // the ciphertext that will not be encrypted but will be authenticated. If dst // has enough capacity to hold these bytes, the ciphertext and the tag, no // allocation and copy operations will be performed. dst and plaintext may // fully overlap or not at all. func (s *chachapoly) Encrypt(dst, plaintext, nonce, aad []byte) ([]byte, error) { return encrypt(s.aead, dst, plaintext, nonce, aad) } func (s *chachapoly) Decrypt(dst, ciphertext, nonce, aad []byte) ([]byte, error) { return decrypt(s.aead, dst, ciphertext, nonce, aad) } func (s *chachapoly) TagSize() int { return TagSize } s2a-go-0.1.8/internal/record/internal/aeadcrypter/chachapoly_test.go000066400000000000000000000173641464711036600255450ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter import ( "fmt" "testing" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) // getChachaPolyCrypterPair outputs a sender/receiver pair of CHACHA-POLY AEAD crypters. func getChachaPolyCrypterPair(key []byte, t *testing.T) (S2AAEADCrypter, S2AAEADCrypter) { sender, err := NewChachaPoly(key) if err != nil { t.Fatalf("NewChachaPoly(ClientSide, key) = %v", err) } receiver, err := NewChachaPoly(key) if err != nil { t.Fatalf("NewChachaPoly(ServerSide, key) = %v", err) } return sender, receiver } // wycheProofTestVectorFilter filters out unsupported wycheproof test vectors. func wycheProofTestVectorFilterChachaPoly(testGroup testutil.TestGroup) bool { // Filter these test groups out, since they are not supported in our // implementation of Chacha-Poly. return testGroup.IVSize != 96 || (testGroup.KeySize != 256) || testGroup.TagSize != 128 } func testChachaPolyEncryptionDecryption(sender S2AAEADCrypter, receiver S2AAEADCrypter, tc *testutil.CryptoTestVector, t *testing.T) { // Ciphertext is: encrypted text + tag. ciphertext := append(tc.Ciphertext, tc.Tag...) // Encrypt. var dst []byte if tc.AllocateDst { dst = make([]byte, len(tc.Plaintext)+sender.TagSize()) } got, err := sender.Encrypt(dst[:0], tc.Plaintext, tc.Nonce, tc.Aad) if testutil.IsFailure(tc.Result, err, got, ciphertext) { t.Errorf("key=%v\nEncrypt(\n dst = %v\n plaintext = %v\n nonce = %v\n aad = %v\n) = (\n %v\n %v\n), want %v", tc.Key, dst[:0], tc.Plaintext, tc.Nonce, tc.Aad, got, err, ciphertext) } // Decrypt. got, err = receiver.Decrypt(nil, ciphertext, tc.Nonce, tc.Aad) if testutil.IsFailure(tc.Result, err, got, tc.Plaintext) { t.Errorf("key=%v\nDecrypt(\n dst = nil\n ciphertext = %v\n nonce = %v\n aad = %v\n) = (\n %v\n %v\n), want %v", tc.Key, ciphertext, tc.Nonce, tc.Aad, got, err, tc.Plaintext) } } func testChachaPolyEncryptRoundtrip(sender S2AAEADCrypter, receiver S2AAEADCrypter, t *testing.T) { // Construct a dummy nonce. nonce := make([]byte, NonceSize) // Encrypt. const plaintext = "This is plaintext." var err error // Reuse `buf` as both the input and output buffer. This is required to test // the case where the input and output buffers fully overlap. buf := []byte(plaintext) ciphertext, err := sender.Encrypt(buf[:0], buf, nonce, nil) if err != nil { t.Fatalf("Encrypt(%v, %v, %v, nil) failed: %v", buf[:0], buf, nonce, err) } // Decrypt first message. decryptedPlaintext, err := receiver.Decrypt(ciphertext[:0], ciphertext, nonce, nil) if err != nil { t.Fatalf("Decrypt(%v, %v, %v, nil) failed: %v", ciphertext[:0], ciphertext, nonce, err) } if string(decryptedPlaintext) != plaintext { t.Fatalf("Decrypt(%v, %v, %v, nil) = %v, want %v", ciphertext[:0], ciphertext, nonce, decryptedPlaintext, plaintext) } } // Test creating new Chacha-Poly AEAD crypter using an invalid key size. func TestChachaPolyInvalidKeySize(t *testing.T) { // Use 1 + keySize, which is invalid. key := make([]byte, 1+Chacha20Poly1305KeySize) if _, err := NewChachaPoly(key); err == nil { t.Error("expected an error when using invalid key size") } } // Test Encrypt/Decrypt using an invalid nonce size. func TestChachaPolyEncryptDecryptInvalidNonce(t *testing.T) { key := make([]byte, Chacha20Poly1305KeySize) crypter, err := NewChachaPoly(key) if err != nil { t.Fatalf("NewChachaPoly(keySize=%v) failed, err: %v", Chacha20Poly1305KeySize, err) } // Construct nonce with invalid size. nonce := make([]byte, 1) if _, err = crypter.Encrypt(nil, nil, nonce, nil); err == nil { t.Errorf("Encrypt should fail due to invalid nonce size") } if _, err = crypter.Decrypt(nil, nil, nonce, nil); err == nil { t.Fatalf("Decrypt should fail due to invalid nonce size") } } // Test encrypt and decrypt on roundtrip messages for Chacha-Poly. func TestChachaPolyEncryptRoundtrip(t *testing.T) { for _, keySize := range []int{Chacha20Poly1305KeySize} { t.Run(fmt.Sprintf("keySize=%d", keySize), func(t *testing.T) { key := make([]byte, keySize) sender, receiver := getChachaPolyCrypterPair(key, t) testChachaPolyEncryptRoundtrip(sender, receiver, t) }) } } func TestWycheProofTestVectorsChachaPoly(t *testing.T) { for _, tc := range testutil.ParseWycheProofTestVectors("testdata/chacha_poly_wycheproof.json", wycheProofTestVectorFilter, t) { t.Run(fmt.Sprintf("%d/%s", tc.ID, tc.Desc), func(t *testing.T) { // Test encryption and decryption for CHACHA-POLY. sender, receiver := getChachaPolyCrypterPair(tc.Key, t) testChachaPolyEncryptionDecryption(sender, receiver, &tc, t) }) } } // Test ChachaPoly with RFC test vectors. func TestChachaPolyRFC(t *testing.T) { for _, tc := range []testutil.CryptoTestVector{ { Desc: "RFC test vector 1", Key: testutil.Dehex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"), Nonce: testutil.Dehex("070000004041424344454647"), Aad: testutil.Dehex("50515253c0c1c2c3c4c5c6c7"), Plaintext: testutil.Dehex("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e"), Ciphertext: testutil.Dehex("d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691"), Result: testutil.ValidResult, }, { Desc: "RFC test vector 2", Key: testutil.Dehex("1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0"), Nonce: testutil.Dehex("000000000102030405060708"), Aad: testutil.Dehex("f33388860000000000004e91"), Plaintext: testutil.Dehex("496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d"), Ciphertext: testutil.Dehex("64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38"), Result: testutil.ValidResult, }, } { t.Run(fmt.Sprintf("%s", tc.Desc), func(t *testing.T) { // Test encryption and decryption for Chacha-Poly. sender, receiver := getChachaPolyCrypterPair(tc.Key, t) testChachaPolyEncryptionDecryption(sender, receiver, &tc, t) }) } } s2a-go-0.1.8/internal/record/internal/aeadcrypter/common.go000066400000000000000000000067341464711036600236620ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter import ( "crypto/cipher" "fmt" ) const ( // TagSize is the tag size in bytes for AES-128-GCM-SHA256, // AES-256-GCM-SHA384, and CHACHA20-POLY1305-SHA256. TagSize = 16 // NonceSize is the size of the nonce in number of bytes for // AES-128-GCM-SHA256, AES-256-GCM-SHA384, and CHACHA20-POLY1305-SHA256. NonceSize = 12 // SHA256DigestSize is the digest size of sha256 in bytes. SHA256DigestSize = 32 // SHA384DigestSize is the digest size of sha384 in bytes. SHA384DigestSize = 48 ) // sliceForAppend takes a slice and a requested number of bytes. It returns a // slice with the contents of the given slice followed by that many bytes and a // second slice that aliases into it and contains only the extra bytes. If the // original slice has sufficient capacity then no allocation is performed. func sliceForAppend(in []byte, n int) (head, tail []byte) { if total := len(in) + n; cap(in) >= total { head = in[:total] } else { head = make([]byte, total) copy(head, in) } tail = head[len(in):] return head, tail } // encrypt is the encryption function for an AEAD crypter. aead determines // the type of AEAD crypter. dst can contain bytes at the beginning of the // ciphertext that will not be encrypted but will be authenticated. If dst has // enough capacity to hold these bytes, the ciphertext and the tag, no // allocation and copy operations will be performed. dst and plaintext may // fully overlap or not at all. func encrypt(aead cipher.AEAD, dst, plaintext, nonce, aad []byte) ([]byte, error) { if len(nonce) != NonceSize { return nil, fmt.Errorf("nonce size must be %d bytes. received: %d", NonceSize, len(nonce)) } // If we need to allocate an output buffer, we want to include space for // the tag to avoid forcing the caller to reallocate as well. dlen := len(dst) dst, out := sliceForAppend(dst, len(plaintext)+TagSize) data := out[:len(plaintext)] copy(data, plaintext) // data may fully overlap plaintext // Seal appends the ciphertext and the tag to its first argument and // returns the updated slice. However, sliceForAppend above ensures that // dst has enough capacity to avoid a reallocation and copy due to the // append. dst = aead.Seal(dst[:dlen], nonce, data, aad) return dst, nil } // decrypt is the decryption function for an AEAD crypter, where aead determines // the type of AEAD crypter, and dst the destination bytes for the decrypted // ciphertext. The dst buffer may fully overlap with plaintext or not at all. func decrypt(aead cipher.AEAD, dst, ciphertext, nonce, aad []byte) ([]byte, error) { if len(nonce) != NonceSize { return nil, fmt.Errorf("nonce size must be %d bytes. received: %d", NonceSize, len(nonce)) } // If dst is equal to ciphertext[:0], ciphertext storage is reused. plaintext, err := aead.Open(dst, nonce, ciphertext, aad) if err != nil { return nil, fmt.Errorf("message auth failed: %v", err) } return plaintext, nil } s2a-go-0.1.8/internal/record/internal/aeadcrypter/common_test.go000066400000000000000000000077651464711036600247260ustar00rootroot00000000000000/* * * Copyright 2021 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 aeadcrypter import ( "bytes" "testing" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) // fakeAEAD is a fake implementation of an AEAD interface used for testing. type fakeAEAD struct{} func (*fakeAEAD) NonceSize() int { return NonceSize } func (*fakeAEAD) Overhead() int { return TagSize } func (*fakeAEAD) Seal(_, _, plaintext, _ []byte) []byte { return plaintext } func (*fakeAEAD) Open(_, _, ciphertext, _ []byte) ([]byte, error) { return ciphertext, nil } type encryptDecryptTestVector struct { desc string nonce []byte outErr bool } func TestSliceForAppend(t *testing.T) { for _, tc := range []struct { desc string inBuf []byte n int }{ { desc: "nil buf and zero length", }, { desc: "nil buf and non-zero length", n: 5, }, { desc: "non-empty buf and zero length", inBuf: testutil.Dehex("1111111111"), }, { desc: "non-empty buf and non-zero length", inBuf: testutil.Dehex("1111111111"), n: 5, }, { desc: "test slice capacity pre allocated", inBuf: make([]byte, 0, 5), n: 5, }, } { t.Run(tc.desc, func(t *testing.T) { head, tail := sliceForAppend(tc.inBuf, tc.n) // Check that the resulting head buffer starts with the same byte // sequence as the input buffer. if got, want := head, tc.inBuf; !bytes.HasPrefix(head, tc.inBuf) { t.Errorf("sliceForAppend(%v, %v).head = %v, want %v", tc.inBuf, tc.n, got, want) } // Check that the length of the resulting head buffer is equal // to the initial buffer + the additional length requested. if got, want := len(head), len(tc.inBuf)+tc.n; got != want { t.Errorf("sliceForAppend(%v, %v).tail = %v, want %v", tc.inBuf, tc.n, got, want) } // Check that the length of the resulting tail buffer is what was // requested. if got, want := len(tail), tc.n; got != want { t.Errorf("sliceForAppend(%v, %v).tail = %v, want %v", tc.inBuf, tc.n, got, want) } }) } } func TestEncrypt(t *testing.T) { plaintext := []byte("test") for _, tc := range []encryptDecryptTestVector{ { desc: "valid nonce size", nonce: make([]byte, NonceSize), }, { desc: "invalid nonce size", nonce: make([]byte, 1), outErr: true, }, } { ciphertext, err := encrypt(&fakeAEAD{}, nil, plaintext, tc.nonce, nil) if got, want := err == nil, !tc.outErr; got != want { t.Fatalf("encrypt(&fakeAEAD{}, nil, %v, %v, nil)=(err=nil)=%v, want %v", plaintext, tc.nonce, got, want) } if got, want := ciphertext, plaintext; err == nil && !bytes.Equal(got, want) { t.Fatalf("encrypt(&fakeAEAD{}, nil, %v, %v, nil) = %v, want %v", plaintext, tc.nonce, got, want) } } } func TestDecrypt(t *testing.T) { ciphertext := []byte("test") for _, tc := range []encryptDecryptTestVector{ { desc: "valid nonce size", nonce: make([]byte, NonceSize), }, { desc: "invalid nonce size", nonce: make([]byte, 1), outErr: true, }, } { plaintext, err := decrypt(&fakeAEAD{}, nil, ciphertext, tc.nonce, nil) if got, want := err == nil, !tc.outErr; got != want { t.Fatalf("decrypt(&fakeAEAD{}, nil, %v, %v, nil)=(err=nil)=%v, want %v", ciphertext, tc.nonce, got, want) } if got, want := plaintext, ciphertext; err == nil && !bytes.Equal(got, want) { t.Fatalf("decrypt(&fakeAEAD{}, nil, %v, %v, nil) = %v, want %v", ciphertext, tc.nonce, got, want) } } } s2a-go-0.1.8/internal/record/internal/aeadcrypter/testdata/000077500000000000000000000000001464711036600236425ustar00rootroot00000000000000s2a-go-0.1.8/internal/record/internal/aeadcrypter/testdata/aes_gcm_wycheproof.json000066400000000000000000004045171464711036600304130ustar00rootroot00000000000000{ "algorithm" : "AES-GCM", "generatorVersion" : "0.8r12", "numberOfTests" : 256, "header" : [ "Test vectors of type AeadTest test authenticated encryption with", "additional data. The test vectors are intended for testing both", "encryption and decryption." ], "notes" : { "ConstructedIv" : "The counter for AES-GCM is reduced modulo 2**32. This test vector was constructed to test for correct wrapping of the counter.", "SmallIv" : "AES-GCM leaks the authentication key if the same IV is used twice. Hence short IV sizes are typically discouraged. This test vector uses an IV smaller than 12 bytes", "ZeroLengthIv" : "AES-GCM does not allow an IV of length 0. Encrypting with such an IV leaks the authentication key. Hence using an IV of length 0 is insecure even if the key itself is only used for a single encryption." }, "schema" : "aead_test_schema.json", "testGroups" : [ { "ivSize" : 96, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 1, "comment" : "", "key" : "5b9604fe14eadba931b0ccf34843dab9", "iv" : "028318abc1824029138141a2", "aad" : "", "msg" : "001d0c231287c1182784554ca3a21908", "ct" : "26073cc1d851beff176384dc9896d5ff", "tag" : "0a3ea7a5487cb5f7d70fb6c58d038554", "result" : "valid", "flags" : [] }, { "tcId" : 2, "comment" : "", "key" : "5b9604fe14eadba931b0ccf34843dab9", "iv" : "921d2507fa8007b7bd067d34", "aad" : "00112233445566778899aabbccddeeff", "msg" : "001d0c231287c1182784554ca3a21908", "ct" : "49d8b9783e911913d87094d1f63cc765", "tag" : "1e348ba07cca2cf04c618cb4d43a5b92", "result" : "valid", "flags" : [] }, { "tcId" : 3, "comment" : "", "key" : "aa023d0478dcb2b2312498293d9a9129", "iv" : "0432bc49ac34412081288127", "aad" : "aac39231129872a2", "msg" : "2035af313d1346ab00154fea78322105", "ct" : "eea945f3d0f98cc0fbab472a0cf24e87", "tag" : "4bb9b4812519dadf9e1232016d068133", "result" : "valid", "flags" : [] }, { "tcId" : 4, "comment" : "", "key" : "bedcfb5a011ebc84600fcb296c15af0d", "iv" : "438a547a94ea88dce46c6c85", "aad" : "", "msg" : "", "ct" : "", "tag" : "960247ba5cde02e41a313c4c0136edc3", "result" : "valid", "flags" : [] }, { "tcId" : 5, "comment" : "", "key" : "384ea416ac3c2f51a76e7d8226346d4e", "iv" : "b30c084727ad1c592ac21d12", "aad" : "", "msg" : "35", "ct" : "54", "tag" : "7c1e4ae88bb27e5638343cb9fd3f6337", "result" : "valid", "flags" : [] }, { "tcId" : 6, "comment" : "", "key" : "cae31cd9f55526eb038241fc44cac1e5", "iv" : "b5e006ded553110e6dc56529", "aad" : "", "msg" : "d10989f2c52e94ad", "ct" : "a036ead03193903f", "tag" : "3b626940e0e9f0cbea8e18c437fd6011", "result" : "valid", "flags" : [] }, { "tcId" : 7, "comment" : "", "key" : "dd6197cd63c963919cf0c273ef6b28bf", "iv" : "ecb0c42f7000ef0e6f95f24d", "aad" : "", "msg" : "4dcc1485365866e25ac3f2ca6aba97", "ct" : "8a9992388e735f80ee18f4a63c10ad", "tag" : "1486a91cccf92c9a5b00f7b0e034891c", "result" : "valid", "flags" : [] }, { "tcId" : 8, "comment" : "", "key" : "ffdf4228361ea1f8165852136b3480f7", "iv" : "0e1666f2dc652f7708fb8f0d", "aad" : "", "msg" : "25b12e28ac0ef6ead0226a3b2288c800", "ct" : "f7bd379d130477176b8bb3cb23dbbbaa", "tag" : "1ee6513ce30c7873f59dd4350a588f42", "result" : "valid", "flags" : [] }, { "tcId" : 9, "comment" : "", "key" : "c15ed227dd2e237ecd087eaaaad19ea4", "iv" : "965ff6643116ac1443a2dec7", "aad" : "", "msg" : "fee62fde973fe025ad6b322dcdf3c63fc7", "ct" : "0de51fe4f7f2d1f0f917569f5c6d1b009c", "tag" : "6cd8521422c0177e83ef1b7a845d97db", "result" : "valid", "flags" : [] }, { "tcId" : 10, "comment" : "", "key" : "a8ee11b26d7ceb7f17eaa1e4b83a2cf6", "iv" : "fbbc04fd6e025b7193eb57f6", "aad" : "", "msg" : "c08f085e6a9e0ef3636280c11ecfadf0c1e72919ffc17eaf", "ct" : "7cd9f4e4f365704fff3b9900aa93ba54b672bac554275650", "tag" : "f4eb193241226db017b32ec38ca47217", "result" : "valid", "flags" : [] }, { "tcId" : 11, "comment" : "", "key" : "28ff3def08179311e2734c6d1c4e2871", "iv" : "32bcb9b569e3b852d37c766a", "aad" : "c3", "msg" : "dfc61a20df8505b53e3cd59f25770d5018add3d6", "ct" : "f58d453212c2c8a436e9283672f579f119122978", "tag" : "5901131d0760c8715901d881fdfd3bc0", "result" : "valid", "flags" : [] }, { "tcId" : 12, "comment" : "", "key" : "e63a43216c08867210e248859eb5e99c", "iv" : "9c3a4263d983456658aad4b1", "aad" : "834afdc5c737186b", "msg" : "b14da56b0462dc05b871fc815273ff4810f92f4b", "ct" : "bf864616c2347509ca9b10446379b9bdbb3b8f64", "tag" : "a97d25b490390b53c5db91f6ee2a15b8", "result" : "valid", "flags" : [] }, { "tcId" : 13, "comment" : "", "key" : "38449890234eb8afab0bbf82e2385454", "iv" : "33e90658416e7c1a7c005f11", "aad" : "4020855c66ac4595058395f367201c4c", "msg" : "f762776bf83163b323ca63a6b3adeac1e1357262", "ct" : "a6f2ef3c7ef74a126dd2d5f6673964e27d5b34b6", "tag" : "b8bbdc4f5014bc752c8b4e9b87f650a3", "result" : "valid", "flags" : [] }, { "tcId" : 14, "comment" : "", "key" : "6a68671dfe323d419894381f85eb63fd", "iv" : "9f0d85b605711f34cd2a35ba", "aad" : "76eb5f147250fa3c12bff0a6e3934a0b16860cf11646773b", "msg" : "0fc67899c3f1bbe196d90f1eca3797389230aa37", "ct" : "bd64802cfebaeb487d3a8f76ce943a37b3472dd5", "tag" : "fce9a5b530c7d7af718be1ec0ae9ed4d", "result" : "valid", "flags" : [] }, { "tcId" : 15, "comment" : "", "key" : "e12260fcd355a51a0d01bb1f6fa538c2", "iv" : "5dfc37366f5688275147d3f9", "aad" : "", "msg" : "d902deeab175c008329a33bfaccd5c0eb3a6a152a1510e7db04fa0aff7ce4288530db6a80fa7fea582aa7d46d7d56e708d2bb0c5edd3d26648d336c3620ea55e", "ct" : "d33bf6722fc29384fad75f990248b9528e0959aa67ec66869dc3996c67a2d559e7d77ce5955f8cad2a4df5fdc3acccafa7bc0def53d848111256903e5add0420", "tag" : "8bc833de510863b4b432c3cbf45aa7cc", "result" : "valid", "flags" : [] }, { "tcId" : 16, "comment" : "", "key" : "3c55f88e9faa0d68ab50d02b47161276", "iv" : "d767c48d2037b4bd2c231bbd", "aad" : "", "msg" : "5d6add48e7a5704e54f9c2829a9b4283dce0d3a65b133eba3793c4fbfa1d8e3a2539d0d4f3de381598ce5b2360173fbd149476c31692c5d6e872fce40219378949c2e70b5f1b9f0a1d5f38352ad814b2a035bb3f3f26425d831a2f7a5e65c5dfcd91a315c2b24f53a662605ea40857dd980e9be5cdad000c569f2d204d4bd3b0", "ct" : "17d72d90bd23e076d8364a87ecb9ac58acc5de4629bfd590409b8bf1fcd3a2f602731b4614cec15e773ea65a65e7210994256bf5450a25acb527269c065f2e2f2279d1fe8b3eda98dcf87b348f1528377bbdd258355d46e035330483d8097e80c7de9bbb606ddf723f2909217ffdd18e8bdbd7b08062f1dcba960e5c0d290f5f", "tag" : "090b8c2ec98e4116186d0e5fbefeb9c2", "result" : "valid", "flags" : [] }, { "tcId" : 17, "comment" : "", "key" : "a294e70fa2ac10a1fb00c588b888b673", "iv" : "dfe20d1c4350e6235d987af1", "aad" : "", "msg" : "6ed1d7d618d158741f52078006f28494ba72a2454f27160ae8722793fcebc538ebc2f67c3ace3e0fe7c47b9e74e081182b47c930144e3fc80d0ad50611c3afcfe2dbc5279edbbba087c0e390355f3daffcd25ad4dea007c284ad92e7fcbecb438fb60623ff89a599dca2aac141b26651386ca55b739b94901ef6db609c344d8acf4544568e31bb09361112754b1c0c6a3c875bd9453b0ee0081412151398a294ecad75add521611db5288b60ac3c0128f6e94366b69e659e6aa66f058a3a3571064edbb0f05c11e5dde938fb46c3935dd5193a4e5664688f0ae67c29b7cc49a7963140f82e311a20c98cd34fbcab7b4b515ae86557e62099e3fc37b9595c85a75c", "ct" : "5bc6dbafc401101c7a08c81d6c2791aa147ce093aad172be18379c747384a54a41a747ba955cade8fdfb8967aa808b43fee3d757cc80f11163b800e5e59df932757f76c40b3d9cba449aaf11e4f80e003b1f384eafa4f76e81b13c09ec1ad88e7650c750d442fe46d225a373e8a1b564b4915a5c6c513cfdfa22d929d5741ca5ebefaedcba636c7c3bbef18863fdc126b4b451611049c35d814fc2eb7e4b8f1a8995ecb4a3c86652a068c0b2a3e1c5941d59c210b458d5d5d3b06420ec2053465ccceca7c20f67404985460379e2ee806a46e8409dfab2e0dd67ea3cf46d5ad4eb78756827358c3ef1fdbd07c33834f3d9eca3ff13b744a01059a6c17a315a8fd4", "tag" : "c7587e7da41bed682c37377ea4324029", "result" : "valid", "flags" : [] }, { "tcId" : 18, "comment" : "", "key" : "c4b03435b91fc52e09eff27e4dc3fb42", "iv" : "5046e7e08f0747e1efccb09e", "aad" : "75fc9078b488e9503dcb568c882c9eec24d80b04f0958c82aac8484f025c90434148db8e9bfe29c7e071b797457cb1695a5e5a6317b83690ba0538fb11e325ca", "msg" : "8e887b224e8b89c82e9a641cf579e6879e1111c7", "ct" : "b6786812574a254eb43b1cb1d1753564c6b520e9", "tag" : "ad8c09610d508f3d0f03cc523c0d5fcc", "result" : "valid", "flags" : [] }, { "tcId" : 19, "comment" : "", "key" : "7e37d56e6b1d0172d40d64d6111dd424", "iv" : "517c55c2ec9bfea90addc2bd", "aad" : "8ed8a9be4c3d32a5098434ee5c0c4fc20f78ef5e25ed8b72a840a463e36b67b881e048b5e49f515b2541ad5ce4ebb3a917c16bcdc0dc3cb52bb4ed5a1dffcf1e1866544e8db103b2ad99c6fa6e7de1d8b45bff57ec872f1cfc78b0e4870f6f200ff1291cae033defc3327ba82792ba438e35c4bfbb684fec5ce5e3ae167d01d7", "msg" : "6a7dea03c1bba70be8c73da47d5ee06d72a27430", "ct" : "cfb631790767d0645d8ec6f23bf7fa8b19ce79ee", "tag" : "c5767ddaa747158446231766bd20490c", "result" : "valid", "flags" : [] }, { "tcId" : 20, "comment" : "", "key" : "3076741408f734ce25d48f982e8b844b", "iv" : "a2712eac5e06d3cc2864aa8b", "aad" : "18526e4efd995a0bf6405d9f906725c290278958d49554974d8fe025e7860daa225c1285b0573916a4b6741f7cc2e29ce4e525e12f436cb7ce0ad47df3d0f5bd80fb27e47635a4985fdaedf0e821f1c8959985cac49c97a4a02438d92b4afd4c855dcc7ef41ecfc36866334fcc05b2bb93ef13f00c5ea9b921e8a519d77f648e0efe9b5a62305a2ecf7d4999663a6ddfca517f1f36f0899b0bdef9f433c4bb2663c0cc1bb616e7d1949e522bec85485d371d1134c90eede75e865dc7be405b54c33f0acbace6cf780c78035b8035b6ea3f562a8d30a156c199fdafd25be06ee895581195ef125cb4e629e4f18e0bee979d31513896db8466e448e6b4600a316757", "msg" : "414ec6b149e54735302dada888b98b7fdb4c127c", "ct" : "e4d3f4898cb3d9732641d1f8d9d889b2c98af930", "tag" : "76d4fbb69d529b64175b328be00b1068", "result" : "valid", "flags" : [] }, { "tcId" : 21, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff", "iv" : "000000000000000000000000", "aad" : "", "msg" : "ebd4a3e10cf6d41c50aeae007563b072", "ct" : "f62d84d649e56bc8cfedc5d74a51e2f7", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] }, { "tcId" : 22, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff", "iv" : "ffffffffffffffffffffffff", "aad" : "", "msg" : "d593c4d8224f1b100c35e4f6c4006543", "ct" : "431f31e6840931fd95f94bf88296ff69", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 23, "comment" : "Flipped bit 0 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d9847dbc326a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 24, "comment" : "Flipped bit 1 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "da847dbc326a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 25, "comment" : "Flipped bit 7 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "58847dbc326a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 26, "comment" : "Flipped bit 8 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8857dbc326a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 27, "comment" : "Flipped bit 31 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847d3c326a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 28, "comment" : "Flipped bit 32 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc336a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 29, "comment" : "Flipped bit 33 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc306a06e988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 30, "comment" : "Flipped bit 63 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a066988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 31, "comment" : "Flipped bit 64 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e989c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 32, "comment" : "Flipped bit 71 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e908c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 33, "comment" : "Flipped bit 77 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988e77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 34, "comment" : "Flipped bit 80 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77bd3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 35, "comment" : "Flipped bit 96 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3873e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 36, "comment" : "Flipped bit 97 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3843e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 37, "comment" : "Flipped bit 103 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3063e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 38, "comment" : "Flipped bit 120 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3863e6082", "result" : "invalid", "flags" : [] }, { "tcId" : 39, "comment" : "Flipped bit 121 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3863e6081", "result" : "invalid", "flags" : [] }, { "tcId" : 40, "comment" : "Flipped bit 126 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3863e60c3", "result" : "invalid", "flags" : [] }, { "tcId" : 41, "comment" : "Flipped bit 127 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a06e988c77ad3863e6003", "result" : "invalid", "flags" : [] }, { "tcId" : 42, "comment" : "Flipped bits 0 and 64 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d9847dbc326a06e989c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 43, "comment" : "Flipped bits 31 and 63 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847d3c326a066988c77ad3863e6083", "result" : "invalid", "flags" : [] }, { "tcId" : 44, "comment" : "Flipped bits 63 and 127 in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d8847dbc326a066988c77ad3863e6003", "result" : "invalid", "flags" : [] }, { "tcId" : 45, "comment" : "all bits of tag flipped", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "277b8243cd95f9167738852c79c19f7c", "result" : "invalid", "flags" : [] }, { "tcId" : 46, "comment" : "Tag changed to all zero", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "00000000000000000000000000000000", "result" : "invalid", "flags" : [] }, { "tcId" : 47, "comment" : "tag changed to all 1", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "invalid", "flags" : [] }, { "tcId" : 48, "comment" : "msbs changed in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "5804fd3cb2ea86690847fa5306bee003", "result" : "invalid", "flags" : [] }, { "tcId" : 49, "comment" : "lsbs changed in tag", "key" : "000102030405060708090a0b0c0d0e0f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "eb156d081ed6b6b55f4612f021d87b39", "tag" : "d9857cbd336b07e889c67bd2873f6182", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 64, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 50, "comment" : "", "key" : "aa023d0478dcb2b2312498293d9a9129", "iv" : "0432bc49ac344120", "aad" : "aac39231129872a2", "msg" : "2035af313d1346ab00154fea78322105", "ct" : "64c36bb3b732034e3a7d04efc5197785", "tag" : "b7d0dd70b00d65b97cfd080ff4b819d1", "result" : "valid", "flags" : [] }, { "tcId" : 51, "comment" : "small IV sizes", "key" : "f3434725c82a7f8bb07df1f8122fb6c9", "iv" : "28e9b7851724bae3", "aad" : "", "msg" : "", "ct" : "", "tag" : "44aca00f42e4199b829a55e69b073d9e", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 52, "comment" : "small IV sizes", "key" : "deb62233559b57476602b5adac57c77f", "iv" : "d084547de55bbc15", "aad" : "", "msg" : "d8986df0241ed3297582c0c239c724cb", "ct" : "03e1a168a7e377a913879b296a1b5f9c", "tag" : "3290aa95af505a742f517fabcc9b2094", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 128, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 53, "comment" : "", "key" : "2034a82547276c83dd3212a813572bce", "iv" : "3254202d854734812398127a3d134421", "aad" : "1a0293d8f90219058902139013908190bc490890d3ff12a3", "msg" : "02efd2e5782312827ed5d230189a2a342b277ce048462193", "ct" : "64069c2d58690561f27ee199e6b479b6369eec688672bde9", "tag" : "9b7abadd6e69c1d9ec925786534f5075", "result" : "valid", "flags" : [] }, { "tcId" : 54, "comment" : "", "key" : "b67b1a6efdd40d37080fbe8f8047aeb9", "iv" : "fa294b129972f7fc5bbd5b96bba837c9", "aad" : "", "msg" : "", "ct" : "", "tag" : "a2cf26481517ec25085c5b17d0786183", "result" : "valid", "flags" : [] }, { "tcId" : 55, "comment" : "", "key" : "209e6dbf2ad26a105445fc0207cd9e9a", "iv" : "9477849d6ccdfca112d92e53fae4a7ca", "aad" : "", "msg" : "01", "ct" : "fd", "tag" : "032df7bba5d8ea1a14f16f70bd0e14ec", "result" : "valid", "flags" : [] }, { "tcId" : 56, "comment" : "", "key" : "a549442e35154032d07c8666006aa6a2", "iv" : "5171524568e81d97e8c4de4ba56c10a0", "aad" : "", "msg" : "1182e93596cac5608946400bc73f3a", "ct" : "2f333087bdca58219f9bfc273e45cc", "tag" : "e06d1ef473132957ad37eaef29733ca0", "result" : "valid", "flags" : [] }, { "tcId" : 57, "comment" : "", "key" : "cfb4c26f126f6a0acb8e4e220f6c56cd", "iv" : "1275115499ae722268515bf0c164b49c", "aad" : "", "msg" : "09dfd7f080275257cf97e76f966b1ad9", "ct" : "a780bd01c80885156c88a973264c8ee5", "tag" : "2adeffa682c8d8a81fada7d9fcdd2ee2", "result" : "valid", "flags" : [] }, { "tcId" : 58, "comment" : "", "key" : "0b11ef3a08c02970f74281c860691c75", "iv" : "95c1dd8c0f1705ece68937901f7add7b", "aad" : "", "msg" : "f693d4edd825dbb0618d91113128880dbebb23e25d00ed1f077d870be9cc7536", "ct" : "7e47e10fe3c6fbfa381770eaf5d48d1482e71e0c44dff1e30ca6f95d92052084", "tag" : "d01444fa5d9c499629d174ff3927a1ac", "result" : "valid", "flags" : [] }, { "tcId" : 59, "comment" : "J0:000102030405060708090a0b0c0d0e0f", "key" : "00112233445566778899aabbccddeeff", "iv" : "f95fde4a751913202aeeee32a0b55753", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "00078d109d92143fcd5df56721b884fac64ac7762cc09eea2a3c68e92a17bdb575f87bda18be564e", "tag" : "152a65045fe674f97627427af5be22da", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 60, "comment" : "J0:00000000000000000000000000000000", "key" : "00112233445566778899aabbccddeeff", "iv" : "7b95b8c356810a84711d68150a1b7750", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "84d4c9c08b4f482861e3a9c6c35bc4d91df927374513bfd49f436bd73f325285daef4ff7e13d46a6", "tag" : "213a3cb93855d18e69337eee66aeec07", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 61, "comment" : "J0:ffffffffffffffffffffffffffffffff", "key" : "00112233445566778899aabbccddeeff", "iv" : "1a552e67cdc4dc1a33b824874ebf0bed", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "948ca37a8e6649e88aeffb1c598f3607007702417ea0e0bc3c60ad5a949886de968cf53ea6462aed", "tag" : "99b381bfa2af9751c39d1b6e86d1be6a", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 62, "comment" : "J0:fffffffffffffffffffffffffffffffe", "key" : "00112233445566778899aabbccddeeff", "iv" : "dd9d0b4a0c3d681524bffca31d907661", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "64b19314c31af45accdf7e3c4db79f0d948ca37a8e6649e88aeffb1c598f3607007702417ea0e0bc", "tag" : "5281efc7f13ac8e14ccf5dca7bfbfdd1", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 63, "comment" : "J0:fffffffffffffffffffffffffffffffd", "key" : "00112233445566778899aabbccddeeff", "iv" : "57c5643c4e37b4041db794cfe8e1f0f4", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "2bb69c3e5d1f91815c6b87a0d5bbea7164b19314c31af45accdf7e3c4db79f0d948ca37a8e6649e8", "tag" : "a3ea2c09ee4f8c8a12f45cddf9aeff81", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 64, "comment" : "J0:000102030405060708090a0bffffffff", "key" : "00112233445566778899aabbccddeeff", "iv" : "99821c2dd5daecded07300f577f7aff1", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4af37d0fe9af033052bd537c4ae978f60", "tag" : "07eb2fe4a958f8434d40684899507c7c", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 65, "comment" : "J0:000102030405060708090a0bfffffffe", "key" : "00112233445566778899aabbccddeeff", "iv" : "5e4a3900142358d1c774d8d124d8d27d", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "0cf6ae47156b14dce03c8a07a2e172b1127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4", "tag" : "f145c2dcaf339eede427be934357eac0", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 66, "comment" : "J0:000102030405060708090a0bfffffffd", "key" : "00112233445566778899aabbccddeeff", "iv" : "d4125676562984c0fe7cb0bdd1a954e8", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "f0c6ffc18bd46df5569185a9afd169eb0cf6ae47156b14dce03c8a07a2e172b1127af9b39ecdfc57", "tag" : "facd0bfe8701b7b4a2ba96d98af52bd9", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 67, "comment" : "J0:000102030405060708090a0b7fffffff", "key" : "00112233445566778899aabbccddeeff", "iv" : "b97ec62a5e5900ccf9e4be332e336091", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "d6928e094c06e0a7c4db42184cf7529e95de88b767edebe9b343000be3dab47ea08b744293eed698", "tag" : "a03e729dcfd7a03155655fece8affd7e", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 68, "comment" : "J0:000102030405060708090a0b7ffffffe", "key" : "00112233445566778899aabbccddeeff", "iv" : "7eb6e3079fa0b4c3eee366177d1c1d1d", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "d82ce58771bf6487116bf8e96421877ed6928e094c06e0a7c4db42184cf7529e95de88b767edebe9", "tag" : "1e43926828bc9a1614c7b1639096c195", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 69, "comment" : "J0:000102030405060708090a0bffff7fff", "key" : "00112233445566778899aabbccddeeff", "iv" : "0314fcd10fdd675d3c612962c931f635", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "a197a37a5d79697078536bc27fe46cd8d475526d9044aa94f088a054f8e380c64f79414795c61480", "tag" : "f08baddf0b5285c91fc06a67fe4708ca", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 70, "comment" : "J0:000102030405060708090a0bffff7ffe", "key" : "00112233445566778899aabbccddeeff", "iv" : "c4dcd9fcce24d3522b66f1469a1e8bb9", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "149fde9abbd3a43c2548575e0db9fb84a197a37a5d79697078536bc27fe46cd8d475526d9044aa94", "tag" : "62a4b6875c288345d6a454399eac1afa", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 71, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff", "iv" : "00000000000000000000000000000000", "aad" : "", "msg" : "bec6fa05c1718b9b84c47345bbed7dcb", "ct" : "45a3f89d02918bfd0c8161658ccc9795", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 72, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff", "iv" : "ffffffffffffffffffffffffffffffff", "aad" : "", "msg" : "4d82639c39d3f3490ee903dd0be7afcf", "ct" : "1cd5a06214235ceb044d4bad7b047312", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 96, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 73, "comment" : "", "key" : "92ace3e348cd821092cd921aa3546374299ab46209691bc28b8752d17f123c20", "iv" : "00112233445566778899aabb", "aad" : "00000000ffffffff", "msg" : "00010203040506070809", "ct" : "e27abdd2d2a53d2f136b", "tag" : "9a4a2579529301bcfb71c78d4060f52c", "result" : "valid", "flags" : [] }, { "tcId" : 74, "comment" : "", "key" : "29d3a44f8723dc640239100c365423a312934ac80239212ac3df3421a2098123", "iv" : "00112233445566778899aabb", "aad" : "aabbccddeeff", "msg" : "", "ct" : "", "tag" : "2a7d77fa526b8250cb296078926b5020", "result" : "valid", "flags" : [] }, { "tcId" : 75, "comment" : "", "key" : "80ba3192c803ce965ea371d5ff073cf0f43b6a2ab576b208426e11409c09b9b0", "iv" : "4da5bf8dfd5852c1ea12379d", "aad" : "", "msg" : "", "ct" : "", "tag" : "4771a7c404a472966cea8f73c8bfe17a", "result" : "valid", "flags" : [] }, { "tcId" : 76, "comment" : "", "key" : "cc56b680552eb75008f5484b4cb803fa5063ebd6eab91f6ab6aef4916a766273", "iv" : "99e23ec48985bccdeeab60f1", "aad" : "", "msg" : "2a", "ct" : "06", "tag" : "633c1e9703ef744ffffb40edf9d14355", "result" : "valid", "flags" : [] }, { "tcId" : 77, "comment" : "", "key" : "51e4bf2bad92b7aff1a4bc05550ba81df4b96fabf41c12c7b00e60e48db7e152", "iv" : "4f07afedfdc3b6c2361823d3", "aad" : "", "msg" : "be3308f72a2c6aed", "ct" : "cf332a12fdee800b", "tag" : "602e8d7c4799d62c140c9bb834876b09", "result" : "valid", "flags" : [] }, { "tcId" : 78, "comment" : "", "key" : "67119627bd988eda906219e08c0d0d779a07d208ce8a4fe0709af755eeec6dcb", "iv" : "68ab7fdbf61901dad461d23c", "aad" : "", "msg" : "51f8c1f731ea14acdb210a6d973e07", "ct" : "43fc101bff4b32bfadd3daf57a590e", "tag" : "ec04aacb7148a8b8be44cb7eaf4efa69", "result" : "valid", "flags" : [] }, { "tcId" : 79, "comment" : "", "key" : "59d4eafb4de0cfc7d3db99a8f54b15d7b39f0acc8da69763b019c1699f87674a", "iv" : "2fcb1b38a99e71b84740ad9b", "aad" : "", "msg" : "549b365af913f3b081131ccb6b825588", "ct" : "f58c16690122d75356907fd96b570fca", "tag" : "28752c20153092818faba2a334640d6e", "result" : "valid", "flags" : [] }, { "tcId" : 80, "comment" : "", "key" : "3b2458d8176e1621c0cc24c0c0e24c1e80d72f7ee9149a4b166176629616d011", "iv" : "45aaa3e5d16d2d42dc03445d", "aad" : "", "msg" : "3ff1514b1c503915918f0c0c31094a6e1f", "ct" : "73a6b6f45f6ccc5131e07f2caa1f2e2f56", "tag" : "2d7379ec1db5952d4e95d30c340b1b1d", "result" : "valid", "flags" : [] }, { "tcId" : 81, "comment" : "", "key" : "0212a8de5007ed87b33f1a7090b6114f9e08cefd9607f2c276bdcfdbc5ce9cd7", "iv" : "e6b1adf2fd58a8762c65f31b", "aad" : "", "msg" : "10f1ecf9c60584665d9ae5efe279e7f7377eea6916d2b111", "ct" : "0843fff52d934fc7a071ea62c0bd351ce85678cde3ea2c9e", "tag" : "7355fde599006715053813ce696237a8", "result" : "valid", "flags" : [] }, { "tcId" : 82, "comment" : "", "key" : "b279f57e19c8f53f2f963f5f2519fdb7c1779be2ca2b3ae8e1128b7d6c627fc4", "iv" : "98bc2c7438d5cd7665d76f6e", "aad" : "c0", "msg" : "fcc515b294408c8645c9183e3f4ecee5127846d1", "ct" : "eb5500e3825952866d911253f8de860c00831c81", "tag" : "ecb660e1fb0541ec41e8d68a64141b3a", "result" : "valid", "flags" : [] }, { "tcId" : 83, "comment" : "", "key" : "cdccfe3f46d782ef47df4e72f0c02d9c7f774def970d23486f11a57f54247f17", "iv" : "376187894605a8d45e30de51", "aad" : "956846a209e087ed", "msg" : "e28e0e9f9d22463ac0e42639b530f42102fded75", "ct" : "feca44952447015b5df1f456df8ca4bb4eee2ce2", "tag" : "082e91924deeb77880e1b1c84f9b8d30", "result" : "valid", "flags" : [] }, { "tcId" : 84, "comment" : "", "key" : "f32364b1d339d82e4f132d8f4a0ec1ff7e746517fa07ef1a7f422f4e25a48194", "iv" : "5a86a50a0e8a179c734b996d", "aad" : "ab2ac7c44c60bdf8228c7884adb20184", "msg" : "43891bccb522b1e72a6b53cf31c074e9d6c2df8e", "ct" : "43dda832e942e286da314daa99bef5071d9d2c78", "tag" : "c3922583476ced575404ddb85dd8cd44", "result" : "valid", "flags" : [] }, { "tcId" : 85, "comment" : "", "key" : "ff0089ee870a4a39f645b0a5da774f7a5911e9696fc9cad646452c2aa8595a12", "iv" : "bc2a7757d0ce2d8b1f14ccd9", "aad" : "972ab4e06390caae8f99dd6e2187be6c7ff2c08a24be16ef", "msg" : "748b28031621d95ee61812b4b4f47d04c6fc2ff3", "ct" : "a929ee7e67c7a2f91bbcec6389a3caf43ab49305", "tag" : "ebec6774b955e789591c822dab739e12", "result" : "valid", "flags" : [] }, { "tcId" : 86, "comment" : "", "key" : "5b1d1035c0b17ee0b0444767f80a25b8c1b741f4b50a4d3052226baa1c6fb701", "iv" : "d61040a313ed492823cc065b", "aad" : "", "msg" : "d096803181beef9e008ff85d5ddc38ddacf0f09ee5f7e07f1e4079cb64d0dc8f5e6711cd4921a7887de76e2678fdc67618f1185586bfea9d4c685d50e4bb9a82", "ct" : "c7d191b601f86c28b6a1bdef6a57b4f6ee3ae417bc125c381cdf1c4dac184ed1d84f1196206d62cad112b038845720e02c061179a8836f02b93fa7008379a6bf", "tag" : "f15612f6c40f2e0db6dc76fc4822fcfe", "result" : "valid", "flags" : [] }, { "tcId" : 87, "comment" : "", "key" : "d7addd3889fadf8c893eee14ba2b7ea5bf56b449904869615bd05d5f114cf377", "iv" : "8a3ad26b28cd13ba6504e260", "aad" : "", "msg" : "c877a76bf595560772167c6e3bcc705305db9c6fcbeb90f4fea85116038bc53c3fa5b4b4ea0de5cc534fbe1cf9ae44824c6c2c0a5c885bd8c3cdc906f12675737e434b983e1e231a52a275db5fb1a0cac6a07b3b7dcb19482a5d3b06a9317a54826cea6b36fce452fa9b5475e2aaf25499499d8a8932a19eb987c903bd8502fe", "ct" : "53cc8c920a85d1accb88636d08bbe4869bfdd96f437b2ec944512173a9c0fe7a47f8434133989ba77dda561b7e3701b9a83c3ba7660c666ba59fef96598eb621544c63806d509ac47697412f9564eb0a2e1f72f6599f5666af34cffca06573ffb4f47b02f59f21c64363daecb977b4415f19fdda3c9aae5066a57b669ffaa257", "tag" : "5e63374b519e6c3608321943d790cf9a", "result" : "valid", "flags" : [] }, { "tcId" : 88, "comment" : "", "key" : "317ba331307f3a3d3d82ee1fdab70f62a155af14daf631307a61b187d413e533", "iv" : "a6687cf508356b174625deaa", "aad" : "", "msg" : "32c1d09107c599d3cce4e782179c966c6ef963689d45351dbe0f6f881db273e54db76fc48fdc5d30f089da838301a5f924bba3c044e19b3ed5aa6be87118554004ca30e0324337d987839412bf8f8bbdd537205d4b0e2120e965373235d6cbd2fb3776ba0a384ec1d9b7c631a0379ff997c3f974a6f7bbf4fd23016211f5fc10acadb5e400d2ff0fdfd193f5c6fc6d4f7271dfd1349ed80fbedaebb155b9b02fb3074495d55f9a2455f59bf6f113191a029c6b0ba75d97cdc0c84f131836337f29f9d96ca448eec0cc46d1ca8b3735661979d83302fec08fffcf5e58f12b1e7050657b1b97c64a4e07e317f554f8310b6ccb49f36d48c57816d24952aada711d4f", "ct" : "d7eebc9587aa21136fa38b41cf0e2db03a7ea2ba9eaddf83d33f781093617bf50f49b2bfe2f7173b113912e2e1775f40edfed8b3b0099b9e1c220dd103be6166210b01029feb24ed9e20614eddc3cebe41b0079a9a8c117b596c90288effd3796fbd0c7e8eab00609a64be3ad9597cdbf3a818c260cd938bdf232e4059ae35a2571a838887fc196912179486e046a62227a4caddce38cbbc37587bb9439ec637602b6818c5cbe3c71a7c4143960533dc74174bd315c8db227b69b55bb7fc30ba1d5213a752ec33925043cefbc1a62943ee5f34d5da01799e69094d732aef52f8e036980d0070e22e173c67c4bbcca61cc1eedbd6016516c592144819df13204dee", "tag" : "bf0540d34b20f761101bc608b02458f2", "result" : "valid", "flags" : [] }, { "tcId" : 89, "comment" : "", "key" : "2ce6b4c15f85fb2da5cc6c269491eef281980309181249ebf2832bd6d0732d0b", "iv" : "c064fae9173b173fd6f11f34", "aad" : "498d3075b09fed998280583d61bb36b6ce41f130063b80824d1586e143d349b126b16aa10fe57343ed223d6364ee602257fe313a7fc9bf9088f027795b8dc1d3", "msg" : "f8a27a4baf00dc0555d222f2fa4fb42dc666ea3c", "ct" : "aed58d8a252f740dba4bf6d36773bd5b41234bba", "tag" : "01f93d7456aa184ebb49bea472b6d65d", "result" : "valid", "flags" : [] }, { "tcId" : 90, "comment" : "", "key" : "44c8d0cdb8f7e736cfd997c872a5d9c5ef30afbe44b6566606b90aa5e3e8b797", "iv" : "6f39afba021e4c36eb92962e", "aad" : "98d1ca1788cbeb300ea5c6b1eec95eb2347177201400913d45225622b6273eec8a74c3f12c8d5248dabee586229786ff192c4df0c79547f7ad6a92d78d9f8952758635783add2a5977d386e0aef76482211d2c3ae98de4baadb3f8b35b510464755dc75ceb2bf25b233317523f399a6c507db214f085fa2818f0d3702b10952b", "msg" : "2e6f40f9d3725836ac0c858177938fd67be19432", "ct" : "b42428f8094ef7e65c9e8c45ef3e95c28ce07d72", "tag" : "32b25dfbb896d0f9d79c823bdd8e5d06", "result" : "valid", "flags" : [] }, { "tcId" : 91, "comment" : "", "key" : "e40003d6e08ab80b4bfc8400ef112945a901ec64a1b6536ca92665090d608bc4", "iv" : "9f095dafe6f6e0fbafbbe02e", "aad" : "422d5efcffe364905984533f0a579d80b18bda7b29e6e46498effba53c350112c0bbb8dc4ce03bb0c69e1d0baa19f0637108aa4a16b09a281f232839d87b6d0e42be1baa7c67f1be970ea169d3960b9fe0a61f11cd2eb7398c19e641feb43f778e257a397063db5b3a6707e9db62387054f9f9d44f143583e63edad45a00251e5173d7505f22a8bce232e56c2c276a58033ae30d5dbf4e35a862e42af573be38c6406d9b4c7acbf275fe36c0ecf2c4642898a30e6146fac992a16405f98312126b7a3722f5dfb7dd4e4911c1426b2e01d04e9be6db3771100f7d7d4282e4ea585f3646241e807ca64f06a7fa9b7003d710b801d66f517d2d5ebd740872deba13d0", "msg" : "38c3f44bc5765de1f3d1c3684cd09cddefaf298d", "ct" : "d4a79f729487935950ec032e690ab8fe25c4158e", "tag" : "876d2f334f47968b10c103859d436db8", "result" : "valid", "flags" : [] }, { "tcId" : 92, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "000000000000000000000000", "aad" : "", "msg" : "561008fa07a68f5c61285cd013464eaf", "ct" : "23293e9b07ca7d1b0cae7cc489a973b3", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] }, { "tcId" : 93, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "ffffffffffffffffffffffff", "aad" : "", "msg" : "c6152244cea1978d3e0bc274cf8c0b3b", "ct" : "7cb6fc7c6abc009efe9551a99f36a421", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 94, "comment" : "Flipped bit 0 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9de8fef6d8ab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 95, "comment" : "Flipped bit 1 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ee8fef6d8ab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 96, "comment" : "Flipped bit 7 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "1ce8fef6d8ab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 97, "comment" : "Flipped bit 8 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce9fef6d8ab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 98, "comment" : "Flipped bit 31 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fe76d8ab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 99, "comment" : "Flipped bit 32 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d9ab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 100, "comment" : "Flipped bit 33 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6daab1bf1bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 101, "comment" : "Flipped bit 63 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1b71bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 102, "comment" : "Flipped bit 64 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1be887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 103, "comment" : "Flipped bit 71 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf13f887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 104, "comment" : "Flipped bit 77 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bfa87232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 105, "comment" : "Flipped bit 80 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887332eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 106, "comment" : "Flipped bit 96 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887232ebb590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 107, "comment" : "Flipped bit 97 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887232e8b590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 108, "comment" : "Flipped bit 103 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf8872326ab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 109, "comment" : "Flipped bit 120 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887232eab590dc", "result" : "invalid", "flags" : [] }, { "tcId" : 110, "comment" : "Flipped bit 121 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887232eab590df", "result" : "invalid", "flags" : [] }, { "tcId" : 111, "comment" : "Flipped bit 126 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887232eab5909d", "result" : "invalid", "flags" : [] }, { "tcId" : 112, "comment" : "Flipped bit 127 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1bf1bf887232eab5905d", "result" : "invalid", "flags" : [] }, { "tcId" : 113, "comment" : "Flipped bits 0 and 64 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9de8fef6d8ab1bf1be887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 114, "comment" : "Flipped bits 31 and 63 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fe76d8ab1b71bf887232eab590dd", "result" : "invalid", "flags" : [] }, { "tcId" : 115, "comment" : "Flipped bits 63 and 127 in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9ce8fef6d8ab1b71bf887232eab5905d", "result" : "invalid", "flags" : [] }, { "tcId" : 116, "comment" : "all bits of tag flipped", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "631701092754e40e40778dcd154a6f22", "result" : "invalid", "flags" : [] }, { "tcId" : 117, "comment" : "Tag changed to all zero", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "00000000000000000000000000000000", "result" : "invalid", "flags" : [] }, { "tcId" : 118, "comment" : "tag changed to all 1", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "invalid", "flags" : [] }, { "tcId" : 119, "comment" : "msbs changed in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "1c687e76582b9b713f08f2b26a35105d", "result" : "invalid", "flags" : [] }, { "tcId" : 120, "comment" : "lsbs changed in tag", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "b2061457c0759fc1749f174ee1ccadfa", "tag" : "9de9fff7d9aa1af0be897333ebb491dc", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 128, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 121, "comment" : "J0:000102030405060708090a0b0c0d0e0f", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "029e0e777db092b12535d043012f09ba", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "f83cee467336e1a09b75f24e9b4385c99c13e6af722256a66129ece961fe803b167bad206f5017fb", "tag" : "09338a42f0acc14f97c064f52f5f1688", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 122, "comment" : "J0:00000000000000000000000000000000", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "f1be3b06b7feac07e7eab629f556047b", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "0b32b648a2c28e9edd7cee08eeeb900034cae7215e5ab1e201bd2eed1032c5a97866ba582a3458a4", "tag" : "90be3606de58bd778fa5beff4a4102bd", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 123, "comment" : "J0:ffffffffffffffffffffffffffffffff", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "de9eb63b1daed321a11b7547cc9e223c", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "575e2ecec2b3c72d4e80830d0d859ad9e42c29c4a68d8d9d8d23434de2cd07733be49d62ac1ae085", "tag" : "6e4d6396125a10df5443bd0cbc8566d1", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 124, "comment" : "J0:fffffffffffffffffffffffffffffffe", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "40bb0abebc483ff6d5671241ff5d66c6", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "2a818888d1f09f32aa7beedd2869b446575e2ecec2b3c72d4e80830d0d859ad9e42c29c4a68d8d9d", "tag" : "dc481f172545268eff63ab0490403dc3", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 125, "comment" : "J0:fffffffffffffffffffffffffffffffd", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "20d5cf305e630a8f49e3bb4bab18abc9", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "96d36b795f8e7edf6a8e0dbcd20d6c072a818888d1f09f32aa7beedd2869b446575e2ecec2b3c72d", "tag" : "8a3a22bf2592958b930292aa47f590e8", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 126, "comment" : "J0:000102030405060708090a0bffffffff", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "255358a71a0e5731f6dd6ce28e158ae6", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "cfce3d920f0e01f0bb49a751955b236d1b887baefd25c47f41303c46d5c7bf9ca4c2c45a8f1e6656", "tag" : "2db9dc1b7fd315df1c95432432fcf474", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 127, "comment" : "J0:000102030405060708090a0bfffffffe", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "bb76e422bbe8bbe682a10be4bdd6ce1c", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "69a24169792e9a07f6e6f4736fa972dccfce3d920f0e01f0bb49a751955b236d1b887baefd25c47f", "tag" : "82ad967f7ac19084354f69a751443fb2", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 128, "comment" : "J0:000102030405060708090a0bfffffffd", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "db1821ac59c38e9f1e25a2eee9930313", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "4e4417a83beac1eb7e24456a05f6ba5569a24169792e9a07f6e6f4736fa972dccfce3d920f0e01f0", "tag" : "472d5dd582dc05ef5fc496b612023cb2", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 129, "comment" : "J0:000102030405060708090a0b7fffffff", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "f7a02ecca03064b2ef3cce9feab79f07", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "6f8e174efca3097299f784efd4caff0bf168c3e5165b9ad3d20062009848044eef8f31f7d2fead05", "tag" : "caff723826df150934aee3201ba175e7", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 130, "comment" : "J0:000102030405060708090a0b7ffffffe", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "6985924901d688659b40a999d974dbfd", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "af193090ce3d43a388a1d294a09616906f8e174efca3097299f784efd4caff0bf168c3e5165b9ad3", "tag" : "3b08958be1286c2b4acba02b3674adb2", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 131, "comment" : "J0:000102030405060708090a0bffff7fff", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "3f1188546c65ed0fc55e75032c68ee44", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "5deccf838b2cf5f869c90d2a611160b1e578ab8121b93735cba4a1930647b8c4c84bf776333ee45a", "tag" : "c14d52208f0f51b816a48971eaf8ff7e", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 132, "comment" : "J0:000102030405060708090a0bffff7ffe", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "a13434d1cd8301d8b12212051fabaabe", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "d2cae1684aa407a13a2e2da5357e29f55deccf838b2cf5f869c90d2a611160b1e578ab8121b93735", "tag" : "ea2d018099cd7925c507cef0ceddb0ae", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 133, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "00000000000000000000000000000000", "aad" : "", "msg" : "5c7d3f81d4b5055ed6f8db53614587a4", "ct" : "541b835dc828d541073f7d7d7504ebf5", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 134, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "ffffffffffffffffffffffffffffffff", "aad" : "", "msg" : "6a347ad1190e72ede611044e7475f0eb", "ct" : "a3f36154331c196624564bc395e49c3b", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] }, { "tcId" : 135, "comment" : "", "key" : "fae2a14197c7d1140061fe7c3d11d9f77c79562e3593a99b", "iv" : "bc28433953772d57bbd933100cd47a56", "aad" : "", "msg" : "", "ct" : "", "tag" : "1bb94331f26cad24036cfeff34b89aaf", "result" : "valid", "flags" : [] }, { "tcId" : 136, "comment" : "", "key" : "cee9abbc26b63e169f0ced621fe21d95904e75b881d93e6b", "iv" : "1e8259e0a43e571068f701cd2064fc0c", "aad" : "", "msg" : "46", "ct" : "dc", "tag" : "af1f5535b125b34fc466902ea40cb3a2", "result" : "valid", "flags" : [] }, { "tcId" : 137, "comment" : "", "key" : "189f0bd390ba40632586a45c39735c2b87113329c800f394", "iv" : "c84442d6975f0359737de0fa828f958e", "aad" : "", "msg" : "b4bcd7b8eeca3050dd17682c6a914e", "ct" : "2aab5c87dcb4a4dae4e975ddb65aab", "tag" : "6b03b7557c7131e2352e495d54e61aef", "result" : "valid", "flags" : [] }, { "tcId" : 138, "comment" : "", "key" : "b0724f15df5b792c2f49bc51df0ac5aad69be0030981613c", "iv" : "13cd526ec77b58f62d48d03f8b88f2b8", "aad" : "", "msg" : "8da3ab9c3d195b04df452ad23953da4d", "ct" : "d127fd2e67c0887d90eb92b91f357d97", "tag" : "eb05bda937faeed27f8833295d4ba559", "result" : "valid", "flags" : [] }, { "tcId" : 139, "comment" : "", "key" : "998750ba784841e40a7c5b03985732b6397e5459a3843954", "iv" : "1d3d62eccd8ac5e896f2654a7f606fc9", "aad" : "", "msg" : "2f60ca3494a958dc3e6ebeb5d0b4e6dda0d0c4331ab9c957f6422a5100878ebf", "ct" : "344c2cea17b06cb3da272e22a22a3a71ee0eaa1959a7facfff464660ddccedd1", "tag" : "bab7fbf499ff06aad5f757b1c1a4fcc0", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 96, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 140, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "000000000000000000000000", "aad" : "", "msg" : "0b4dbbba8982e0f649f8ba85f3aa061b", "ct" : "3f875c9bd7d8511448459468e398c3b2", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] }, { "tcId" : 141, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff1021324354657687", "iv" : "ffffffffffffffffffffffff", "aad" : "", "msg" : "1ae93688ef7e2650a9342ad4718b2780", "ct" : "210dabea4364c6d5b3429e7743322936", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 142, "comment" : "", "key" : "5019eb9fef82e5750b631758f0213e3e5fcca12748b40eb4", "iv" : "ff0ddb0a0d7b36d219da12b5", "aad" : "", "msg" : "", "ct" : "", "tag" : "7971284e6c9e6aac346fe2b7a0a064c2", "result" : "valid", "flags" : [] }, { "tcId" : 143, "comment" : "", "key" : "21218af790428f8024d3e7e1428c9fcf578c216636d60e73", "iv" : "34047bc39b9c608384dff5b8", "aad" : "", "msg" : "e3", "ct" : "fe", "tag" : "2e982e24b81cd120d35a70fe6935e665", "result" : "valid", "flags" : [] }, { "tcId" : 144, "comment" : "", "key" : "3a8bf543c480925632118245bcbf5d01522b987a31a33da3", "iv" : "4ebc13cf4636cc7c45e560a7", "aad" : "", "msg" : "53fc72e71b59eeb3", "ct" : "99f2ff1c8a44e5f2", "tag" : "6870f104ddc514477b400336fb01860e", "result" : "valid", "flags" : [] }, { "tcId" : 145, "comment" : "", "key" : "92f4d2672fceec43963ccffb17e6ea7578b11418b06a3b82", "iv" : "6e7ff7f0797685cfc44b05ff", "aad" : "", "msg" : "c3ec16adb184affa8ae9738bffb916", "ct" : "afe8ef41591bfcc00db3c880ceb186", "tag" : "29fff7f285768645c9c8bf7a471c9393", "result" : "valid", "flags" : [] }, { "tcId" : 146, "comment" : "", "key" : "bcb6bc5ee6743df1396a34639327b25809ec9c81dd6a0c0e", "iv" : "be0326d23bdc2c64648d13f4", "aad" : "", "msg" : "80474a3a3b809560eee2ce7a7a33ea07", "ct" : "90339dca02ef717f1603994aee6cf6d2", "tag" : "e3d33e01ce64f271783147de226228bc", "result" : "valid", "flags" : [] }, { "tcId" : 147, "comment" : "", "key" : "5e1d28213e092536525bbae09e214af4c891e202b2b4fa4f", "iv" : "b6be6cd0681235d826aa28ea", "aad" : "", "msg" : "53d59433a7db7f41b31ccb6d4a2d789965", "ct" : "b98ed6321679941a3e521834296686ad98", "tag" : "9f50c03e055e519712c582ec9db3235b", "result" : "valid", "flags" : [] }, { "tcId" : 148, "comment" : "", "key" : "7f672d85e151aa490bc0eec8f66b5e5bee74af11642be3ff", "iv" : "b022067048505b20946216ef", "aad" : "", "msg" : "ef6412c72b03c643fa02565a0ae2378a9311c11a84065f80", "ct" : "addd303651119e52f6170dfc7a915064253d57532987b9ab", "tag" : "fa0484f8baa95f5b7a31c56d1b34c58b", "result" : "valid", "flags" : [] }, { "tcId" : 149, "comment" : "", "key" : "969fed5068541d65418c2c1de8fe1f845e036030496e1272", "iv" : "817fe51c31f2879141a34335", "aad" : "cb", "msg" : "3d8233191a2823bf767e99167b1d4af4f4848458", "ct" : "0d2c3a3c0cc4b40e70ed45e188e356a0e1533b31", "tag" : "92909a80e90540e1878ab59ef300072b", "result" : "valid", "flags" : [] }, { "tcId" : 150, "comment" : "", "key" : "fa5b9b41f93f8b682c04ba816c3fecc24eec095b04dd7497", "iv" : "62b9cf1e923bc1138d05d205", "aad" : "2ed8487153e21b12", "msg" : "18159841813a69fc0f8f4229e1678da7c9016711", "ct" : "c7c1cbb85ce2a0a3f32cb9ef01ad45ec1118b66d", "tag" : "253317f98bdab87531ece20475cd9ebb", "result" : "valid", "flags" : [] }, { "tcId" : 151, "comment" : "", "key" : "fbfb395662787e2d25a2e7510f818e825936a35114e237c9", "iv" : "3f1a1e02e90a4ba7a1db9df2", "aad" : "74318d8876528243f1944b73eb77e96e", "msg" : "2952a3d64107d5cbb9602239d05a5c5c222cf72b", "ct" : "ecf5e403f19c007c8da7a456caf0a6d75762829b", "tag" : "e0877a100f9dd9d6795f0e74c56a9fab", "result" : "valid", "flags" : [] }, { "tcId" : 152, "comment" : "", "key" : "5d8e9c2222316c9ed5ff94513cc957436ae447a6e1a73a29", "iv" : "0802ae86c75a73bf79561521", "aad" : "5ca354a4cb8e4fc9798aa209ad4f739dc7c232fdd1f22584", "msg" : "42b4439e1d2116f834b91c516a26299df279956b", "ct" : "94d844d98b9467daa7e8dde7f4290037354d7fb2", "tag" : "62196638590cef429d6b1d1a59839c02", "result" : "valid", "flags" : [] }, { "tcId" : 153, "comment" : "", "key" : "ccbd0f509825a5f358a14aac044ae2826bb2c9eaaaaa077f", "iv" : "9189a71ac359b73c8c08df22", "aad" : "", "msg" : "a1ed1007b52e36ec0f70109c68da72ee7b675c855e3e4956d2dcf9d12f675d6933f677ddcc58face857699d2e3d90adcb8c6c57c9d88b5dfcf356de4c0b63f0e", "ct" : "e9915bc5aea63c8bc014f2ae6a4986b03115ff1f34ad6c0acd74ffca07c453ec3f3ce6902d5ff338c588a34a1c3b30ef753ec7001572cbfeafe690fd00f59b02", "tag" : "fbf19b6b90e2d9df7ead0c3bc6e375a2", "result" : "valid", "flags" : [] }, { "tcId" : 154, "comment" : "", "key" : "d045c6eb173f440843faec3e9374602a94ee3f7176312208", "iv" : "98e9153daca2522e3162cb15", "aad" : "", "msg" : "3f0b30dc963a82d182c035b5a823060f07c4123792e6cee6bf91fea3c52fa66bb6a93ea6cce9f4813eb95bf18f816c00ad4fb56932827a39efb2fe56804e604a606774ee92ad46cd8c172a0d2bdea2fc99f67cd82c6024c315cfee6dbb8d27f745c9d0ce9bf5d09724f4bed003cf39478348b3304baa4ecc9974fc4f3ff93f95", "ct" : "9663e6f98b2768448e6dd0dd780e145668af5b002257e353213868c9cd9fd3a1e9427530327541775a093123076d34985db3aa248cd55e532609d1a39274c49216ea20fbab719b9c7e310b27877b9a33d1b69ab747afac944d1e97ea789367821c331f00b5d618402bfc57884d18edbd60c4dfe218c08080b8e3479ff84bdfb5", "tag" : "fc2ff62a41bdb79afc369842e4eccabf", "result" : "valid", "flags" : [] }, { "tcId" : 155, "comment" : "", "key" : "e602188abf6a91f3e258838cea6befeffcf6257a509c3e95", "iv" : "9e35d3ef1897c5fe3f647204", "aad" : "", "msg" : "3b9a6edc44848c072341fd4af51ec116ac328f69cc5a3354e49299fb2e5d22fa0084e30b36ecaf54309397b2b498d686087f3457698c3639e73ca18c78c3e021d673986cfc2ceb4d07e66971e976f58f0336f82c7fc0d52d66610f26ca3bfe53c0b01cf7c207306db904c1ad300ab95c56fde820a8edd256f2b9906b312bf7af5ef4a806f618ddfcb67179b03fff80a245c38d8f4cff2875b71a0bf69129caf97121462e0501ec6574ede94706f4a04d2fb301d415c22ea12157d2e919bc7a0169a5ad5c7bb5761a8531abbe77d66a4871b3f27a7170f099044b9fdc50a8cb3b894252a501cc896ac4793bdb478bb1cb99c02341d7238dd8d593cfda02f7d520d7", "ct" : "167183661675677625bed2d5f55f728dab80d7f06f629d99e58b45069fe9d7428e8961561b11245c709ac9ebb5c59ac2a89d8375d8a01d849c7733a1b482529927e3f1a1a53f63a4be08a11c941c634cd40373c42ffb2449c641bc9e39eafbcf9c0fba677e36496f73fc70aa0972224901ab04b0a196ab745262021b2313a8464187fecec43adb406258bddcd8c9d04dc2ae29e65d54a89dd0f1752d6d950dbf7da4dea0a7b9465579503fc8ec4451f4b39878ac4754a1aaf7b0b73fee11213cb8e601fc6039393f72e0e079ee97ecc610241757da2db2f51d5ed121481540eff47287744dac43375c4f48a46af70190453a17c3c78d735ba1d1fc76a330e6cbed", "tag" : "c72035314f43d256f8d845eb696bd943", "result" : "valid", "flags" : [] }, { "tcId" : 156, "comment" : "", "key" : "55a4ca526443357ac7c896d9a67cf7d467f6921d69002d3a", "iv" : "dba233ccbc7992e64e82cfa3", "aad" : "df737cd77d31eb9097a17c31b4c92889ef1f32b7464e2620e9007192ea675b9ad6910527ffecee2452be0248fab75608c7fdca08e86580322aac1d6a11b96ecf", "msg" : "4e56d1ea538cf49cad49959e884eb540c846556c", "ct" : "3f57ec1b414f74818fead9f35aa1679402c3e750", "tag" : "97b89b291419e32cf654ea630a3ad014", "result" : "valid", "flags" : [] }, { "tcId" : 157, "comment" : "", "key" : "f381d0ffd3373a1aa02edd1d7fa748e91908fe534bef73d2", "iv" : "10aaec0de4ad75376be9fd41", "aad" : "7739aad7399d9c0f0a3c95b403888f0072d94acb76ff576e05f4a063120b84e722b4d5cd43a58e4abab444cb8ced112f3dbd8993b831c39b4edb76e92eb33ee24c5922b56552685f3b0f4cf22e0e11628f6a3d33eff9def7ec527112dfafcf122814e3d1aaf66c3f970526511088bffef8101d1cef833268ff80387df30557f7", "msg" : "653a3f033c2775e08fef73cf80f5e2699fb360cb", "ct" : "5565c6d09c4c924d61c0ef808fb0ea144ffb4738", "tag" : "12b72ec1d9c32fb22c13c40b33796fa9", "result" : "valid", "flags" : [] }, { "tcId" : 158, "comment" : "", "key" : "8f27b1c3b3d7023c76ee66c768a3e92d4971e25f729d8788", "iv" : "12444040caede67285e490d7", "aad" : "58fd02ac23ec7fa5b9460f60bfc85b4bebba70039a8f83261d6cc4f560107c10bc69548a5d6152882fb465fd59fb8164d7c94523c3dd4206d33064f5191bd31f0c48fe03d7460e995c93175b57cb03f58711adc94632031c4305272367b4289c725d9cb7ae9ba996b3a079174508c1eae8162a0bac446c1e53fe0c402b6912dfd6702addccada30a5c010fc22c2c75e43226378ec7f4b3b71ccc71f32ab1adc877cc7b0a180c75d385c0f71a0b291a1cccf4be47e272249d61ffbf059c4f7be74eba07d5e1be3a7438458a611fe58cee4f946e25dee03e6485235566f20ed555be32cd57a94e522d2168eae23c4587371a2d145f418c59e7bbc464a3bd88b8919b", "msg" : "0df6e750092b9ac576dde66006a4cab2116eee21", "ct" : "c6877b03552e97d9a1e6557f90dc7adde15a2f43", "tag" : "2536272bee7446820041854e10b49a03", "result" : "valid", "flags" : [] }, { "tcId" : 159, "comment" : "Flipped bit 0 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b5e44c5b2fe90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 160, "comment" : "Flipped bit 1 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b6e44c5b2fe90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 161, "comment" : "Flipped bit 7 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "34e44c5b2fe90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 162, "comment" : "Flipped bit 8 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e54c5b2fe90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 163, "comment" : "Flipped bit 31 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44cdb2fe90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 164, "comment" : "Flipped bit 32 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2ee90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 165, "comment" : "Flipped bit 33 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2de90e4c78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 166, "comment" : "Flipped bit 63 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90ecc78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 167, "comment" : "Flipped bit 64 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c79f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 168, "comment" : "Flipped bit 71 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4cf8f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 169, "comment" : "Flipped bit 77 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78d358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 170, "comment" : "Flipped bit 80 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f359da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 171, "comment" : "Flipped bit 96 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da0c99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 172, "comment" : "Flipped bit 97 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da0f99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 173, "comment" : "Flipped bit 103 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da8d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 174, "comment" : "Flipped bit 120 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da0d99cb65", "result" : "invalid", "flags" : [] }, { "tcId" : 175, "comment" : "Flipped bit 121 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da0d99cb66", "result" : "invalid", "flags" : [] }, { "tcId" : 176, "comment" : "Flipped bit 126 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da0d99cb24", "result" : "invalid", "flags" : [] }, { "tcId" : 177, "comment" : "Flipped bit 127 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90e4c78f358da0d99cbe4", "result" : "invalid", "flags" : [] }, { "tcId" : 178, "comment" : "Flipped bits 0 and 64 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b5e44c5b2fe90e4c79f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 179, "comment" : "Flipped bits 31 and 63 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44cdb2fe90ecc78f358da0d99cb64", "result" : "invalid", "flags" : [] }, { "tcId" : 180, "comment" : "Flipped bits 63 and 127 in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b4e44c5b2fe90ecc78f358da0d99cbe4", "result" : "invalid", "flags" : [] }, { "tcId" : 181, "comment" : "all bits of tag flipped", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "4b1bb3a4d016f1b3870ca725f266349b", "result" : "invalid", "flags" : [] }, { "tcId" : 182, "comment" : "Tag changed to all zero", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "00000000000000000000000000000000", "result" : "invalid", "flags" : [] }, { "tcId" : 183, "comment" : "tag changed to all 1", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "invalid", "flags" : [] }, { "tcId" : 184, "comment" : "msbs changed in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "3464ccdbaf698eccf873d85a8d194be4", "result" : "invalid", "flags" : [] }, { "tcId" : 185, "comment" : "lsbs changed in tag", "key" : "000102030405060708090a0b0c0d0e0f1011121314151617", "iv" : "505152535455565758595a5b", "aad" : "", "msg" : "202122232425262728292a2b2c2d2e2f", "ct" : "458256842dfd297f30bd2f8f15c92db0", "tag" : "b5e54d5a2ee80f4d79f259db0c98ca65", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 128, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 186, "comment" : "J0:000102030405060708090a0b0c0d0e0f", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "5c2ea9b695fcf6e264b96074d6bfa572", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "28e1c5232f4ee8161dbe4c036309e0b3254e9212bef0a93431ce5e5604c8f6a73c18a3183018b770", "tag" : "d5808a1bd11a01129bf3c6919aff2339", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 187, "comment" : "J0:00000000000000000000000000000000", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "57b3a81f2c36b6b06577ca0fbab8fa8e", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "cceebeb4fe4cd90c514e52d2327a2ecd75393661006cf2476d8620149aef3d1cdce491fff3e7a7a3", "tag" : "8132e865b69d64ef37db261f80cbbe24", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 188, "comment" : "J0:ffffffffffffffffffffffffffffffff", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "ce20a7e870696a5e68533c465bad2ba1", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "4f4350565d91d9aa8c5f4048550492ad6d6fdabf66da5d1e2af7bfe1a8aadaa0baa3de38a41d9713", "tag" : "155da6441ec071ef2d8e6cffbacc1c7c", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 189, "comment" : "J0:fffffffffffffffffffffffffffffffe", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "918e3c19dbdfee2db18156c5b93f3d75", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "8316a53167b6de1a7575700693ffef274f4350565d91d9aa8c5f4048550492ad6d6fdabf66da5d1e", "tag" : "6c574aa6a2490cc3b2f2f8f0ffbc56c4", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 190, "comment" : "J0:fffffffffffffffffffffffffffffffd", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "717d900b270462b9dbf7e9419e890609", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "5175927513e751eb309f45bc2ef225f28316a53167b6de1a7575700693ffef274f4350565d91d9aa", "tag" : "8082a761e1d755344bf29622144e7d39", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 191, "comment" : "J0:000102030405060708090a0bffffffff", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "ecd52120af240e9b4bf3b9d1eeb49434", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "36b3fbecd09178d04527fb37544f5579d20d60a41266f685c48098e1a52804ca387d90709d3268dd", "tag" : "033e0ef2953ebfd8425737c7d393f89a", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 192, "comment" : "J0:000102030405060708090a0bfffffffe", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "b37bbad104928ae89221d3520c2682e0", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "16929b773051f12b0adac95f65e21a7f36b3fbecd09178d04527fb37544f5579d20d60a41266f685", "tag" : "ca448bb7e52e897eca234ef343d057d0", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 193, "comment" : "J0:000102030405060708090a0bfffffffd", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "538816c3f849067cf8576cd62b90b99c", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "6d3faefaf691d58163846f8d4b9ffd5916929b773051f12b0adac95f65e21a7f36b3fbecd09178d0", "tag" : "84f49740e6757f63dd0df7cb7656d0ef", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 194, "comment" : "J0:000102030405060708090a0b7fffffff", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "d10e631943cd3bdababab2bbd13951c0", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "d60196c2d14fcf30c0991d2721ddc52d385f407a16691dade82c9023c855fd8e2e8fbb562102f018", "tag" : "877e15d9889e69a99fcc6d727465c391", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 195, "comment" : "J0:000102030405060708090a0b7ffffffe", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "8ea0f8e8e87bbfa96368d83833ab4714", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "948fbceca12a6e4fabb79b6d965e336fd60196c2d14fcf30c0991d2721ddc52d385f407a16691dad", "tag" : "cd5757626945976ba9f0264bd6bee894", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 196, "comment" : "J0:000102030405060708090a0bffff7fff", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "7b2df4fbed1de2727eb24898e5deabb9", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "a1a0120660ff52e6b1700b12c54d2d33b94b00cd7882d8857d84e6e183a1dea6ee85a7da84fbc35d", "tag" : "b015d72da62c81cb4d267253b20db9e5", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 197, "comment" : "J0:000102030405060708090a0bffff7ffe", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "24836f0a46ab6601a760221b074cbd6d", "aad" : "", "msg" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000", "ct" : "5e3434b45edbf0d1f6e02d1144dbf867a1a0120660ff52e6b1700b12c54d2d33b94b00cd7882d885", "tag" : "ee74ccb30d649ebf6916d05a7dbe5696", "result" : "valid", "flags" : [ "ConstructedIv" ] }, { "tcId" : 198, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "00000000000000000000000000000000", "aad" : "", "msg" : "8d74f1c97243d362577ff376c393d2dc", "ct" : "265c42e2b96ea1de9c24f7182e337390", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 199, "comment" : "special case", "key" : "00112233445566778899aabbccddeeff102132435465768798a9bacbdcedfe0f", "iv" : "ffffffffffffffffffffffffffffffff", "aad" : "", "msg" : "884df0e76f3ce227bf9595d103825a46", "ct" : "988f47668ea650cbaa6714711abe268d", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] }, { "tcId" : 200, "comment" : "", "key" : "b4cd11db0b3e0b9b34eafd9fe027746976379155e76116afde1b96d21298e34f", "iv" : "00c49f4ebb07393f07ebc3825f7b0830", "aad" : "", "msg" : "", "ct" : "", "tag" : "306fe8c9645cc849823e333a685b90b2", "result" : "valid", "flags" : [] }, { "tcId" : 201, "comment" : "", "key" : "b7797eb0c1a6089ad5452d81fdb14828c040ddc4589c32b565aad8cb4de3e4a0", "iv" : "0ad570d8863918fe89124e09d125a271", "aad" : "", "msg" : "ed", "ct" : "3f", "tag" : "fd8f593b83314e33c5a72efbeb7095e8", "result" : "valid", "flags" : [] }, { "tcId" : 202, "comment" : "", "key" : "4c010d9561c7234c308c01cea3040c925a9f324dc958ff904ae39b37e60e1e03", "iv" : "2a55caa137c5b0b66cf3809eb8f730c4", "aad" : "", "msg" : "2a093c9ed72b8ff4994201e9f9e010", "ct" : "041341078f0439e50b43c991635117", "tag" : "5b8a2f2da20ef657c903da88ef5f57bb", "result" : "valid", "flags" : [] }, { "tcId" : 203, "comment" : "", "key" : "e7f7a48df99edd92b81f508618aa96526b279debd9ddb292d385ddbae80b2259", "iv" : "7ee376910f08f497aa6c3aa7113697fd", "aad" : "", "msg" : "5e51dbbb861b5ec60751c0996e00527f", "ct" : "469478d448f7e97d755541aa09ad95b0", "tag" : "254ada5cf662d90c5e11b2bd9c4db4c4", "result" : "valid", "flags" : [] }, { "tcId" : 204, "comment" : "", "key" : "4f84782bfbb64a973c3de3dcfa3430367fd68bc0b4c3b31e5d7c8141ba3e6a67", "iv" : "5d1bde6fa0994b33efd8f23f531248a7", "aad" : "", "msg" : "78cb6650a1908a842101ea85804fed00cc56fbdafafba0ef4d1ca607dcae57b6", "ct" : "cb960201fa5ad41d41d1c2c8037c71d52b72e76b16b589d71b976627c9734c9d", "tag" : "8dfce16467c3a6ebb3e7242c9a551962", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 120, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 205, "comment" : "unusual IV size", "key" : "34c74e28182948e03af02a01f46eb4f7", "iv" : "b0a73119a97d623806b49d45ddf4c7", "aad" : "", "msg" : "fe82ba66cf2e265741f2c86c", "ct" : "2bc3ef8e7402b4631f48e9be", "tag" : "4b6f6f5be291a90b9e93a8a82ddbc8d8", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 160, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 206, "comment" : "unusual IV size", "key" : "55cb7cac77efe18a1ea3b30c65f3f346", "iv" : "e22b6b144ab26b5781316e7a42a76202ac4b2278", "aad" : "", "msg" : "2f3d11ea32bf5bc72cbe2b8d", "ct" : "4fe13ef29f118f85a63188f8", "tag" : "05975b175316df8045889f43e0c857e0", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 120, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 207, "comment" : "unusual IV size", "key" : "66f75acbd8d3acf7af47d13e8384c2809d6b91503a7f294b", "iv" : "edf93e16294f15eded83808f09320e", "aad" : "", "msg" : "a900c86b6b7e0e5563f8f826", "ct" : "9af1a022c61c4315aa0e923e", "tag" : "20529bff3c59222ec33353af337b1d40", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 160, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 208, "comment" : "unusual IV size", "key" : "ef2e299dd4ecd7e3b9cc62780922cc2c89f78840564d1276", "iv" : "130c14c839e35b7d56b3350b194b0da342e6b65d", "aad" : "", "msg" : "03f59579b14437199583270e", "ct" : "073a5291b11df379f31b4f16", "tag" : "17205999491bd4c1d6c7ec3e56779c32", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 120, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 209, "comment" : "unusual IV size", "key" : "e98b0669a645eb14cd06df6968fc5f10edc9f54feed264e3d410cdc61b72ef51", "iv" : "17ca250fb733877556263223eadde1", "aad" : "", "msg" : "f384b3ed7b274641f5db60cf", "ct" : "fc213602aa423b87d7c2a874", "tag" : "36b15bab6923b17218fe1c24048e2391", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 160, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 210, "comment" : "unusual IV size", "key" : "849b3e6b8cdd85bdcfb8eb701aa5522ae2340fbe5214e389622cef76979225c4", "iv" : "0f9d6ed7eef362dfa4a7dfa5c0f74c5b27bd4ebf", "aad" : "", "msg" : "8c5564e53051c0de273199b4", "ct" : "c1d76233e8c5042e92bf8d32", "tag" : "7cf036d235d3b2dd349a8c804b65144a", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 256, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 211, "comment" : "long IV size", "key" : "5927bae748bb69d81b5a724e0a165652", "iv" : "365e0b96932b13306f92e9bb23847165bcbf5d35e45a83d75c86ecca70131f4c", "aad" : "", "msg" : "316bf99bfafc76f1bfc0b03c", "ct" : "5348af57fafe2485b43f2bc4", "tag" : "019a96c5373c031626b6c0300d4cf78b", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 512, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 212, "comment" : "long IV size", "key" : "dbd3676f293409273f27b375e03793a3", "iv" : "967fa7c990eb2becbd450835e28ea3a9000c7216285cfa7696e8c3dac3ce952a1fe638d7c8c73e1d708dce01b5a20fcc9aa011949d2a835f777423c172fa3aa0", "aad" : "", "msg" : "625efedb8b7f1aa62238a8f2", "ct" : "f559b70fe1149cb34406a2c7", "tag" : "94180ddb7bb1995abe0219eab5ce232f", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 1024, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 213, "comment" : "long IV size", "key" : "7e5a39dcda7e066988f19adf4de4d501", "iv" : "494356c3459d60e3a83433c9bcf2c0454a763e496e4ec99bfbe4bbb83a4fda76b542213899dcf5521cd9bbbe5d11545bda44a3f4a681ce2843acea730d83d3930ea30991ee1a68ebf6d1a5a40f9b02a1aab091298df8dd689dc7613bcbff94d35f2ca43377d81618562bcf6573411ec9bc97c5a6276b554054c0fa787073d067", "aad" : "", "msg" : "b04729b4adbaac63c2aaf8d8", "ct" : "5291dd4da91ccc2e77306d83", "tag" : "a7f7b21a3b7ece509e922647fd905f06", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 2056, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 214, "comment" : "long IV size", "key" : "eac3f28cd937ff29eb6158a3721b5145", "iv" : "6fd260bba87339539c37dc68fdc3656f63c83028cb8adcb531085e98bd570c6b735d0cc4b4b924696000a2d893621ae64dcce992b562b89a5285643a08febccbc52243cbfc8d45212e047b00c87c6b6bf175f8bb678ec55c1091315cbecb8b85700f4a4653623fb78e63cfff7d6235e48e9832c9f0716d10992fc5b0ad4e6972bbeeb1ad670cd7ec8fac82e07ea5a64f9761a39714aaa73affd2cb190a7ac2df5e5dcea6812ae2c872c7ac70453c5e7ec4d0b5b18c6ff3bfb9ae15fea44cf392615b80034edae596b8821f97fca58d167fb44a093b0c009a0bd5631355b0cb25d93ba9b79b006301d99db657e801933fc2764a0ce650eaf5a1299efe60cb53b634", "aad" : "", "msg" : "098912a302773377b9c26ac3", "ct" : "e3be947153a26a3a54e3015c", "tag" : "fd042bdde22f67c4fd298d5dc0867606", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 256, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 215, "comment" : "long IV size", "key" : "8f9ebc67a9a6430c2b0ceeaf983e1356964bb928635b9ca4", "iv" : "36e4b381574d171c7769a788cbc147224fabd8b773f16b8ae84d8f2603aaa440", "aad" : "", "msg" : "a3a96ee94f94caa81ebcd66d", "ct" : "8c2a9823a3b3d413be696387", "tag" : "faaf01ceb40a7e145e8fe65aa9af58c0", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 512, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 216, "comment" : "long IV size", "key" : "f4bbdfd06f7fb1434880e4166d38d56e02a3f0df0d5301ce", "iv" : "90743bd5d794d52ac848b7e2384545a25846acf143be84c0ead0432fcf3172631cf58d0ca78571c03053c1e1b85ed79cb5303d0e3a98ff4f56c4f0a5eb4f0eac", "aad" : "", "msg" : "39d2abe6697f17ec27f2a39c", "ct" : "a660ea5bf07a78fea0120173", "tag" : "7404fc7b7354694428236f203c130244", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 1024, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 217, "comment" : "long IV size", "key" : "1761c77798ef9cdfa40553f34614fe7402212087f0509411", "iv" : "fbb3eab379c9b8689dc30b0713690e55d51c956ca36fbcc73eeeee16a46d7c41a7a9626e68e25d685c008c19d3b2b1792bdc99c35441a6fcac35e0d6446dd914f543abd9ecd6b0cb5201c243026c4f13641d67c8d8cd5114b6e11ebbc6b1dee2a18db2150a5a575dcd21648e0337dadbccd3deffd6d979e03e6b9ddfee0abdc2", "aad" : "", "msg" : "35ca4eb463a2000138210b4d", "ct" : "f400132ff38c04ed747dde34", "tag" : "ca1534e7dd0336bbb32a79830c71a447", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 2056, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 218, "comment" : "long IV size", "key" : "f795ece7de1881fbc6843eb740f812e41e3fc49ff6c7b940", "iv" : "3569fca7c9d06e2a03fed1aac2484fd4416ca07d55ecbb333ec674f0ea5c6e75a10dfb9c738b69dab2eda10ada721a61c7f02b7e7f79e8a9e2dc36b3fdf609e436054c82a774ec617dceec84a577037ff1a3f120d9818d042063acb36c9584e81ec94f11f1ee240f2e45e944694a9c8e535acbb01d93958411cff68e3d32f8931746a4a0cece65e93c51c70b3111034b6867b407e0147f97c576d3ed8cec7e8ec26e95643e46e97ea3595c9c3172b4856f2d2b6dc8564666ddac92c794ffb2d4dc7f461761f0e326650f48d327604e095bd8754072116c96360d09f010ac2f39eb96b227f3d738deb756c8699460d88cf716170ae15267b14f4a89164720f1c602", "aad" : "", "msg" : "22dbd8037aa05b14cf81dd23", "ct" : "13a95a06c1bed4845af9c701", "tag" : "03379836b0c82f64a1bccdcd763acbbc", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 256, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 219, "comment" : "long IV size", "key" : "ee4171917d2337496812a2784d6a71300e6b8c1ac3b1ef58cee77c229aeaf2c5", "iv" : "e826a79361f9d582b64450e3edc82589487853d5b22feaa0c889875bd0d87cd4", "aad" : "", "msg" : "94d2f8697facaaa191ba617a", "ct" : "a295c2cb27ce23d26874ade1", "tag" : "04650a78bbb61db337c9c32aa3e7b6fa", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 512, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 220, "comment" : "long IV size", "key" : "132c59b4bcb8afb31637734a81105bb2c9878f320ace9076d5fd7c5d216c8d12", "iv" : "ec51ee18cfb46897d3666c7df35c29ca5d898241c4a34f893eb1db5d5c6b76e24617459d1153868154437a0e95aa3c26e956b494a52dd5ac3b9331116c7c775f", "aad" : "", "msg" : "12c7be00facda49596e19134", "ct" : "9cdcfc3aaa8d466f25588e4b", "tag" : "7e80f51e7180f1cd3ba84349888fcd5c", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 1024, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 221, "comment" : "long IV size", "key" : "7b0b12491901d62d097fa26dc71e15cfacafa3226719e47126d99c79d98ec222", "iv" : "7d08b226b4a5d03f6f8cb3a3cb8d1ce31b059dc5112385275e38a15c97e0f24022b249a5f7019ea577198cb26ac64e82b2b04681537c4198775a523b0e6494b84febaef3399b35c27b0969fa43572bf5827a763aac1af69526f37e38acb5d354f2b68487f275f4361ed39073f7dd6653ac17c0794118a0cf143293ac0be66229", "aad" : "", "msg" : "c80312590700c3bbfacd1a40", "ct" : "3f3c151e984d059462f9e5a0", "tag" : "e559f5f755aa292171cc35fbf911a64f", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 2056, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 222, "comment" : "long IV size", "key" : "3bc3bf39d0d5ffd94cca2b45c678a2d049151ed2babc713be53cb66f54a16337", "iv" : "92c2cee7e9138b186da51f146fb21fd5b491f1a19eef61d4ed14ce6b21b04fdb6ff8ebb60fddc55926e7bda2a8f35c610bb795232412739d6c2d74458ef5a1a1cde9bf17e47e3b00db0b0504d56dc8b8d3de23f7c3a5d52e8d0aab1e64405aaa852ec2dd667ed9c1fd8dc1fdbbc8712c7a38f30faeab594f33897b41b1720f3c2f954ed91ca450d82c3dcd35858c608ad42f36832e56b04821a132f72e0da7b62cbd3925250f64fbb3f5c4783495893097adc09a32d776e04bf72558d37830b372341f6536d8ee9df4a82e4074e7774ab6917a04fa8c499eb4b46a92def365da8b5eb1e0b438779507d1f5272a6e8629a3f9c7bd4862c5691ee8b56bfe292deb4e", "aad" : "", "msg" : "8125ee7637d7d0e03bbacf35", "ct" : "5496ae94c3322ebf959ea9a9", "tag" : "70717cc00fd1ffa59bb04329226a0c0a", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 0, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 223, "comment" : "0 size IV is not valid", "key" : "8f3f52e3c75c58f5cb261f518f4ad30a", "iv" : "", "aad" : "", "msg" : "", "ct" : "", "tag" : "cf71978ffcc778f3c85ac9c31b6fe191", "result" : "invalid", "flags" : [ "ZeroLengthIv" ] }, { "tcId" : 224, "comment" : "0 size IV is not valid", "key" : "2a4bf90e56b70fdd8649d775c089de3b", "iv" : "", "aad" : "", "msg" : "324ced6cd15ecc5b3741541e22c18ad9", "ct" : "00a29f0a5e2e7490279d1faf8b881c7b", "tag" : "a2c7e8d7a19b884f742dfec3e76c75ee", "result" : "invalid", "flags" : [ "ZeroLengthIv" ] } ] }, { "ivSize" : 0, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 225, "comment" : "0 size IV is not valid", "key" : "0b18d21337035c7baa08211b702fa780ac7c09be8f9ed11f", "iv" : "", "aad" : "", "msg" : "", "ct" : "", "tag" : "ca69a2eb3a096ea36b1015d5dffff532", "result" : "invalid", "flags" : [ "ZeroLengthIv" ] }, { "tcId" : 226, "comment" : "0 size IV is not valid", "key" : "ba76d594a6df915bb7ab7e6d1a8d024b2796336c1b8328a9", "iv" : "", "aad" : "", "msg" : "d62f302742d61d823ea991b93430d589", "ct" : "509b0658d09f7a5bb9db43b70c8387f7", "tag" : "2c9488d53a0b2b5308c2757dfac7219f", "result" : "invalid", "flags" : [ "ZeroLengthIv" ] } ] }, { "ivSize" : 0, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 227, "comment" : "0 size IV is not valid", "key" : "3f8ca47b9a940582644e8ecf9c2d44e8138377a8379c5c11aafe7fec19856cf1", "iv" : "", "aad" : "", "msg" : "", "ct" : "", "tag" : "1726aa695fbaa21a1db88455c670a4b0", "result" : "invalid", "flags" : [ "ZeroLengthIv" ] }, { "tcId" : 228, "comment" : "0 size IV is not valid", "key" : "7660d10966c6503903a552dde2a809ede9da490e5e5cc3e349da999671809883", "iv" : "", "aad" : "", "msg" : "c314235341debfafa1526bb61044a7f1", "ct" : "7772ea358901f571d3d35c19497639d9", "tag" : "8fe0520ad744a11f0ccfd228454363fa", "result" : "invalid", "flags" : [ "ZeroLengthIv" ] } ] }, { "ivSize" : 8, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 229, "comment" : "small IV sizes", "key" : "59a284f50aedd8d3e2a91637d3815579", "iv" : "80", "aad" : "", "msg" : "", "ct" : "", "tag" : "af498f701d2470695f6e7c8327a2398b", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 230, "comment" : "small IV sizes", "key" : "fec58aa8cf06bfe05de829f27ec77693", "iv" : "9d", "aad" : "", "msg" : "f2d99a9f893378e0757d27c2e3a3101b", "ct" : "0a24612a9d1cbe967dbfe804bf8440e5", "tag" : "96e6fd2cdc707e3ee0a1c90d34c9c36c", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 16, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 231, "comment" : "small IV sizes", "key" : "88a972cce9eaf5a7813ce8149d0c1d0e", "iv" : "0f2f", "aad" : "", "msg" : "", "ct" : "", "tag" : "4ccf1efb4da05b4ae4452aea42f5424b", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 232, "comment" : "small IV sizes", "key" : "b43967ee933e4632bd6562ba1201bf83", "iv" : "8760", "aad" : "", "msg" : "5a6ad6db70591d1e520b0122f05021a0", "ct" : "ba3e7f8b2999995c7fc4006ca4f475ff", "tag" : "98f47a5279cebbcac214515710f6cd8a", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 32, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 233, "comment" : "small IV sizes", "key" : "4e9a97d3ed54c7b54610793ab05052e1", "iv" : "cc851957", "aad" : "", "msg" : "", "ct" : "", "tag" : "e574b355bda2980e047e584feb1676ca", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 234, "comment" : "small IV sizes", "key" : "d83c1d7a97c43f182409a4aa5609c1b1", "iv" : "7b5faeb2", "aad" : "", "msg" : "c8f07ba1d65554a9bd40390c30c5529c", "ct" : "1b84baea9df1e65bee7b49e4a8cda1ec", "tag" : "5c0bb79d8240041edce0f94bd4bb384f", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 48, "keySize" : 128, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 235, "comment" : "small IV sizes", "key" : "c6a705677affb49e276d9511caa46145", "iv" : "4ad80c2854fb", "aad" : "", "msg" : "", "ct" : "", "tag" : "1e2ed72af590cafb8647d185865f5463", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 236, "comment" : "small IV sizes", "key" : "eba7699b56cc0aa2f66a2a5be9944413", "iv" : "d1dafc8de3e3", "aad" : "", "msg" : "d021e53d9098a2df3d6b903cdad0cd9c", "ct" : "18291aa8dc7b07448aa8f71bb8e380bf", "tag" : "9c0e22e5c41b1039ff5661ffaefa8e0f", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 8, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 237, "comment" : "small IV sizes", "key" : "c70ce38e84e5f53ed41c3f0d2ca493412ad32cb04c6e2efa", "iv" : "cb", "aad" : "", "msg" : "", "ct" : "", "tag" : "08d96edb5e22874cd10cb2256ca04bc6", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 238, "comment" : "small IV sizes", "key" : "74c816b83dfd287210a3e2c6da8d3053bbfbd9b156d3fdd8", "iv" : "0f", "aad" : "", "msg" : "f2b7b2c9b312cf2af78f003df15c8e19", "ct" : "6c5e796ba9a3ddc64f401e68d135101d", "tag" : "96a132ed43924e98feb888ff682bdaef", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 16, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 239, "comment" : "small IV sizes", "key" : "cbf45ba488932aea1a10e5862f92e4a7e277bda9f34af6d0", "iv" : "75e5", "aad" : "", "msg" : "", "ct" : "", "tag" : "1f0d23070fcd748e25bf6454f5c9136e", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 240, "comment" : "small IV sizes", "key" : "e1c0446f11ae6aa4fa254f9a846fc6e13e45e537e47f2042", "iv" : "8989", "aad" : "", "msg" : "3a2f5ad0eb216e546e0bcaa377b6cbc7", "ct" : "550b48a43e821fd76f49f0f1a897aead", "tag" : "f6e0a979481f9957ddad0f21a777a73a", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 32, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 241, "comment" : "small IV sizes", "key" : "567563bf4cf154902275a53bc57cd6dd7b370d27011bdac8", "iv" : "68d7fc38", "aad" : "", "msg" : "", "ct" : "", "tag" : "1475563e3212f3b5e40062569afd71e3", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 242, "comment" : "small IV sizes", "key" : "834d0bb601170865a78139428a1503695a6a291ebd747cd1", "iv" : "bb9d2aa3", "aad" : "", "msg" : "6f79e18b4acd5a03d3a5f7e1a8d0f183", "ct" : "309133e76159fe8a41b20843486511ab", "tag" : "03ab26993b701910a2e8ecccd2ba9e52", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 48, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 243, "comment" : "small IV sizes", "key" : "99fb18f5ba430bb9ea942968ecb799b43406e1af4b6425a1", "iv" : "a984bdcdcae2", "aad" : "", "msg" : "", "ct" : "", "tag" : "d7b9a6b58a97982916e83219fbf71b1e", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 244, "comment" : "small IV sizes", "key" : "b77b242aa0d51c92fda013e0cb0ef2437399ace5d3f507e4", "iv" : "52aa01e0d0d6", "aad" : "", "msg" : "4ba541a9914729216153801340ab1779", "ct" : "e08261e46eaf90d978ea8f7889bccd4f", "tag" : "c052a55df3926a50990a532efe3d80ec", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 64, "keySize" : 192, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 245, "comment" : "small IV sizes", "key" : "d74599b3d2db81653de43b52fc994c50d0be759fab87c33a", "iv" : "d1c61cf8532531b5", "aad" : "", "msg" : "", "ct" : "", "tag" : "f94f2049a6560c470b3a7ca7bbc31a3d", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 246, "comment" : "small IV sizes", "key" : "0b177198c8b419bf74acc3bc65b5fb3d09a915ff71add754", "iv" : "8f075cbcda9831c3", "aad" : "", "msg" : "c4b1e05ca3d591f9543e64de3fc682ac", "ct" : "3c6ec0ab1b827bf238a5384fb7e212ce", "tag" : "7db7402224fd583e312bc0e61cf11366", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 8, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 247, "comment" : "small IV sizes", "key" : "8f9a38c1014966e4d9ae736139c5e79b99345874f42d4c7d2c81aa6797c417c0", "iv" : "a9", "aad" : "", "msg" : "", "ct" : "", "tag" : "2a268bf3a75fd7b00ba230b904bbb014", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 248, "comment" : "small IV sizes", "key" : "144cd8279229e8bb2de99d24e615306663913fe9177fcd270fafec493d43bca1", "iv" : "b3", "aad" : "", "msg" : "976229f5538f9636476d69f0c328e29d", "ct" : "7bea30ecc2f73f8e121263b37966954c", "tag" : "8bbad4adc54b37a2b2f0f6e8617548c9", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 16, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 249, "comment" : "small IV sizes", "key" : "7d31861f9d3536e14016a3216b1042e0d2f7d4614314268b6f834ec7f38bbb65", "iv" : "c332", "aad" : "", "msg" : "", "ct" : "", "tag" : "1d978a693120c11f6d51a3ed88cd4ace", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 250, "comment" : "small IV sizes", "key" : "22b35fe9623ee11f8b60b6d22db3765b666ed972fa7ccd92b45f22deee02cab1", "iv" : "da6c", "aad" : "", "msg" : "5341c78e4ce5bf8fbc3e077d1990dd5d", "ct" : "9c39f5b110361e9a770cc5e8b0f444bb", "tag" : "b63ff43c12073ec5572b1be70f17e231", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 32, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 251, "comment" : "small IV sizes", "key" : "c224e0bba3d7a99165f7996b67a0fce3e12f2c01179b197b69b7e628bca92096", "iv" : "6b30145e", "aad" : "", "msg" : "", "ct" : "", "tag" : "ae6f7c9a29f0d8204ca50b14a1e0dcf2", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 252, "comment" : "small IV sizes", "key" : "093eb12343537ee8e91c1f715b862603f8daf9d4e1d7d67212a9d68e5aac9358", "iv" : "5110604c", "aad" : "", "msg" : "33efb58c91e8c70271870ec00fe2e202", "ct" : "f73f72f976a296ba3ca94bc6eb08cd46", "tag" : "b824c33c13f289429659aa017c632f71", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 48, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 253, "comment" : "small IV sizes", "key" : "98e6f8ab673e804e865e32403a6551bf807a959343c60d34559360bc295ecb5b", "iv" : "d4d857510888", "aad" : "", "msg" : "", "ct" : "", "tag" : "3db16725fafc828d414ab61c16a6c38f", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 254, "comment" : "small IV sizes", "key" : "0bd0e8e7781166e1d876dec8fad34ba95b032a27cac0551595116091005947b7", "iv" : "1bdcd44b663e", "aad" : "", "msg" : "91222263b12cf5616a049cbe29ab9b5b", "ct" : "ed463f4f43336af3f4d7e08770201145", "tag" : "c8fc39906aca0c64e14a43ff750abd8a", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] }, { "ivSize" : 64, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 255, "comment" : "small IV sizes", "key" : "61ba694897925d1b4174d40401469c3ef267cdb9f829edb1a10618c16d666059", "iv" : "0d10c5c84b88d688", "aad" : "", "msg" : "", "ct" : "", "tag" : "1311f9f830d729c189b74ec4f9080fa1", "result" : "acceptable", "flags" : [ "SmallIv" ] }, { "tcId" : 256, "comment" : "small IV sizes", "key" : "115884f693b155563e9bfb3b07cacb2f7f7caa9bfe51f89e23feb5a9468bfdd0", "iv" : "04102199ef21e1df", "aad" : "", "msg" : "82e3e604d2be8fcab74f638d1e70f24c", "ct" : "7e0dd6c72aec49f89cc6a80060c0b170", "tag" : "af68a37cfefecc4ab99ba50a5353edca", "result" : "acceptable", "flags" : [ "SmallIv" ] } ] } ] } s2a-go-0.1.8/internal/record/internal/aeadcrypter/testdata/chacha_poly_wycheproof.json000066400000000000000000005771301464711036600312710ustar00rootroot00000000000000{ "algorithm" : "CHACHA20-POLY1305", "generatorVersion" : "0.8r12", "numberOfTests" : 300, "header" : [ "Test vectors of type AeadTest test authenticated encryption with", "additional data. The test vectors are intended for testing both", "encryption and decryption." ], "notes" : { }, "schema" : "aead_test_schema.json", "testGroups" : [ { "ivSize" : 96, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 1, "comment" : "RFC 7539", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "070000004041424344454647", "aad" : "50515253c0c1c2c3c4c5c6c7", "msg" : "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", "ct" : "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116", "tag" : "1ae10b594f09e26a7e902ecbd0600691", "result" : "valid", "flags" : [] }, { "tcId" : 2, "comment" : "", "key" : "80ba3192c803ce965ea371d5ff073cf0f43b6a2ab576b208426e11409c09b9b0", "iv" : "4da5bf8dfd5852c1ea12379d", "aad" : "", "msg" : "", "ct" : "", "tag" : "76acb342cf3166a5b63c0c0ea1383c8d", "result" : "valid", "flags" : [] }, { "tcId" : 3, "comment" : "", "key" : "7a4cd759172e02eb204db2c3f5c746227df584fc1345196391dbb9577a250742", "iv" : "a92ef0ac991dd516a3c6f689", "aad" : "bd506764f2d2c410", "msg" : "", "ct" : "", "tag" : "906fa6284b52f87b7359cbaa7563c709", "result" : "valid", "flags" : [] }, { "tcId" : 4, "comment" : "", "key" : "cc56b680552eb75008f5484b4cb803fa5063ebd6eab91f6ab6aef4916a766273", "iv" : "99e23ec48985bccdeeab60f1", "aad" : "", "msg" : "2a", "ct" : "3a", "tag" : "cac27dec0968801e9f6eded69d807522", "result" : "valid", "flags" : [] }, { "tcId" : 5, "comment" : "", "key" : "46f0254965f769d52bdb4a70b443199f8ef207520d1220c55e4b70f0fda620ee", "iv" : "ab0dca716ee051d2782f4403", "aad" : "91ca6c592cbcca53", "msg" : "51", "ct" : "c4", "tag" : "168310ca45b1f7c66cad4e99e43f72b9", "result" : "valid", "flags" : [] }, { "tcId" : 6, "comment" : "", "key" : "2f7f7e4f592bb389194989743507bf3ee9cbde1786b6695fe6c025fd9ba4c100", "iv" : "461af122e9f2e0347e03f2db", "aad" : "", "msg" : "5c60", "ct" : "4d13", "tag" : "91e8b61efb39c122195453077b22e5e2", "result" : "valid", "flags" : [] }, { "tcId" : 7, "comment" : "", "key" : "c8833dce5ea9f248aa2030eacfe72bffe69a620caf793344e5718fe0d7ab1a58", "iv" : "61546ba5f1720590b6040ac6", "aad" : "88364fc8060518bf", "msg" : "ddf2", "ct" : "b60d", "tag" : "ead0fd4697ec2e5558237719d02437a2", "result" : "valid", "flags" : [] }, { "tcId" : 8, "comment" : "", "key" : "bd8ed7fb0d607522f04d0b12d42c92570bccc5ba2486953d70ba2e8193f6225a", "iv" : "d2ab0abb50a8e9fba25429e1", "aad" : "", "msg" : "201221", "ct" : "3cf470", "tag" : "a27a69c9d7ee84586f11388c6884e63a", "result" : "valid", "flags" : [] }, { "tcId" : 9, "comment" : "", "key" : "1c8b59b17a5ceced31bde97d4cefd9aaaa63362e096e863ec1c89580bca79b7a", "iv" : "94f32a6dff588f2b5a2ead45", "aad" : "6c8cf2ab3820b695", "msg" : "453f95", "ct" : "610925", "tag" : "a8a7883eb7e40bc40e2e5922ae95ddc3", "result" : "valid", "flags" : [] }, { "tcId" : 10, "comment" : "", "key" : "e4912cb75a1174345f1a457366f18885fe8460b06478e04be2f7fb4ec9c113e5", "iv" : "7aa5ad8bf5254762171ec869", "aad" : "", "msg" : "9e4c1d03", "ct" : "fe6849aa", "tag" : "99ad07871b25c27defc31a541bd5c418", "result" : "valid", "flags" : [] }, { "tcId" : 11, "comment" : "", "key" : "e05777ef3d989ace7d2abfba452bfded54801dbd5c66e91c0c2ef00479d85572", "iv" : "b7f526e3fd71cf5720961aec", "aad" : "15d93a96d0e6c5a9", "msg" : "17bfda03", "ct" : "f4710e51", "tag" : "b957c6a37b6a4c94996c002186d63b2b", "result" : "valid", "flags" : [] }, { "tcId" : 12, "comment" : "", "key" : "1a4c4f39abe890e62345c947bcf7de7c2e33bd5ceeda0a0abf0e7ef935ddf3ee", "iv" : "9447bf85d5b97d8aee0f8e51", "aad" : "", "msg" : "c15a593bd0", "ct" : "f711647ff1", "tag" : "22b12dc38cb79629f84cdbdc2425c09d", "result" : "valid", "flags" : [] }, { "tcId" : 13, "comment" : "", "key" : "800e9a24791700c9609736695ba2a8b99b2d57f1c3bfb61ed49db1c6c5219583", "iv" : "3dbe876bd880ec8ea2017043", "aad" : "96224835610b782b", "msg" : "a7bfd041e3", "ct" : "d171f046ea", "tag" : "d179b1b9c4184378df009019dbb8c249", "result" : "valid", "flags" : [] }, { "tcId" : 14, "comment" : "", "key" : "208c2c376c9430433db20e1a6b7ba817f8ffbfa6827f26759ccede42e591d3ec", "iv" : "27fb58ec6a21e84696cb8830", "aad" : "", "msg" : "af104b5ccd0e", "ct" : "9351b1b1b082", "tag" : "560785509f60f26b681933d9cdbfd29f", "result" : "valid", "flags" : [] }, { "tcId" : 15, "comment" : "", "key" : "2eb168e53b07ab04355ea792fe11a6be2ce9c39cfe15a997076b1e38c17ad620", "iv" : "b5965470c383fd29fe7eaee7", "aad" : "6d52feb2509f7fbf", "msg" : "6fdf2927e169", "ct" : "41abff7b71cc", "tag" : "9b5174297c03cf8902d1f706fd008902", "result" : "valid", "flags" : [] }, { "tcId" : 16, "comment" : "", "key" : "55568158d3a6483f1f7021eab69b703f614251cadc1af5d34a374fdbfc5adac7", "iv" : "3c4e654d663fa4596dc55bb7", "aad" : "", "msg" : "ab85e9c1571731", "ct" : "5dfe3440dbb3c3", "tag" : "ed7a434e2602d394281e0afa9fb7aa42", "result" : "valid", "flags" : [] }, { "tcId" : 17, "comment" : "", "key" : "e3c09e7fab1aefb516da6a33022a1dd4eb272c80d540c5da52a730f34d840d7f", "iv" : "58389375c69ee398de948396", "aad" : "84e46be8c0919053", "msg" : "4ee5cda20d4290", "ct" : "4bd47212941ce3", "tag" : "185f1408ee7fbf18f5abad6e2253a1ba", "result" : "valid", "flags" : [] }, { "tcId" : 18, "comment" : "", "key" : "51e4bf2bad92b7aff1a4bc05550ba81df4b96fabf41c12c7b00e60e48db7e152", "iv" : "4f07afedfdc3b6c2361823d3", "aad" : "", "msg" : "be3308f72a2c6aed", "ct" : "8e9439a56eeec817", "tag" : "fbe8a6ed8fabb1937539dd6c00e90021", "result" : "valid", "flags" : [] }, { "tcId" : 19, "comment" : "", "key" : "1131c1418577a054de7a4ac551950f1a053f9ae46e5b75fe4abd5608d7cddadd", "iv" : "b4ea666ee119563366484a78", "aad" : "66c0ae70076cb14d", "msg" : "a4c9c2801b71f7df", "ct" : "b9b910433af052b0", "tag" : "4530f51aeee024e0a445a6328fa67a18", "result" : "valid", "flags" : [] }, { "tcId" : 20, "comment" : "", "key" : "e1094967f86d893cdfe2e2e6d5c7ee4dfef67da3c9c5d64e6ad7c1577dcb38c5", "iv" : "8092fc245b3326cddbd1424c", "aad" : "", "msg" : "c37aa791ddd6accf91", "ct" : "d9d897a9c1c5bb9f01", "tag" : "085a430373058f1a12a0d589fd5be68b", "result" : "valid", "flags" : [] }, { "tcId" : 21, "comment" : "", "key" : "236f9baee4f9da15beeca40ff4af7c760f254a64bc3a3d7f4fad557e61b68586", "iv" : "f1ca81338629587acf9372bf", "aad" : "8c32f47a386152ec", "msg" : "d7f26d5252e1765f5b", "ct" : "8fdb429d47761cbf8e", "tag" : "8ef647ed334fdebbc2bef80be02884e0", "result" : "valid", "flags" : [] }, { "tcId" : 22, "comment" : "", "key" : "4de207a3b70c51e5f23048eed5a5da9bb65e917a69aa93e7c8b4a815cd9724de", "iv" : "4c15a71dc6791a8c005ad502", "aad" : "", "msg" : "f2c54b6b5e490da18659", "ct" : "700d35adf5100a22a1de", "tag" : "102d992ffaff599b5bddddeb2dfb399b", "result" : "valid", "flags" : [] }, { "tcId" : 23, "comment" : "", "key" : "6d667fd79e5fb725f50343dccc4863227c75ee3f7a578476e3e9f32598d81559", "iv" : "6220527aba88e27f766658b2", "aad" : "e1e27ccddb3cb407", "msg" : "0c8c5a252681f2b5b4c0", "ct" : "04aad66c60e0bf8ebba9", "tag" : "c15f69a4d2aef97d7748756ff49d894b", "result" : "valid", "flags" : [] }, { "tcId" : 24, "comment" : "", "key" : "8f4bd94ef73e75d1e068c30b37ead576c5344e093ece1330e9101c82f793cf05", "iv" : "ec1e2967f0f6979e5f5b07fb", "aad" : "", "msg" : "b89812b34d9bced4a0ba07", "ct" : "1c3d53baaa36eaa1d8ec4d", "tag" : "4d94ebf960f12433bec43aa86d7e6e6d", "result" : "valid", "flags" : [] }, { "tcId" : 25, "comment" : "", "key" : "2aa3bc7033351cac51364cdaf6ffac2c20f64046e1550a7b1c65f41800599019", "iv" : "28cce57a5db2cd206321e340", "aad" : "a9bc350eaf2e6e3d", "msg" : "83016823123484b56095b0", "ct" : "1c8578f8e75203d0336a52", "tag" : "5910f7a9d5e4df05d7248bd7a8d65e63", "result" : "valid", "flags" : [] }, { "tcId" : 26, "comment" : "", "key" : "99b62bd5afbe3fb015bde93f0abf483957a1c3eb3ca59cb50b39f7f8a9cc51be", "iv" : "9a59fce26df0005e07538656", "aad" : "", "msg" : "42baae5978feaf5c368d14e0", "ct" : "ff7dc203b26c467a6b50db33", "tag" : "578c0f2758c2e14e36d4fc106dcb29b4", "result" : "valid", "flags" : [] }, { "tcId" : 27, "comment" : "", "key" : "85f35b6282cff440bc1020c8136ff27031110fa63ec16f1e825118b006b91257", "iv" : "58dbd4ad2c4ad35dd906e9ce", "aad" : "a506e1a5c69093f9", "msg" : "fdc85b94a4b2a6b759b1a0da", "ct" : "9f8816de0994e938d9e53f95", "tag" : "d086fc6c9d8fa915fd8423a7cf05072f", "result" : "valid", "flags" : [] }, { "tcId" : 28, "comment" : "", "key" : "faf4bfe8019a891c74901b17f4f48cee5cd065d55fdea60118aaf6c4319a0ea5", "iv" : "b776c3fddba7c81362ce6e1b", "aad" : "", "msg" : "8dadff8d60c8e88f604f274833", "ct" : "e6b33a74a4ac443bd93f9c1b94", "tag" : "0c115172bdb02bbad3130fff22790d60", "result" : "valid", "flags" : [] }, { "tcId" : 29, "comment" : "", "key" : "841020d1606edcfc536abfb1a638a7b958e21efc10c386ac45a18493450afd5f", "iv" : "6d62f159731b140eb18ce074", "aad" : "5a8e1c7aa39810d5", "msg" : "d6af138f701b801e60c85ffd5c", "ct" : "b0a7500aca45bb15f01ece4389", "tag" : "0160e83adbec7f6a2ee2ff0215f9ef00", "result" : "valid", "flags" : [] }, { "tcId" : 30, "comment" : "", "key" : "470f9ce3d2250bd60cbbefdb2e6a1178c012299b5590639c7797b6024fa703d8", "iv" : "a9ea4d619fe405d04cba7d7a", "aad" : "", "msg" : "6ca67dd023fba6507b9f9a1f667e", "ct" : "d3017e0bb1705b380b34cc333450", "tag" : "5708e72ca2bd354f487f82f67fbc3acb", "result" : "valid", "flags" : [] }, { "tcId" : 31, "comment" : "", "key" : "e4b97e91e4c8e85eb7ce0a7f30bf8a0abf4468251e4c6386c0e7aacb8e879aa8", "iv" : "0e23c942a0c9fb526586eead", "aad" : "eaaaeab26957f9a1", "msg" : "b84b3f74cd23064bb426fe2ced2b", "ct" : "52e9672b416d84d97033796072d0", "tag" : "e83839dc1fd9b8b9d1444c40e488d493", "result" : "valid", "flags" : [] }, { "tcId" : 32, "comment" : "", "key" : "67119627bd988eda906219e08c0d0d779a07d208ce8a4fe0709af755eeec6dcb", "iv" : "68ab7fdbf61901dad461d23c", "aad" : "", "msg" : "51f8c1f731ea14acdb210a6d973e07", "ct" : "0b29638e1fbdd6df53970be2210042", "tag" : "2a9134087d67a46e79178d0a93f5e1d2", "result" : "valid", "flags" : [] }, { "tcId" : 33, "comment" : "", "key" : "e6f1118d41e4b43fb58221b7ed79673834e0d8ac5c4fa60bbc8bc4893a58894d", "iv" : "d95b3243afaef714c5035b6a", "aad" : "6453a53384632212", "msg" : "97469da667d6110f9cbda1d1a20673", "ct" : "32db66c4a3819d81557455e5980fed", "tag" : "feae30dec94e6ad3a9eea06a0d703917", "result" : "valid", "flags" : [] }, { "tcId" : 34, "comment" : "", "key" : "59d4eafb4de0cfc7d3db99a8f54b15d7b39f0acc8da69763b019c1699f87674a", "iv" : "2fcb1b38a99e71b84740ad9b", "aad" : "", "msg" : "549b365af913f3b081131ccb6b825588", "ct" : "e9110e9f56ab3ca483500ceabab67a13", "tag" : "836ccabf15a6a22a51c1071cfa68fa0c", "result" : "valid", "flags" : [] }, { "tcId" : 35, "comment" : "", "key" : "b907a45075513fe8a8019edee3f2591487b2a030b03c6e1d771c862571d2ea1e", "iv" : "118a6964c2d3e380071f5266", "aad" : "034585621af8d7ff", "msg" : "55a465644f5b650928cbee7c063214d6", "ct" : "e4b113cb775945f3d3a8ae9ec141c00c", "tag" : "7c43f16ce096d0dc27c95849dc383b7d", "result" : "valid", "flags" : [] }, { "tcId" : 36, "comment" : "", "key" : "3b2458d8176e1621c0cc24c0c0e24c1e80d72f7ee9149a4b166176629616d011", "iv" : "45aaa3e5d16d2d42dc03445d", "aad" : "", "msg" : "3ff1514b1c503915918f0c0c31094a6e1f", "ct" : "02cc3acb5ee1fcdd12a03bb857976474d3", "tag" : "d83b7463a2c3800fe958c28eaa290813", "result" : "valid", "flags" : [] }, { "tcId" : 37, "comment" : "", "key" : "f60c6a1b625725f76c7037b48fe3577fa7f7b87b1bd5a982176d182306ffb870", "iv" : "f0384fb876121410633d993d", "aad" : "9aaf299eeea78f79", "msg" : "63858ca3e2ce69887b578a3c167b421c9c", "ct" : "35766488d2bc7c2b8d17cbbb9abfad9e6d", "tag" : "1f391e657b2738dda08448cba2811ceb", "result" : "valid", "flags" : [] }, { "tcId" : 38, "comment" : "", "key" : "37ceb574ccb0b701dd11369388ca27101732339f49d8d908ace4b23af0b7ce89", "iv" : "37270b368f6b1e3e2ca51744", "aad" : "", "msg" : "f26991537257378151f4776aad28ae8bd16b", "ct" : "b621d76a8dacff00b3f840cdf26c894cc5d1", "tag" : "e0a21716ed94c0382fa9b0903d15bb68", "result" : "valid", "flags" : [] }, { "tcId" : 39, "comment" : "", "key" : "68888361919bc10622f45df168e5f6a03bd8e884c0611bea2f34c1882ed9832b", "iv" : "bfd6ff40f2df8ca7845980cc", "aad" : "b8373438ddb2d6c3", "msg" : "ff97f2eefb3401ac31fc8dc1590d1a92cbc1", "ct" : "e0a745186c1a7b147f74faff2a715df5c19d", "tag" : "917baf703e355d4d950e6c05fe8f349f", "result" : "valid", "flags" : [] }, { "tcId" : 40, "comment" : "", "key" : "1b35b856b5a86d3403d28fc2103a631d42deca5175cdb0669a5e5d90b2caafc5", "iv" : "2343de88be6c7196d33b8694", "aad" : "", "msg" : "21ef185c3ae9a96fa5eb473878f4d0b242781d", "ct" : "d6e0ed54fccef30bd605d72da3320e249a9cb5", "tag" : "c68bc6724ec803c43984ce42f6bd09ff", "result" : "valid", "flags" : [] }, { "tcId" : 41, "comment" : "", "key" : "d6484e3973f6be8c83ed3208d5be5cfa06fda72fbfdc5b19d09be3f4e4eba29d", "iv" : "1af1d90e877e11a496efa3df", "aad" : "cc4efd8364fb114a", "msg" : "7335ab04b03e706109ec3ee835db9a246ea0ad", "ct" : "29e54d608237c3c3609dba16e6edf43842d72f", "tag" : "d3365fdcd506aaaa5368661e80e9d99b", "result" : "valid", "flags" : [] }, { "tcId" : 42, "comment" : "", "key" : "422add37849d6e4c3dfd8020dc6a07e8a249788f3d6a83b9cb4d802362c97542", "iv" : "1e7e67be948de7352ffdb727", "aad" : "", "msg" : "d7f5e611dd3a2750fb843fc1b6b93087310dc87d", "ct" : "7fe606652d858f595ec2e706754fa3d933fcc834", "tag" : "78d59235aa5d03a4c32590e590c04d22", "result" : "valid", "flags" : [] }, { "tcId" : 43, "comment" : "", "key" : "cdccfe3f46d782ef47df4e72f0c02d9c7f774def970d23486f11a57f54247f17", "iv" : "376187894605a8d45e30de51", "aad" : "956846a209e087ed", "msg" : "e28e0e9f9d22463ac0e42639b530f42102fded75", "ct" : "14f707c446988a4903775ec7acec6da114d43112", "tag" : "987d4b147c490d43d376a198cab383f0", "result" : "valid", "flags" : [] }, { "tcId" : 44, "comment" : "", "key" : "e79dfc6d2fc465b8439e1c5baccb5d8ef2853899fc19753b397e6c25b35e977e", "iv" : "f9d6320d7ce51d8ed0677d3a", "aad" : "", "msg" : "4f543e7938d1b878dacaeec81dce4899974816813b", "ct" : "1003f13ea1329cbb187316f64c3ff3a87cf5b96661", "tag" : "d2323ad625094bec84790d7958d5583f", "result" : "valid", "flags" : [] }, { "tcId" : 45, "comment" : "", "key" : "1d7b8f1d96a1424923aef8a984869d4a777a110990ba465627acf80396c7f376", "iv" : "50ba1962cdc32a5a2d36e640", "aad" : "093053e20261daab", "msg" : "5d3efd5767f3c12efd08af9a44e028ae68c9eff843", "ct" : "2d48b0834e9ffe3046103ef7a214f02e8e4d33360e", "tag" : "d533ad089be229ea606ec0f3fa22eb33", "result" : "valid", "flags" : [] }, { "tcId" : 46, "comment" : "", "key" : "dd433e28cfbcb5de4ab36a02bf38686d83208771a0e63dcd08b4df1a07ac47a1", "iv" : "c9cc0a1afc38ec6c30c38c68", "aad" : "", "msg" : "8a3e17aba9606dd49e3b1a4d9e5e42f1742373632489", "ct" : "e9917ff3e64bbe1783579375e75ea823976b35539949", "tag" : "074a890669b25105434c75beed3248db", "result" : "valid", "flags" : [] }, { "tcId" : 47, "comment" : "", "key" : "a60924101b42ac24154a88de42142b2334cf599176caf4d1226f712dd9172930", "iv" : "8ba77644b08d65d5e9f31942", "aad" : "b2a4e12a19a61c75", "msg" : "c949957e66439deee4b2ac1d4a6c98a6c527b90f52ab", "ct" : "db4c700513818972b0dc0e531b1c281ca03e40c60dea", "tag" : "63f4478bba2af469a7a4dc3b4f141360", "result" : "valid", "flags" : [] }, { "tcId" : 48, "comment" : "", "key" : "1aa42027836965b1e6086fa137f9cf7f1ff48676696829bd281ff81c8ea0a4a9", "iv" : "4b3dca84ecc407f424f281a9", "aad" : "", "msg" : "37252a3eb5c8960f0567e503a9035783b3d0a19a4b9a47", "ct" : "b5f14617491fc923b683e2cc9562d043dd5986b97dbdbd", "tag" : "972ce54713c05c4bb4d088c0a30cacd3", "result" : "valid", "flags" : [] }, { "tcId" : 49, "comment" : "", "key" : "5d40db0cc18ef2e42815d3b6245a466a0b30a0f93e318ac10edde3bf8ad98160", "iv" : "acad618039b317470d21621b", "aad" : "413036411af75745", "msg" : "959dde1ef3129b27702c558849e466f2baca1a45bdf4b2", "ct" : "b7ca3879f95140bf6a97b3212218b7bf864a51e5bb0b3e", "tag" : "fe558fb570145470ea693eb76eb73171", "result" : "valid", "flags" : [] }, { "tcId" : 50, "comment" : "", "key" : "0212a8de5007ed87b33f1a7090b6114f9e08cefd9607f2c276bdcfdbc5ce9cd7", "iv" : "e6b1adf2fd58a8762c65f31b", "aad" : "", "msg" : "10f1ecf9c60584665d9ae5efe279e7f7377eea6916d2b111", "ct" : "42f26c56cb4be21d9d8d0c80fc99dde00d75f38074bfe764", "tag" : "54aa7e13d48fff7d7557039457040a3a", "result" : "valid", "flags" : [] }, { "tcId" : 51, "comment" : "", "key" : "c5bc09565646e7edda954f1f739223dada20b95c44ab033d0fae4b0283d18be3", "iv" : "6b282ebecc541bcd7834ed55", "aad" : "3e8bc5ade182ff08", "msg" : "9222f9018e54fd6de1200806a9ee8e4cc904d29f25cba193", "ct" : "123032437b4bfd6920e8f7e7e0087ae4889ebe7a0ad0e900", "tag" : "3cf68f179550da63d3b96c2d55411865", "result" : "valid", "flags" : [] }, { "tcId" : 52, "comment" : "", "key" : "9460b3c44ed86e70f3bda66385e1ca10b0c1677ef4f1360532830d17535f996f", "iv" : "abfaf42e0dba884efcf07823", "aad" : "", "msg" : "5c5cce881b93fb7a1b7939af1ffc5f84d3280ada778cca0953", "ct" : "1d218c9f1f9f02f248a6f976a7557057f37d9393d9f213c1f3", "tag" : "bc88344c6fdc898feed394fb28511316", "result" : "valid", "flags" : [] }, { "tcId" : 53, "comment" : "", "key" : "c111d6d5d78a071b15ab37cc8c3819199387ab7c1933aa97b1489f6584ba8e2a", "iv" : "85f18ad8ff72cafee2452ab8", "aad" : "84cdff939391c022", "msg" : "6989c646a10b7c76f4d9f7d574da40e152013cf0dd78f5aa8a", "ct" : "9715d344e8d3f3a3eaa98a9cea57c0cd717c6ef5076027c9ec", "tag" : "3056ff5ee0aa8636bb639984edb5236b", "result" : "valid", "flags" : [] }, { "tcId" : 54, "comment" : "", "key" : "8a1b1e699a0c4a3e610b10902daedab1bf1ea0d505c47d7842cbcee0d3b1b6e6", "iv" : "a6f9a8d335fa84c3b27dcd2a", "aad" : "", "msg" : "ee6a15fc183108f0877e7f2b8a9615f4b3fc36e1c83440f66aad", "ct" : "9089bbdb8bcfd124e227bf75c4bfe1cba2004a274fc31aa32358", "tag" : "fd2e21c64a019621c68594826cd7b1cd", "result" : "valid", "flags" : [] }, { "tcId" : 55, "comment" : "", "key" : "74b384e6e013ec4172ed7a28a10fb9bb79b4be2a24f6999e3d3caa28e64a8656", "iv" : "ebc19fc9ecb2339908ea3836", "aad" : "85073f2edc13d3a1", "msg" : "3aa9f7372f056e5a0729752d9a37132d6dd07c56792e1c7582a9", "ct" : "796ffb70ab43e7fa79f95583e384524727bb3e47fc45b969f714", "tag" : "c3322b4445de5f3c9f18dcc847cc94c3", "result" : "valid", "flags" : [] }, { "tcId" : 56, "comment" : "", "key" : "77d824795d2029f0eb0e0baab5cfeb32f7e93474913a7f95c737a667a3c33314", "iv" : "f3307430f492d2b8a72d3a81", "aad" : "", "msg" : "0c4179a497d8fdd72796fb725692b805d63b7c718359cf10518aee", "ct" : "49c81d17d67d7ba9954f497d0b0ddc21f3f839c9d2cc198d30bc2c", "tag" : "50009899e5b2a9726c8f3556cadfbe84", "result" : "valid", "flags" : [] }, { "tcId" : 57, "comment" : "", "key" : "bec5eac68f893951cbd7d1ecd3ee6611130dd9c3f80cddf95111d07d5edd76d1", "iv" : "342ada4f0c115124b222df80", "aad" : "73365f6d80edb1d8", "msg" : "481433d8b1cd38af4a750e13a64b7a4e8507682b3517595938a20e", "ct" : "4c129fc13cbdd9d3fe81ac755bf4fbea2fdd7e0aca0505a6ee9637", "tag" : "9cede1d30a03db5d55265d3648bc40d4", "result" : "valid", "flags" : [] }, { "tcId" : 58, "comment" : "", "key" : "a59c1e13064df8f2b8df77a492b0ca2eae921b52a84b305a3a9a51408a9ecb69", "iv" : "9544d41ece0c92ef01cfac2d", "aad" : "", "msg" : "1c35b898821ba55c2617c25df9e6df2a8002b384902186cd69dfd20e", "ct" : "a6fa8f57ddc81d6099f667dd62402b6a5d5b7d05a329298029113169", "tag" : "bb24e38b31dbbc3e575b9e3ee076af2a", "result" : "valid", "flags" : [] }, { "tcId" : 59, "comment" : "", "key" : "084b5d7365f1a8fec6365939ed741e6ea5893e0318d82ab47500a97d77aaa041", "iv" : "829f005e980f0a6e2f983eaa", "aad" : "770f6e6e89a3fe8e", "msg" : "7510016efadc385a71ed689ceb590c8ea9cc1e81b793338bddf5f10c", "ct" : "fd42cb5cf894f879e3cf751662aaa58a2288cc53548802becaf42359", "tag" : "188329438afe1cd7225d0478aa90c773", "result" : "valid", "flags" : [] }, { "tcId" : 60, "comment" : "", "key" : "5a7f850a1d9aafa77d59ae1b731965e8aaec6352280fc76a7b5e23ef3610cfe4", "iv" : "4946a0d6adea93b82d4332e5", "aad" : "", "msg" : "3c161d791f624fb0388e808f0f69ed790dbe4cbd089ebac46627bcf01d", "ct" : "402302b56140c4dcc39774732c55883de124ce4bf0a0261cfa1569e2cf", "tag" : "e830bfe933a96786cff2dd72b82c4bd5", "result" : "valid", "flags" : [] }, { "tcId" : 61, "comment" : "", "key" : "e6d5a4246f6f05618b59c8f9ec3ac8068cc0d3f351c571aa52b09cb251f9c2f6", "iv" : "2f90a65e9e48725de6ffc727", "aad" : "f2415377ad283fd8", "msg" : "964fc9e0e8355947aa1c2caadd7b3dbef82a1024e623606fac436ef573", "ct" : "d052932bad6e6c4f835f02019e52d7ff807dc2a5aac2040883c79dd3d5", "tag" : "655f93396b4d755dc4475721665fed91", "result" : "valid", "flags" : [] }, { "tcId" : 62, "comment" : "", "key" : "09e822123adbb1ed89b79a58619c64853992f8371d46338712f6c91ab11a68bb", "iv" : "a797205a6cacdd7e47a4789d", "aad" : "", "msg" : "80b71bbe833629841bd3aeaeb9db6123e51d367b436fe9d2d3454b62cfad", "ct" : "83f5c77396cabd28dfcc002cba0756d4ea5455e0261d847d5708aac21e8d", "tag" : "705a05820a21f381d244d40e58d2f16b", "result" : "valid", "flags" : [] }, { "tcId" : 63, "comment" : "", "key" : "625735fe7f8fc81b0c1edc3d08a78b41268f87a3c68488b674222630c1d587a5", "iv" : "9d8cdf289dddd09afdc1b02f", "aad" : "200a9c95946ff05c", "msg" : "67ae1882d0b1c1b2485bec98115ecf53b9b438deb1d0400531705038873a", "ct" : "209b7539385c8b19ecd0fd8b5011b2996e316f1942064e68edfa363acbcd", "tag" : "fa2f454b9fa2608f780f7c6f9b780fe1", "result" : "valid", "flags" : [] }, { "tcId" : 64, "comment" : "", "key" : "2eb51c469aa8eb9e6c54a8349bae50a20f0e382711bba1152c424f03b6671d71", "iv" : "04a9be03508a5f31371a6fd2", "aad" : "", "msg" : "b053999286a2824f42cc8c203ab24e2c97a685adcc2ad32662558e55a5c729", "ct" : "45c7d6b53acad4abb68876a6e96a48fb59524d2c92c9d8a189c9fd2db91746", "tag" : "566d3ca10e311b695f3eae1551652493", "result" : "valid", "flags" : [] }, { "tcId" : 65, "comment" : "", "key" : "7f5b74c07ed1b40fd14358fe2ff2a740c116c7706510e6a437f19ea49911cec4", "iv" : "470a339ecb3219b8b81a1f8b", "aad" : "374618a06ea98a48", "msg" : "f45206abc25552b2abc9ab7fa243035fedaaddc3b2293956f1ea6e7156e7eb", "ct" : "46a80c4187024720084627580080dde5a3f4a11093a7076ed6f3d326bc7b70", "tag" : "534d4aa2835a52e72d14df0e4f47f25f", "result" : "valid", "flags" : [] }, { "tcId" : 66, "comment" : "", "key" : "e1731d5854e1b70cb3ffe8b786a2b3ebf0994370954757b9dc8c7bc5354634a3", "iv" : "72cfd90ef3026ca22b7e6e6a", "aad" : "", "msg" : "b9c554cbc36ac18ae897df7beecac1dbeb4eafa156bb60ce2e5d48f05715e678", "ct" : "ea29afa49d36e8760f5fe19723b9811ed5d519934a440f5081ac430b953b0e21", "tag" : "222541af46b86533c6b68d2ff108a7ea", "result" : "valid", "flags" : [] }, { "tcId" : 67, "comment" : "", "key" : "27d860631b0485a410702fea61bc873f3442260caded4abde25b786a2d97f145", "iv" : "262880d475f3dac5340dd1b8", "aad" : "2333e5ce0f93b059", "msg" : "6b2604996cd30c14a13a5257ed6cffd3bc5e29d6b97eb1799eb335e281ea451e", "ct" : "6dad637897544d8bf6be9507ed4d1bb2e954bc427e5de729daf50762846ff2f4", "tag" : "7b997d93c982189d7095dc794c746232", "result" : "valid", "flags" : [] }, { "tcId" : 68, "comment" : "", "key" : "5155dee9aade1cc61ee7e3f92660f7590f5e5ba82f1b59b850e3fa453d2fa6b3", "iv" : "c26c4b3bfdb97ee6b0f63ca1", "aad" : "", "msg" : "2734e08eff8f5c4f84fa0c207f49c7fd78af1ad5123ff81f83f500edf4eda09edf", "ct" : "f5982b601c7a18fc72a65b218c44974dc564d8314cbe6f87fcf6c6cfbe618b34b1", "tag" : "c43632f55760b5d1ed37556a94d049b5", "result" : "valid", "flags" : [] }, { "tcId" : 69, "comment" : "", "key" : "573f08ebbe0cce4ac9618e8c3b224bea0a32f055c6996838a32f527ca3c3b695", "iv" : "ad8050dc6d122dce3e5639ed", "aad" : "e99698241c599b5f", "msg" : "668d5e3f95fe030daf432a5fc5837af3a79c81e94b28d8204c5ee262ab3c9908a7", "ct" : "eaf6810e6ec1cb7a2918856257d1aa3d51a827879146c6337ecf535e9c89b149c5", "tag" : "a2950c2f394a3466c345f796323c1aa7", "result" : "valid", "flags" : [] }, { "tcId" : 70, "comment" : "", "key" : "cf0d40a4644e5f51815165d5301b22631f4544c49a1878e3a0a5e8e1aae0f264", "iv" : "e74a515e7e2102b90bef55d2", "aad" : "", "msg" : "973d0c753826bae466cf9abb3493152e9de7819e2bd0c71171346b4d2cebf8041aa3cedc0dfd7b467e26228bc86c9a", "ct" : "fba78ae4f9d808a62e3da40be2cb7700c3613d9eb2c529c652e76a432c658d27095f0eb8f940c324981ea935e507f9", "tag" : "8f046956db3a512908bd7afc8f2ab0a9", "result" : "valid", "flags" : [] }, { "tcId" : 71, "comment" : "", "key" : "6cbfd71c645d184cf5d23c402bdb0d25ec54898c8a0273d42eb5be109fdcb2ac", "iv" : "d4d807341683825b31cd4d95", "aad" : "b3e4064683b02d84", "msg" : "a98995504df16f748bfb7785ff91eeb3b660ea9ed3450c3d5e7b0e79ef653659a9978d75542ef91c456762215640b9", "ct" : "a1ffed80761829ecce242e0e88b138049016bca018da2b6e19986b3e318cae8d806198fb4c527cc39350ebddeac573", "tag" : "c4cbf0befda0b70242c640d7cd02d7a3", "result" : "valid", "flags" : [] }, { "tcId" : 72, "comment" : "", "key" : "5b1d1035c0b17ee0b0444767f80a25b8c1b741f4b50a4d3052226baa1c6fb701", "iv" : "d61040a313ed492823cc065b", "aad" : "", "msg" : "d096803181beef9e008ff85d5ddc38ddacf0f09ee5f7e07f1e4079cb64d0dc8f5e6711cd4921a7887de76e2678fdc67618f1185586bfea9d4c685d50e4bb9a82", "ct" : "9a4ef22b181677b5755c08f747c0f8d8e8d4c18a9cc2405c12bb51bb1872c8e8b877678bec442cfcbb0ff464a64b74332cf072898c7e0eddf6232ea6e27efe50", "tag" : "9ff3427a0f32fa566d9ca0a78aefc013", "result" : "valid", "flags" : [] }, { "tcId" : 73, "comment" : "", "key" : "97d635c4f47574d9998a90875da1d3a284b755b2d39297a5725235190e10a97e", "iv" : "d31c21aba175b70de4ebb19c", "aad" : "7193f623663321a2", "msg" : "94ee166d6d6ecf8832437136b4ae805d428864359586d9193a25016293edba443c58e07e7b7195ec5bd84582a9d56c8d4a108c7d7ce34e6c6f8ea1bec0567317", "ct" : "5fbbdecc34be201614f636031eeb42f1cace3c79a12cffd871ee8e73820c829749f1abb4294367849fb6c2aa56bda8a3078f723d7c1c852024b017b58973fb1e", "tag" : "09263da7b4cb921452f97dca40f580ec", "result" : "valid", "flags" : [] }, { "tcId" : 74, "comment" : "", "key" : "fe6e55bdaed1f7284ca5fc0f8c5f2b8df56dc0f49e8ca66a41995e783351f901", "iv" : "17c86a8abbb7e003acde2799", "aad" : "", "msg" : "b429eb80fb8fe8baeda0c85b9c333458e7c2992e558475069d12d45c22217564121588032297eff56783742a5fc22d7410ffb29d66098661d76f126c3c27689e43b37267cac5a3a6d3ab49e391da29cd3054a5692e2807e4c3ea46c8761d50f592", "ct" : "d0102f6c258bf49742cec34cf2d0fedf23d105fb4c84cf98515e1bc9a64f8ad5be8f0721bde50645d00083c3a263a31053b760245f52ae2866a5ec83b19f61be1d30d5c5d9fecc4cbbe08fd385813a2aa39a00ff9c10f7f23702add1e4b2ffa31c", "tag" : "41865fc71de12b19612127ce49993bb0", "result" : "valid", "flags" : [] }, { "tcId" : 75, "comment" : "", "key" : "aabc063474e65c4c3e9bdc480dea97b45110c8618846ff6b15bdd2a4a5682c4e", "iv" : "46362f45d6379e63e5229460", "aad" : "a11c40b603767330", "msg" : "ceb534ce50dc23ff638ace3ef63ab2cc2973eeada80785fc165d06c2f5100ff5e8ab2882c475afcd05ccd49f2e7d8f55ef3a72e3dc51d6852b8e6b9e7aece57be6556b0b6d9413e33fc5fc24a9a205ad59574bb39d944a92dc47970d84a6ad3176", "ct" : "7545391b51de01d5c53dfaca777909063e58edee4bb1227e7110ac4d2620c2aec2f848f56deeb037a8dced75afa8a6c890e2dee42f950bb33d9e2424d08a505d899563973ed38870f3de6ee2adc7fe072c366c14e2cf7ca62fb3d36bee11685461", "tag" : "b70d44ef8c66c5c7bbf10dcadd7facf6", "result" : "valid", "flags" : [] }, { "tcId" : 76, "comment" : "", "key" : "d7addd3889fadf8c893eee14ba2b7ea5bf56b449904869615bd05d5f114cf377", "iv" : "8a3ad26b28cd13ba6504e260", "aad" : "", "msg" : "c877a76bf595560772167c6e3bcc705305db9c6fcbeb90f4fea85116038bc53c3fa5b4b4ea0de5cc534fbe1cf9ae44824c6c2c0a5c885bd8c3cdc906f12675737e434b983e1e231a52a275db5fb1a0cac6a07b3b7dcb19482a5d3b06a9317a54826cea6b36fce452fa9b5475e2aaf25499499d8a8932a19eb987c903bd8502fe", "ct" : "294a764c03353f5f4f6e93cd7e977480d6c343071db0b7c1f0db1e95b85e6053f0423168a9c7533268db9a194e7665359d14489bc47172a9f21370e89b0bd0e5ef9661738de282572bcc3e541247626e57e75dec0f91ac5c530bd1a53271842996dcd04d865321b1ecb6e7630114fe780291b8dc3e5d0abc8e65b1c5493e9af0", "tag" : "f2b974ca0f14fb9f92014bff18573cff", "result" : "valid", "flags" : [] }, { "tcId" : 77, "comment" : "", "key" : "80be86fb6fc49bc73428cab576f6ad72ff6aca04001b8b1c57a7128be73900aa", "iv" : "903188433c1ce8971aa19b9d", "aad" : "0587af8530ad0547", "msg" : "67ce499cd8ed68bd717dfe61c60f27d260b1c163a72e8cc8597253d3d987c2dbe1bff2e44d9bd4765d3e53d9c3f8eb3b90e751f47c7157bdc1142bc33f5833ac1cd1262cbb239066b334a4ed99ae82c74f2b49540f1a614bc239d8fc5add8c178184e41281f6e66c5c3117fd953547f7c829425b5082aa69686847eaf5784692", "ct" : "2b90b4f3de280c44913d1984bdd5dfa0566c6a14a058659a9b623277b0bb6e82101e79395d12e643f62d9a822bae497907493e4f8213fcf99da8a78fdf867af36bc8b0931c1886b4f0ae5729986494dbd59737e956cd8f226c7c522689d082f023894d54acab0c4d609f3746a67369bb8876008f7fd3dc6681c5fb9d728c5911", "tag" : "f005ebe1c1ada75a9cee8d630881d5b8", "result" : "valid", "flags" : [] }, { "tcId" : 78, "comment" : "", "key" : "7d00b48095adfa3272050607b264185002ba99957c498be022770f2ce2f3143c", "iv" : "87345f1055fd9e2102d50656", "aad" : "02", "msg" : "e5ccaa441bc814688f8f6e8f28b500b2", "ct" : "7e72f5a185af16a611921b438f749f0b", "tag" : "1242c670732334029adfe1c5001651e4", "result" : "valid", "flags" : [] }, { "tcId" : 79, "comment" : "", "key" : "6432717f1db85e41ac7836bce25185a080d5762b9e2b18444b6ec72c3bd8e4dc", "iv" : "87a3163ec0598ad95b3aa713", "aad" : "b648", "msg" : "02cde168fba3f544bbd0332f7adeada8", "ct" : "85f29a719557cdd14d1f8fffab6d9e60", "tag" : "732ca32becd515a1ed353f542e999858", "result" : "valid", "flags" : [] }, { "tcId" : 80, "comment" : "", "key" : "7afa0f59dfcb5ad3a76490c5c804327c8d052be737a60fa8bcbf0a2c36630a43", "iv" : "25b7bdf4a6dcbf7c9a3ec2b3", "aad" : "8b71ac", "msg" : "623e6ba6d3166a338bfcc7af90a230c8", "ct" : "d46e8265a8c6a25393dd956bb44397ad", "tag" : "e28f3ad9e3ef4a3d94ee07bf538eaafb", "result" : "valid", "flags" : [] }, { "tcId" : 81, "comment" : "", "key" : "2ec25b0ec7ac244224e9c7fc2fa5d3ef17809e19fd6e954158dd0d72738a4cc8", "iv" : "6fb0d1417cdfff4df37db08c", "aad" : "3a5ddf40", "msg" : "a1c933768a6d573ebf68a99e5e18dae8", "ct" : "2d3cb2d9303491e264f2904f0e0753f4", "tag" : "6c1db959362d217b2322b466536bfea0", "result" : "valid", "flags" : [] }, { "tcId" : 82, "comment" : "", "key" : "0a2cf52371cf9d9f95b10108fc82b4fd6110a8ba9a88a26083685ad29826891a", "iv" : "2538fc67afb9eab333f83290", "aad" : "9eec540bb0", "msg" : "0d8c691d044a3978d790432dc71d69f8", "ct" : "a988c03c71b956ff086d0470d706bd34", "tag" : "b35d7cbf2beb894b0c746e0730429e15", "result" : "valid", "flags" : [] }, { "tcId" : 83, "comment" : "", "key" : "307e886b38bb18b445f8a2c6d6f8932492a9cea8d041ba72eb5efdfa70d0b8d2", "iv" : "a071be999151e2a1c41c81e9", "aad" : "56e014d97c74", "msg" : "9aba22b495cb7ec887ddaa62019aa14d", "ct" : "32bf95d4c195dbaf58d9af4001c6e57d", "tag" : "4393808703d67a90870578046cd8b525", "result" : "valid", "flags" : [] }, { "tcId" : 84, "comment" : "", "key" : "dacd51a8a8e4d5905b4cbb947ef4013eb296889353f3c9ee35f5577b26737a51", "iv" : "3fa378a1befdddd61ae68cf4", "aad" : "bb5a3812f0aefd", "msg" : "e148313883a77da121124d06b1c77dca", "ct" : "2a207ca7e9da6b13a229604304d87eb1", "tag" : "8a6b6afec87d93ec6e8dbe13d84c0f8c", "result" : "valid", "flags" : [] }, { "tcId" : 85, "comment" : "", "key" : "7b5fbbb202c16108fd13066446853a850d8b34e9da40519580da446a922f9162", "iv" : "aa077a5ce9161bde8d8edc40", "aad" : "f94bb92c1c668a695b", "msg" : "da471cd6935a0ca8307ddedc6b959962", "ct" : "548a5ca0ae49211cdf30bbdcb1352d31", "tag" : "204dacb98f8c8908cc5ea22bb23f901f", "result" : "valid", "flags" : [] }, { "tcId" : 86, "comment" : "", "key" : "1ffd101eb97531f6faa821ec4d5c5702725dd033d3b830bb760c4ef27ba983df", "iv" : "598114e8cf7fbdea8ad29683", "aad" : "2155627ec15a978fbcb2", "msg" : "28668ca8db535c7e8eb27491ad0fb7cb", "ct" : "28cedac24f14caa326c7fe401f68a87c", "tag" : "2bf1b2c43d3039f8f5ce359c1102f879", "result" : "valid", "flags" : [] }, { "tcId" : 87, "comment" : "", "key" : "d2d0a973d5951af352cbee57ac9dab1c284c99af3b992ce015f219506f64888d", "iv" : "9acd213570ce9bb9d886c6ef", "aad" : "37ad668d4d4fe889949763", "msg" : "3f3f0076250352e1b6b5c12cfa12625e", "ct" : "7256e856872ad3a54b34a2a6bdca8838", "tag" : "3b12e4586e45223f78a6eea811efb863", "result" : "valid", "flags" : [] }, { "tcId" : 88, "comment" : "", "key" : "adcc520b381382237d05a6400a7dfbcd0771b6aa9edb7966131ddef6af21f1be", "iv" : "9183cdf3a8ba7397b6b2d5d5", "aad" : "b334375415f6215c0bf89a9a", "msg" : "958295619cf1b36f0b474663c0bc79eb", "ct" : "852c141b4239a31feeda03550d70a2be", "tag" : "5fc59287b92d3fcf7d66f13defb11b0d", "result" : "valid", "flags" : [] }, { "tcId" : 89, "comment" : "", "key" : "bd534f7adeca466844fb3ba34658be807f15c5291ed6026860a24f179b712c89", "iv" : "412c3e13ee1f7864bd15ce39", "aad" : "2866afff0bcc6135dc63af88c8", "msg" : "d92f8ce5d8d0ad2eb5f11af02ef63949", "ct" : "89d6d089c4a255952aca11b24a01ff95", "tag" : "f88fa4531204da315e7317970240ce9e", "result" : "valid", "flags" : [] }, { "tcId" : 90, "comment" : "", "key" : "910ade7d324d2c9688439e1f142e0e5f9d130ff832e507fe1985e5a26452a6d0", "iv" : "9be090dba93deff27adf99ee", "aad" : "ea2575f123268e936c8e4c8c1bb8", "msg" : "6e356094ed9d9a7053c7906c48ba3d9f", "ct" : "01ffb343c757b27843d8a900a36ce39d", "tag" : "a315541b7d6313c6fddf64b303d71d60", "result" : "valid", "flags" : [] }, { "tcId" : 91, "comment" : "", "key" : "8e34cf73d245a1082a920b86364eb896c4946467bcb3d58929fcb36690e6394f", "iv" : "6f573aa86baa492ba46596df", "aad" : "bd4cd02fc7502bbdbdf6c9a3cbe8f0", "msg" : "16ddd23ff53f3d23c06334487040eb47", "ct" : "c1b295936d56fadac03e5f742bff73a1", "tag" : "39c457dbab66382babb3b55800cda5b8", "result" : "valid", "flags" : [] }, { "tcId" : 92, "comment" : "", "key" : "cb5575f5c7c45c91cf320b139fb594237560d0a3e6f865a67d4f633f2c08f016", "iv" : "1a6518f02ede1da6809266d9", "aad" : "89cce9fb47441d07e0245a66fe8b778b", "msg" : "623b7850c321e2cf0c6fbcc8dfd1aff2", "ct" : "c84c9bb7c61c1bcb17772a1c500c5095", "tag" : "dbadf7a5138ca03459a2cd65831e092f", "result" : "valid", "flags" : [] }, { "tcId" : 93, "comment" : "", "key" : "a5569e729a69b24ba6e0ff15c4627897436824c941e9d00b2e93fddc4ba77657", "iv" : "564dee49ab00d240fc1068c3", "aad" : "d19f2d989095f7ab03a5fde84416e00c0e", "msg" : "87b3a4d7b26d8d3203a0de1d64ef82e3", "ct" : "94bc80621ed1e71b1fd2b5c3a15e3568", "tag" : "333511861796978401598b963722f5b3", "result" : "valid", "flags" : [] }, { "tcId" : 94, "comment" : "", "key" : "56207465b4e48e6d04630f4a42f35cfc163ab289c22a2b4784f6f9290330bee0", "iv" : "df8713e87ec3dbcfad14d53e", "aad" : "5e6470facd99c1d81e37cd44015fe19480a2a4d3352a4ff560c0640fdbda", "msg" : "e601b38557797da2f8a4106a089d1da6", "ct" : "299b5d3f3d03c087209a16e285143111", "tag" : "4b454ed198de117e83ec49fa8d8508d6", "result" : "valid", "flags" : [] }, { "tcId" : 95, "comment" : "", "key" : "077433022ab34d380fc192fc24c2edc6301fec6f24442f572a1087ff2e05b39a", "iv" : "28adcbc74364f26dd4b3108b", "aad" : "e0100eb116cdc5e22a3b9f9b4126c149595e75107f6e237c69e82960052270", "msg" : "03c874eeaaa6fa9f0da62c758fb0ad04", "ct" : "1e9687b35fbc8eaa1825ed3847798f76", "tag" : "0788bf70fd04030ecd1c96d0bc1fcd5d", "result" : "valid", "flags" : [] }, { "tcId" : 96, "comment" : "", "key" : "3937986af86dafc1ba0c4672d8abc46c207062682d9c264ab06d6c5807205130", "iv" : "8df4b15a888c33286a7b7651", "aad" : "ba446f6f9a0ced22450feb10737d9007fd69abc19b1d4d9049a5551e86ec2b37", "msg" : "dc9e9eaf11e314182df6a4eba17aec9c", "ct" : "605bbf90aeb974f6602bc778056f0dca", "tag" : "38ea23d99054b46b42ffe004129d2204", "result" : "valid", "flags" : [] }, { "tcId" : 97, "comment" : "", "key" : "36372abcdb78e0279646ac3d176b9674e9154eecf0d5469c651ec7e16b4c1199", "iv" : "be40e5f1a11817a0a8fa8949", "aad" : "d41a828d5e71829247021905402ea257dccbc3b80fcd5675056b68bb59e62e8873", "msg" : "81ce84ede9b35859cc8c49a8f6be7dc6", "ct" : "7b7ce0d824809a70de32562ccf2c2bbd", "tag" : "15d44a00ce0d19b4231f921e22bc0a43", "result" : "valid", "flags" : [] }, { "tcId" : 98, "comment" : "", "key" : "9f1479ed097d7fe529c11f2f5add9aaff4a1ca0b68997a2cb7f79749bd90aaf4", "iv" : "84c87dae4eee27730ec35d12", "aad" : "3f2dd49bbf09d69a78a3d80ea2566614fc379474196c1aae84583da73d7ff85c6f42ca42056a9792cc1b9fb3c7d261", "msg" : "a66747c89e857af3a18e2c79500087ed", "ct" : "ca82bff3e2f310ccc976672c4415e69b", "tag" : "57638c62a5d85ded774f913c813ea032", "result" : "valid", "flags" : [] }, { "tcId" : 99, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000000000000000000000000000000", "msg" : "65b63bf074b7283992e24b1ac0df0d22b555dbe2254d94a43f1de748d3cc6f0d", "ct" : "0000000000000000000000000000000000000000000000000000000000000000", "tag" : "39f4fce3026d83789ffd1ee6f2cd7c4f", "result" : "valid", "flags" : [] }, { "tcId" : 100, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000000000000000000000000000000", "msg" : "65b63bf074b7283992e24b1ac0df0d22b555dbe2254d94a43f1de748d3cc6f0d20c142fe898fbbe668d4324394434c1b18b58ead710aed9c31db1f2a8a1f1bb2", "ct" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "tag" : "f5eaa804605c3a4785f9d7f13b6f67d6", "result" : "valid", "flags" : [] }, { "tcId" : 101, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000000000000000000000000000000", "msg" : "65b63bf074b7283992e24b1ac0df0d22b555dbe2254d94a43f1de748d3cc6f0d20c142fe898fbbe668d4324394434c1b18b58ead710aed9c31db1f2a8a1f1bb24405c183af94ee1ad630cd931158a6213d48c8fff10d0a1f9ef760188e658802aad55e41a1d99069a18db55c56af7c10a6f21ecc8af9b7ce0a7ea0b67426e925", "ct" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "tag" : "9b5c43a78d954e8a3c659eebc13d5d55", "result" : "valid", "flags" : [] }, { "tcId" : 102, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffffffffffffffffffffffffffffff", "msg" : "9a49c40f8b48d7c66d1db4e53f20f2dd4aaa241ddab26b5bc0e218b72c3390f2", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "37e3399d9ca696799f08f4f72bc0cdd8", "result" : "valid", "flags" : [] }, { "tcId" : 103, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffffffffffffffffffffffffffffff", "msg" : "9a49c40f8b48d7c66d1db4e53f20f2dd4aaa241ddab26b5bc0e218b72c3390f2df3ebd0176704419972bcdbc6bbcb3e4e74a71528ef51263ce24e0d575e0e44d", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "3d52710bec86d4ea9fea2ff269549191", "result" : "valid", "flags" : [] }, { "tcId" : 104, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffffffffffffffffffffffffffffff", "msg" : "9a49c40f8b48d7c66d1db4e53f20f2dd4aaa241ddab26b5bc0e218b72c3390f2df3ebd0176704419972bcdbc6bbcb3e4e74a71528ef51263ce24e0d575e0e44dbbfa3e7c506b11e529cf326ceea759dec2b737000ef2f5e061089fe7719a77fd552aa1be5e266f965e724aa3a95083ef590de13375064831f5815f498bd916da", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "51356329e280b12d55d3d98f0a580cbe", "result" : "valid", "flags" : [] }, { "tcId" : 105, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000080000000800000008000000080", "msg" : "65b63b7074b728b992e24b9ac0df0da2b555db62254d94243f1de7c8d3cc6f8d", "ct" : "0000008000000080000000800000008000000080000000800000008000000080", "tag" : "c152a4b90c548c71dc479edeaf9211bf", "result" : "valid", "flags" : [] }, { "tcId" : 106, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000080000000800000008000000080", "msg" : "65b63b7074b728b992e24b9ac0df0da2b555db62254d94243f1de7c8d3cc6f8d20c1427e898fbb6668d432c394434c9b18b58e2d710aed1c31db1faa8a1f1b32", "ct" : "00000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080", "tag" : "40ef6383052d91c2e4b4611b0e32c5ff", "result" : "valid", "flags" : [] }, { "tcId" : 107, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000080000000800000008000000080", "msg" : "65b63b7074b728b992e24b9ac0df0da2b555db62254d94243f1de7c8d3cc6f8d20c1427e898fbb6668d432c394434c9b18b58e2d710aed1c31db1faa8a1f1b324405c103af94ee9ad630cd131158a6a13d48c87ff10d0a9f9ef760988e658882aad55ec1a1d990e9a18db5dc56af7c90a6f21e4c8af9b74e0a7ea0367426e9a5", "ct" : "0000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080", "tag" : "ae9b542541e84fc74542eed6be638fee", "result" : "valid", "flags" : [] }, { "tcId" : 108, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "80000000800000008000000080000000", "msg" : "e5b63bf0f4b7283912e24b1a40df0d223555dbe2a54d94a4bf1de74853cc6f0d", "ct" : "8000000080000000800000008000000080000000800000008000000080000000", "tag" : "10fee3ecfba9cdf797bae37a626ec83b", "result" : "valid", "flags" : [] }, { "tcId" : 109, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "80000000800000008000000080000000", "msg" : "e5b63bf0f4b7283912e24b1a40df0d223555dbe2a54d94a4bf1de74853cc6f0da0c142fe098fbbe6e8d4324314434c1b98b58eadf10aed9cb1db1f2a0a1f1bb2", "ct" : "80000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000", "tag" : "7490795bdbbbf5d0aecb9a4f65aa379f", "result" : "valid", "flags" : [] }, { "tcId" : 110, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "80000000800000008000000080000000", "msg" : "e5b63bf0f4b7283912e24b1a40df0d223555dbe2a54d94a4bf1de74853cc6f0da0c142fe098fbbe6e8d4324314434c1b98b58eadf10aed9cb1db1f2a0a1f1bb2c405c1832f94ee1a5630cd939158a621bd48c8ff710d0a1f1ef760180e6588022ad55e4121d99069218db55cd6af7c1026f21ecc0af9b7ce8a7ea0b6f426e925", "ct" : "8000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000", "tag" : "1d1096a8ca9e2bda2762c41d5b16f62f", "result" : "valid", "flags" : [] }, { "tcId" : 111, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffff7fffffff7fffffff7fffffff7f", "msg" : "9a49c48f8b48d7466d1db4653f20f25d4aaa249ddab26bdbc0e218372c339072", "ct" : "ffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7f", "tag" : "af8492c792bf8d8062be74ff6efb3869", "result" : "valid", "flags" : [] }, { "tcId" : 112, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffff7fffffff7fffffff7fffffff7f", "msg" : "9a49c48f8b48d7466d1db4653f20f25d4aaa249ddab26bdbc0e218372c339072df3ebd8176704499972bcd3c6bbcb364e74a71d28ef512e3ce24e05575e0e4cd", "ct" : "ffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7f", "tag" : "f24db68c46b67d6f402fa6c897913368", "result" : "valid", "flags" : [] }, { "tcId" : 113, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffff7fffffff7fffffff7fffffff7f", "msg" : "9a49c48f8b48d7466d1db4653f20f25d4aaa249ddab26bdbc0e218372c339072df3ebd8176704499972bcd3c6bbcb364e74a71d28ef512e3ce24e05575e0e4cdbbfa3efc506b116529cf32eceea7595ec2b737800ef2f56061089f67719a777d552aa13e5e266f165e724a23a950836f590de1b3750648b1f5815fc98bd9165a", "ct" : "ffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7f", "tag" : "43f651ab2e2eb0f04bf689a40d32da24", "result" : "valid", "flags" : [] }, { "tcId" : 114, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "7fffffff7fffffff7fffffff7fffffff", "msg" : "1a49c40f0b48d7c6ed1db4e5bf20f2ddcaaa241d5ab26b5b40e218b7ac3390f2", "ct" : "7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff", "tag" : "60d95294a3694cfaa64b2f63bc1f82ec", "result" : "valid", "flags" : [] }, { "tcId" : 115, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "7fffffff7fffffff7fffffff7fffffff", "msg" : "1a49c40f0b48d7c6ed1db4e5bf20f2ddcaaa241d5ab26b5b40e218b7ac3390f25f3ebd01f6704419172bcdbcebbcb3e4674a71520ef512634e24e0d5f5e0e44d", "ct" : "7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff", "tag" : "beaca0b47027196176186d944019c1c8", "result" : "valid", "flags" : [] }, { "tcId" : 116, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "7fffffff7fffffff7fffffff7fffffff", "msg" : "1a49c40f0b48d7c6ed1db4e5bf20f2ddcaaa241d5ab26b5b40e218b7ac3390f25f3ebd01f6704419172bcdbcebbcb3e4674a71520ef512634e24e0d5f5e0e44d3bfa3e7cd06b11e5a9cf326c6ea759de42b737008ef2f5e0e1089fe7f19a77fdd52aa1bede266f96de724aa3295083efd90de133f506483175815f490bd916da", "ct" : "7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff", "tag" : "d4811028a577d4dd69d6b35d717f73e3", "result" : "valid", "flags" : [] }, { "tcId" : 117, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000000ffffffff00000000ffffffff", "msg" : "65b63bf08b48d7c692e24b1a3f20f2ddb555dbe2dab26b5b3f1de7482c3390f2", "ct" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", "tag" : "10fb61272b555bee104f5a71818716d6", "result" : "valid", "flags" : [] }, { "tcId" : 118, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000000ffffffff00000000ffffffff", "msg" : "65b63bf08b48d7c692e24b1a3f20f2ddb555dbe2dab26b5b3f1de7482c3390f220c142fe7670441968d432436bbcb3e418b58ead8ef5126331db1f2a75e0e44d", "ct" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", "tag" : "4756764e59583504182877d8c33120f0", "result" : "valid", "flags" : [] }, { "tcId" : 119, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "00000000ffffffff00000000ffffffff", "msg" : "65b63bf08b48d7c692e24b1a3f20f2ddb555dbe2dab26b5b3f1de7482c3390f220c142fe7670441968d432436bbcb3e418b58ead8ef5126331db1f2a75e0e44d4405c183506b11e5d630cd93eea759de3d48c8ff0ef2f5e09ef76018719a77fdaad55e415e266f96a18db55ca95083efa6f21ecc750648310a7ea0b68bd916da", "ct" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", "tag" : "95a2b12a4a280089d4bd4f904253e754", "result" : "valid", "flags" : [] }, { "tcId" : 120, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffffff00000000ffffffff00000000", "msg" : "9a49c40f74b728396d1db4e5c0df0d224aaa241d254d94a4c0e218b7d3cc6f0d", "ct" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000", "tag" : "60dcd45974bebe032eb7b86c9d063452", "result" : "valid", "flags" : [] }, { "tcId" : 121, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffffff00000000ffffffff00000000", "msg" : "9a49c40f74b728396d1db4e5c0df0d224aaa241d254d94a4c0e218b7d3cc6f0ddf3ebd01898fbbe6972bcdbc94434c1be74a7152710aed9cce24e0d58a1f1bb2", "ct" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000", "tag" : "f0e6a3c1f28ad92d0dbc900be291d877", "result" : "valid", "flags" : [] }, { "tcId" : 122, "comment" : "", "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "iv" : "000102030405060708090a0b", "aad" : "ffffffff00000000ffffffff00000000", "msg" : "9a49c40f74b728396d1db4e5c0df0d224aaa241d254d94a4c0e218b7d3cc6f0ddf3ebd01898fbbe6972bcdbc94434c1be74a7152710aed9cce24e0d58a1f1bb2bbfa3e7caf94ee1a29cf326c1158a621c2b73700f10d0a1f61089fe78e658802552aa1bea1d990695e724aa356af7c10590de1338af9b7cef5815f497426e925", "ct" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000", "tag" : "57eff4a525eeff2ebd7a28eb894282be", "result" : "valid", "flags" : [] }, { "tcId" : 123, "comment" : "Flipped bit 0 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f5409bb729039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 124, "comment" : "Flipped bit 1 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f6409bb729039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 125, "comment" : "Flipped bit 7 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "74409bb729039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 126, "comment" : "Flipped bit 8 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4419bb729039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 127, "comment" : "Flipped bit 31 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409b3729039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 128, "comment" : "Flipped bit 32 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb728039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 129, "comment" : "Flipped bit 33 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb72b039d0814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 130, "comment" : "Flipped bit 63 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d8814ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 131, "comment" : "Flipped bit 64 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0815ac514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 132, "comment" : "Flipped bit 77 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d08148c514054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 133, "comment" : "Flipped bit 80 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac504054323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 134, "comment" : "Flipped bit 96 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac514055323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 135, "comment" : "Flipped bit 97 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac514056323f44", "result" : "invalid", "flags" : [] }, { "tcId" : 136, "comment" : "Flipped bit 120 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac514054323f45", "result" : "invalid", "flags" : [] }, { "tcId" : 137, "comment" : "Flipped bit 121 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac514054323f46", "result" : "invalid", "flags" : [] }, { "tcId" : 138, "comment" : "Flipped bit 126 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac514054323f04", "result" : "invalid", "flags" : [] }, { "tcId" : 139, "comment" : "Flipped bit 127 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d0814ac514054323fc4", "result" : "invalid", "flags" : [] }, { "tcId" : 140, "comment" : "Flipped bit 63 and 127 in tag expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "f4409bb729039d8814ac514054323fc4", "result" : "invalid", "flags" : [] }, { "tcId" : 141, "comment" : "Tag changed to all zero expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "00000000000000000000000000000000", "result" : "invalid", "flags" : [] }, { "tcId" : 142, "comment" : "tag change to all 1 expected tag:f4409bb729039d0814ac514054323f44", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "", "ct" : "", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "invalid", "flags" : [] }, { "tcId" : 143, "comment" : "Flipped bit 0 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "28914007a6119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 144, "comment" : "Flipped bit 1 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "2b914007a6119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 145, "comment" : "Flipped bit 7 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "a9914007a6119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 146, "comment" : "Flipped bit 8 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29904007a6119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 147, "comment" : "Flipped bit 31 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914087a6119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 148, "comment" : "Flipped bit 32 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a7119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 149, "comment" : "Flipped bit 33 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a4119dd3f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 150, "comment" : "Flipped bit 63 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119d53f109bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 151, "comment" : "Flipped bit 64 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f009bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 152, "comment" : "Flipped bit 77 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f129bba21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 153, "comment" : "Flipped bit 80 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109baa21ce9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 154, "comment" : "Flipped bit 96 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109bba21de9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 155, "comment" : "Flipped bit 97 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109bba21ee9a7d6", "result" : "invalid", "flags" : [] }, { "tcId" : 156, "comment" : "Flipped bit 120 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109bba21ce9a7d7", "result" : "invalid", "flags" : [] }, { "tcId" : 157, "comment" : "Flipped bit 121 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109bba21ce9a7d4", "result" : "invalid", "flags" : [] }, { "tcId" : 158, "comment" : "Flipped bit 126 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109bba21ce9a796", "result" : "invalid", "flags" : [] }, { "tcId" : 159, "comment" : "Flipped bit 127 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119dd3f109bba21ce9a756", "result" : "invalid", "flags" : [] }, { "tcId" : 160, "comment" : "Flipped bit 63 and 127 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "29914007a6119d53f109bba21ce9a756", "result" : "invalid", "flags" : [] }, { "tcId" : 161, "comment" : "Tag changed to all zero expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "00000000000000000000000000000000", "result" : "invalid", "flags" : [] }, { "tcId" : 162, "comment" : "tag change to all 1 expected tag:29914007a6119dd3f109bba21ce9a7d6", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "invalid", "flags" : [] }, { "tcId" : 163, "comment" : "Flipped bit 0 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "67405a16e8b44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 164, "comment" : "Flipped bit 1 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "64405a16e8b44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 165, "comment" : "Flipped bit 7 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "e6405a16e8b44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 166, "comment" : "Flipped bit 8 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66415a16e8b44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 167, "comment" : "Flipped bit 31 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a96e8b44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 168, "comment" : "Flipped bit 32 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e9b44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 169, "comment" : "Flipped bit 33 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16eab44eba92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 170, "comment" : "Flipped bit 63 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44e3a92aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 171, "comment" : "Flipped bit 64 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba93aa47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 172, "comment" : "Flipped bit 77 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba928a47f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 173, "comment" : "Flipped bit 80 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa46f5cea52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 174, "comment" : "Flipped bit 96 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa47f5cfa52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 175, "comment" : "Flipped bit 97 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa47f5cca52b7a", "result" : "invalid", "flags" : [] }, { "tcId" : 176, "comment" : "Flipped bit 120 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa47f5cea52b7b", "result" : "invalid", "flags" : [] }, { "tcId" : 177, "comment" : "Flipped bit 121 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa47f5cea52b78", "result" : "invalid", "flags" : [] }, { "tcId" : 178, "comment" : "Flipped bit 126 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa47f5cea52b3a", "result" : "invalid", "flags" : [] }, { "tcId" : 179, "comment" : "Flipped bit 127 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44eba92aa47f5cea52bfa", "result" : "invalid", "flags" : [] }, { "tcId" : 180, "comment" : "Flipped bit 63 and 127 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "66405a16e8b44e3a92aa47f5cea52bfa", "result" : "invalid", "flags" : [] }, { "tcId" : 181, "comment" : "Tag changed to all zero expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "00000000000000000000000000000000", "result" : "invalid", "flags" : [] }, { "tcId" : 182, "comment" : "tag change to all 1 expected tag:66405a16e8b44eba92aa47f5cea52b7a", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b", "aad" : "000102", "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "invalid", "flags" : [] }, { "tcId" : 183, "comment" : "edge case for poly1305 key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef38c382cf07174142ea564920612997b1c2e38aca2438b588d5459493e97e7fa330ff9bc3b9458297ba0967d86ed090b435103478f2869b93ee29c837e95fb6b9903f3b735b7345428eb93b3db1d9b5187cebb889aa177d83e4f63fc9a5c0596eed939883d06aacdfdea44fdecdf5cb7fc", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "c296436246c3a7c4b3ba09ab2a6a0889", "result" : "valid", "flags" : [] }, { "tcId" : 184, "comment" : "edge case for poly1305 key:278de313ffffffdfffe9acbf3ea59357c4e16a5bc120d346af4a8cf694a84374", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "0001020304050607051e9373", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "931227274a89d0b3aade7fac62c96262c1e77b8dafd248f10ad37c6ccb69cb7131b041593c8bb8c3db38f39dd8a124c424fce4389dede1d3cb9d46cf95970aea9856b6e313d756197baf4fcb58df275bca8a2188f9e8a1ad04354ede542ddc30e8b735b2f5905f5811799282be94ae842ec126c55d2e667235e9acf1d48798f0", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "99a3b0fff6fdcbcce9dc5820f2a64861", "result" : "valid", "flags" : [] }, { "tcId" : 185, "comment" : "edge case for poly1305 key:0050799fe9e74fcffcffffcfd21aa8b5cb5aa2c6ab347b6886eedaca4bfff3c0", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "0001020304050607048c3c5f", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "0df91f31230e8941e700a752fef08c897c511ed618fdf8a378a1f439013b40a48d4634c27d9ada7c0bb6f3fa92e341425903d7ecd0c49bee4c77e84b11f1c721922308642885b813fae364da32eaf120d6a43a74fb1632443667bfea6eef1be73eb1c3c0b5a57cee8dc4feed4a1fb9ae02f7b1695588c3c878451cb6ee0cb3dc", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "eaff8f47ef9268fd0d94e8a9c4b78d24", "result" : "valid", "flags" : [] }, { "tcId" : 186, "comment" : "edge case for poly1305 key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715ba428a85431430eada56a2c5dc944b6aa6cef0b056a2eecc51d30838e640615e1458e0943e30f91ba41b4362fa9ed6037b21d14da7b4f76f9f68fa8903138d563ce2590af1201c7cfec2290cfce98a822ebb8d1ed9dc4e20d241755aff91cdfd10fdb69efa0d5c8082692601cbfbb955c7", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "86ed21fda080a7d13981078d86b3e3cd", "result" : "valid", "flags" : [] }, { "tcId" : 187, "comment" : "edge case for poly1305 key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "66115e67ecd3d4178c4c60e713ab4e5e66f8d1f971da17437a2b5e04fbca1671e847139a5f4e3f8e92d7a3b71eb4ff0e50354c0c1580af3662d5f8151e3f7e8264a0085c32ddfcbeb01a8be4c34d53319800ac4ef9d4e4014524bc7cd3387242e774f4d1a7a0521e42ec44844d0bd8b9d73fec959212fd7e8eacf4d984996d9b", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "34f9e0faa515eee0e784e6ef2678befa", "result" : "valid", "flags" : [] }, { "tcId" : 188, "comment" : "edge case for poly1305 key:0000003059ffce96438a246ff9536787d92bc40eafa0241a2972780ef6ca1ef8", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060726c6961b", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "e97244259af5a379238da0cad2a5f493655ec0e5024fd553bbb3deb66a94036d106c3d513407b2dd1cc5936c4c9c1e4f4b37b54dec261c601dc99e90680e23e2dc5c9a8d503d8bea49a8cdca3706bfd2a3daa0afb19a70fd3d355fc37c13f3f9e5c8d0864a5f80a780b36d4698ec2ce9ccc27b97ecbe672e41628ebd773acb81", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "3c94b9fe60bdb35c6b7b73b765083492", "result" : "valid", "flags" : [] }, { "tcId" : 189, "comment" : "edge case for poly1305 key:3fa0ea9c030000a036217d42e775ad189b96e24ee591952e2922ff151334b9ec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "0001020304050607013da060", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "9453aa159c3d87f17e21e88adabc37e553b904d00eefc66b8e0905e23576fbdc9c7bea9777f3b8368481932534b3344d309e6307cddfe7b3549300dd9cda7efe9d43c8a115912a392904079ee92bcd33099f7022ea94c1e7353b89bfc54de3ceb56f529a1a608bb5a970e1359609d1f56806b37f8605f4c27451da6066fc557a", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "2b11cf9f8db8490d409fc62afd7379f3", "result" : "valid", "flags" : [] }, { "tcId" : 190, "comment" : "edge case for poly1305 key:a556cb502baf395b020000f03c5108fb1cf76df1b8a8f724e877bd3c588d3285", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060707db33de", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "2e1836640d810c2709fb83ccf1aef3a971085d1bbfb58a425abf75ccec70b3abde0e80539e83a82546e7372a19481547053308dd7842675e9c4f61302426da0d71c1da3102031030ed928152be009b15b52f71b5911991d39f68a8658d99729df2bbef31c8989f9604558df9f2aba4b3766c58aaef3548de545ec1f080225a88", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "c9c8366920f88381407712cec61e6607", "result" : "valid", "flags" : [] }, { "tcId" : 191, "comment" : "edge case for poly1305 key:0c327fbcc564555545d4fe75020000d0a65799f363ec51b1c5c427b4a04af190", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060702a11942", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "0ecb4d85c956b5268c9b35a8c63b4e9d3e5cb72b64ef98773841b947bd7d59ef7d0eb0e1c050d49a5424ce7deb527d76087e4746674c958965df32d9e5fb03b46501706128d481217aaeae2f78f9259273358a2954cac0bc2fbfe77447d1d387b9314c6541b69f1270b3438b1042b2b4663e62ba4d49c07ac6f163034afa80af", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "2373cfa2ab24446ad5a236167b8027fe", "result" : "valid", "flags" : [] }, { "tcId" : 192, "comment" : "edge case for poly1305 key:415f08302f210340240d0e903e2b01205ba43e106aebd7e2481016b31118b1ae", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506073c0df637", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "2e8e45e903bfab32f2f0d49d9a3e449bef6f4093e2722cdab2cf935c1822b830fb5a4056516d560dfc8638c9a57d2927200a56f0b67153271d498e8f08dc888c61ef634f7ae40f4608f96f92fea5a1e5bd45131120098dc5de0378e58f2ddb46fa4aa5adb38fe006bb19b69146382f77a79e06214def547cfb5ce37a7008b9b6", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "5f93946478d8081e7247f414ad39a515", "result" : "valid", "flags" : [] }, { "tcId" : 193, "comment" : "edge case for poly1305 key:feffff1ff6b87403fd6435b09775bc92491a0ae62c5842a30e3b82710cc2dad1", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112130bc672c3", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "3619cb470af86dceceb6940f2d9abb34c9a9131476053387445ffebbe240d4f9818377855652f46a8219c7f71c3554f8acef8258de4b7d17c0f3d353ac981cc6a13287be1e6b41dc6d133df4ababebdf43d665ce7a4a5c982a0b139cb8202eebc74173e3224a440e4c37d2b595f384290e939ba016df0d49b36cdb4bd91c39", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "133fe62391744d11ce44594b96c53baf", "result" : "valid", "flags" : [] }, { "tcId" : 194, "comment" : "edge case for poly1305 key:bf358f18ffffffbf4b62ed6e1f53790785c4dabdfc72e2a219d377a682c85f38", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "000000001011121303e9b9a4", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "af205bda819f7451be0f28667d4b01b59ff2daa8173cab52046c3c9e0d989889c5e021ef7afd06e9ce6cc30e3a6ebab509134ba10d10e570c55587c13eee53e73be54804c8539ffbf23b35922b1ca37b9e9bc24ee204837ca5a294ce05d12600c7eff6aee32270db2feff47dc5a04176169e15850628e6035f78994f9f5603", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "e3451adb9d23a7710a1aafba26f56387", "result" : "valid", "flags" : [] }, { "tcId" : 195, "comment" : "edge case for poly1305 key:d0b7b3a352a4010ffeffffbfe8cc66dc6e5e7451dc61762c5753174fed88e746", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112130700b982", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "68c67272036fb652a0182eeb4781358e4704a4a702fd731bf3b3ea994717989e7d9104e0ae81732a8c7e9a82b3d31d541761a366b67c3396f1a6c67e293ddb65a59e42541dda144dc6c78388cfca982e23350958ac5b3d54a1722fd64733577862e1879c9e9445ebdec5315d1706db7ebbedd4c779935e72057e5b0ecde081", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "b0bb8a55ff5f52a5043c6e7795847557", "result" : "valid", "flags" : [] }, { "tcId" : 196, "comment" : "edge case for poly1305 key:7bee33931a4157a8cb701becfeffff4fbe7e69f19cd065313bb49a252628dd3d", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "0000000010111213019836bb", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "c483b7334ebe2e879b0c3f9db4fcd9f5219062360d6ce44cdae0f94e04c8345ea7e3ae33855118741dcafe0de4ae98c4e43af7b12b04ee8ab175625823ac040e5abac4403f1d45238adcb8c0cf44bd56917f9f5d93974c82b56951986a9c0450bd9047b5a616e814526ad0580e3ecd8189c9fef2cdb979a22ad3a01930fbd1", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "f4fc25f4c5543a9afee9819e2904fb68", "result" : "valid", "flags" : [] }, { "tcId" : 197, "comment" : "edge case for poly1305 key:7cb5fbdffb40ff5f3c7de74f655ffc1fac03013a7fe468440b861ebe0ab1650a", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112131d59f288", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "bc7f4f15fd1e4c1399740836670abe39a05707be19956ce169b32321759e0f213ae19ad34aa612b3a29f02c4bbac9f785a55a3adfe419ab891bbe0acee9921322ea21002c9dd3dcdd13a7f8554dddc10f9b529ce94be7050937dab76557b7eb17c685aad8f0797e39d62553988989aab1d9764fe431cc1d4c595062ce93ce9", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "5e67a7b8733e0e4b01ac2178a205ae7e", "result" : "valid", "flags" : [] }, { "tcId" : 198, "comment" : "edge case for poly1305 key:00000090e6e328c242cde5c83e3d8262d467f2bcd53d3755c781f3c6a2cb0648", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112130552a411", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "eaccaa778935ef249e0900149dd889462d2a061486ba102b8caebe465f3959fb3119ebb5689676ffdd6d851a26739e772b54a2f5f473ea9c7e58ccbc4cfc953e8c420b2175d9dd519265630bb79bd87a601b113231a8b16ce54c331347ec04c2b1c9160f38207aa46e96feb06dee883eb422fa14908df300bb1a1ef758c408", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "177a77fce114a4349c4f8d5ec825d06f", "result" : "valid", "flags" : [] }, { "tcId" : 199, "comment" : "edge case for poly1305 key:9e98d64e000000505a07183c5c68c63c14c9266dd37ff86aafc22ddbdb355617", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112130c807a72", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "a76c330e015060a17e64cb7b6d753f201f75be8759fd7539fb92b22aef54c9d3029dba0c15cbf7c95135888319c6b2e6276da21e0c351fd522b29aabb5883a3291d6f427de773b124390ef6fd96621ffbc42dfbf7a34da272cbc9ccb1a498d078033d1ac3bf7e92715948b06d69d5c5039e9164ba9c3a02219ec5908206b3b", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "623c7d4424f5497aedfd1339cf8cecce", "result" : "valid", "flags" : [] }, { "tcId" : 200, "comment" : "edge case for poly1305 key:1048a92e65f5e63102000080d9ae08de4319a7c45fdbe707b9ec1b7e0d635161", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112130397a143", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "228a7e15bcce13051de9145f77f7f4ff7921828b4f99efc4ff55ee0d9344955b69ec2d4798b0517f0273c4456ae5ffc5929cbe74ddb0da51d4f2b4df7578a31240c88ae922c3c5eca7b97d72d497062050a587447c562b343d5c71921944872f9fd06b8f34b3eb5d4341f5ff8a907dd7c2e1676b81252726ba54814da51eab", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "1c18b69354b189731a1a83fe8f0d57c9", "result" : "valid", "flags" : [] }, { "tcId" : 201, "comment" : "edge case for poly1305 key:01517a2ceb89bbfb5741f7d9000000401a65b132ad661072a00ffe7defbb18a5", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "000000001011121308cb0f3f", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "c7d843188ab193dfef5c4daf583f952cd4b195f240fa2e704d021723023c123371a41e87dfc6e6c3874a42f331cf035988a38c72ba2da854b1208f98bf8cc29948169481ab3a402d5fcc7ff78f9e31925576dc3938074b8c5b27960e3afc750ad686563688b7441787288d5256c1301d563b7744843bd1ab4eff5be6f1653d", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "2045815b8211b9a2995effe0b8ed9868", "result" : "valid", "flags" : [] }, { "tcId" : 202, "comment" : "edge case for poly1305 key:bc90156087e0125006d90c30babd0590427bff19de1f2e7d0757a79528731138", "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", "iv" : "00000000101112130d8fcf4e", "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "msg" : "cfc3db8631c81c69023a3c8a9ad66c35053685144c4fa2a9510add72e211dad9ca5b982e4c194591fdb74116280311d1299ad81227258cb52f079bbcb12aff161d278dec33a326d71276b3de01a8327ee7f45f94179dff18a3fe643e56c30cfd03871c8110ab00f6612b9e17a4647360d7847bb63a3122613c2e7cdddd08ae", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "1ae2ed84ea9774d78d782bf8d972a8b8", "result" : "valid", "flags" : [] }, { "tcId" : 203, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "ffffffffffffffffffffffffffffffff415771fda4fbcc55c377f73203e60226", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "000102030405060708090a0b0c0d0e0f", "result" : "valid", "flags" : [] }, { "tcId" : 204, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "f1ffffffffffffffffffffffffffffff615af39eddb5fcd2519190d5507d3b06", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "00000000000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 205, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "b5ffffffffffffffffffffffffffffff764e5d82ce7da0d44148484fd96a6107", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "ffffffffffffffffffffffffffffffff", "result" : "valid", "flags" : [] }, { "tcId" : 206, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "fdffffffffffffffffffffffffffffff2bdbf16d8ea4d39dab8dcb3d4bc4e104", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "00000080000000800000008000000080", "result" : "valid", "flags" : [] }, { "tcId" : 207, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "a9ffffffffffffffffffffffffffffffaccd5eb31d8fc909e84b0de7de23bb08", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "ffffff7fffffff7fffffff7fffffff7f", "result" : "valid", "flags" : [] }, { "tcId" : 208, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "d2ffffffffffffffffffffffffffffffdd4b933e7b1a7ed93cc7c050db71dc03", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "01000000010000000100000001000000", "result" : "valid", "flags" : [] }, { "tcId" : 209, "comment" : "edge case for tag", "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", "iv" : "000102030405060708090a0b", "aad" : "ffffffffffffffffffffffffffffffffa08164425d7642e9e90fc8d5c32d2cf6", "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "tag" : "ffffffff000000000000000000000000", "result" : "valid", "flags" : [] }, { "tcId" : 210, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "c68ce708bf26aab862d97e1b42f31ef37bb66f8090c149e452ec7f20327eb2ea2e38aca2438b588d5459493e97e7fa330ff9bc23c897df6b00af86931d6c81555103478f2869b93ee29c837e95fb6b9903f3b72debfba2384baa48ceedfedb91", "ct" : "e5ffffffffffffffffffffffffffffff0871bc8f1e4aa235087712d9df183609ffffffffffffffffffffffffffffffffffffffe7a33009ef5fc604ea0f9a75e9ffffffffffffffffffffffffffffffffffffffe7a33009ef5fc604ea0f9a75e9", "tag" : "3572162777262c518eef573b720e8e64", "result" : "valid", "flags" : [] }, { "tcId" : 211, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "c78ce708bf26aab862d97e1b42f31ef376209eef141691fba5d10eaf581affe62e38aca2438b588d5459493e97e7fa330e73d2dc3bbd954989cb8433b7d6597b5103478f2869b93ee29c837e95fb6b990279d9d218d1e81ac2ce4a6e474403bf", "ct" : "e4ffffffffffffffffffffffffffffff05e74de09a9d7a2aff4a6356b57c7b05fffffffffffffffffffffffffffffffffe759118501a43cdd6a2064aa520adc7fffffffffffffffffffffffffffffffffe759118501a43cdd6a2064aa520adc7", "tag" : "347216375f5b7b5c4e6bff4912fd9473", "result" : "valid", "flags" : [] }, { "tcId" : 212, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "fc8ce708bf26aab862d97e1b42f31ef38b79403dfaabc0d8c18d23a3469c13e62e38aca2438b588d5459493e97e7fa330a4b941e6b66fcc2ed7d8cb3e8cc7ffc5103478f2869b93ee29c837e95fb6b9906419f10480a8191a67842ee185e2538", "ct" : "dffffffffffffffffffffffffffffffff8be933274202b099b164e5aabfa9705fffffffffffffffffffffffffffffffffa4dd7da00c12a46b2140ecafa3a8b40fffffffffffffffffffffffffffffffffa4dd7da00c12a46b2140ecafa3a8b40", "tag" : "30721677ff2eb8894e5a9d8492b7b0af", "result" : "valid", "flags" : [] }, { "tcId" : 213, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "fa8ce708bf26aab862d97e1b42f31ef39bcbb8da477d580d772de4229bba7de22938aca2438b588d5459493e97e7fa331e9dedf9dd64a0681bac2969549425bc5603478f2869b93ee29c837e95fb6b991297e6f7fe08dd3b50a9e734a4067f78", "ct" : "d9ffffffffffffffffffffffffffffffe80c6bd5c9f6b3dc2db689db76dcf901f8ffffffffffffffffffffffffffffffee9bae3db6c376ec44c5ab104662d100f8ffffffffffffffffffffffffffffffee9bae3db6c376ec44c5ab104662d100", "tag" : "2b7216c7873744c20ec5e2cdb260d3fa", "result" : "valid", "flags" : [] }, { "tcId" : 214, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "ee8ce708bf26aab862d97e1b42f31ef3b9f55bd56e0fd74b46063a96354cfbee3238aca2438b588d5459493e97e7fa3320c78886a6f6292d6cc5fbddb546a2b04d03478f2869b93ee29c837e95fb6b992ccd8388859a547e27c0358045d4f874", "ct" : "cdffffffffffffffffffffffffffffffca3288dae0843c9a1c9d576fd82a7f0de3ffffffffffffffffffffffffffffffd0c1cb42cd51ffa933ac79a4a7b0560ce3ffffffffffffffffffffffffffffffd0c1cb42cd51ffa933ac79a4a7b0560c", "tag" : "22721657b0130d28cf1ec65153c41182", "result" : "valid", "flags" : [] }, { "tcId" : 215, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "ef8ce708bf26aab862d97e1b42f31ef3b46fca24d353ff5e49eac51540e840ea3038aca2438b588d5459493e97e7fa333d311e572202011a75e948586fe268b44f03478f2869b93ee29c837e95fb6b99313b1559016e7c493eec86059f703270", "ct" : "ccffffffffffffffffffffffffffffffc7a8192b5dd8148f1371a8ecad8ec409e1ffffffffffffffffffffffffffffffcd375d9349a5d79e2a80ca217d149c08e1ffffffffffffffffffffffffffffffcd375d9349a5d79e2a80ca217d149c08", "tag" : "2172166798485c338f9a6d60f3b21891", "result" : "valid", "flags" : [] }, { "tcId" : 216, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f59d56151de28bef83505f6d89c0b0f7f75b2fa8e6dce386075db283ec85ee62555baffad423af25f66069bb69fb6f4d", "ct" : "d6ee4ee25d3bdea81e76de8934cc51fb849cfca7685708575dc6df7a01e36a81849cfca7685708575dc6df7a01e36a81", "tag" : "831312cbb0f165dc3e8ff52125f48640", "result" : "valid", "flags" : [] }, { "tcId" : 217, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f717f8d5b28032d5c8e8061cd44d71e4f2d55de772fe7a91ce85e410db3e2d8d50d5ddb5400136323fb83f285e40aca2", "ct" : "d464e022f259679255ce87f8694190e881128ee8fc759140941e89e93658a96e81128ee8fc759140941e89e93658a96e", "tag" : "821312db9826b5e7fe0a9d30c5e28d4f", "result" : "valid", "flags" : [] }, { "tcId" : 218, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f28ce708bf26aab862d97e1b42f31ef3e68a922c9219d30f07554d7d99f2bde92c38aca2438b588d5459493e97e7fa33e24c07dd98f9b253ab0c318d9b14f6b15303478f2869b93ee29c837e95fb6b99ee460cd3bb95cf00e009ffd06b86ac75", "ct" : "d1ffffffffffffffffffffffffffffff954d41231c9238de5dce20847494390afdffffffffffffffffffffffffffffff124a4419f35e64d7f465b3f489e2020dfdffffffffffffffffffffffffffffff124a4419f35e64d7f465b3f489e2020d", "tag" : "c1045769d487d545cef3f0d34b7a8733", "result" : "valid", "flags" : [] }, { "tcId" : 219, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef32e6784d857df07543d0dc72f179935fbede8c8baf01ee2044b162cbb343b355acc29d82327cd93f2bfd918034ed5c42a", "ct" : "ffffffffffffffffffffffffffffffff5da057d7d954ec856796aad6faffb1183c2f9be74c6a4576e0b09a7a5c2330963c2f9be74c6a4576e0b09a7a5c233096", "tag" : "64e7efd24516a83e2c87e06a76e2dea3", "result" : "valid", "flags" : [] }, { "tcId" : 220, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f78ce708bf26aab862d97e1b42f31ef34c6ead26f84a0225d557745d32fc72e72c38aca2438b588d5459493e97e7fa3364db334b69bee579383e61ae742c71bb5303478f2869b93ee29c837e95fb6b9968d138454ad2982a733baff384be2b7f", "ct" : "d4ffffffffffffffffffffffffffffff3fa97e2976c1e9f48fcc19a4df9af604fdffffffffffffffffffffffffffffff94dd708f021933fd6757e3d766da8507fdffffffffffffffffffffffffffffff94dd708f021933fd6757e3d766da8507", "tag" : "e6cc6729d79ba558cd73b03cba54d660", "result" : "valid", "flags" : [] }, { "tcId" : 221, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f08ce708bf26aab862d97e1b42f31ef34fd8c3757c9f2938dc3b07d85898bfe22a38aca2438b588d5459493e97e7fa336155412415cbdd760142b62c2ec83fbf5503478f2869b93ee29c837e95fb6b996d5f4a2a36a7a0254a477871de5a657b", "ct" : "d3ffffffffffffffffffffffffffffff3c1f107af214c2e986a06a21b5fe3b01fbffffffffffffffffffffffffffffff915302e07e6c0bf25e2b34553c3ecb03fbffffffffffffffffffffffffffffff915302e07e6c0bf25e2b34553c3ecb03", "tag" : "e5cc6739bfd0f4638def574b5a43dd6f", "result" : "valid", "flags" : [] }, { "tcId" : 222, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f28ce708bf26aab862d97e1b42f31ef3df03ca84082f7f70ad8e4004cabd2ce42b38aca2438b588d5459493e97e7fa3328fd413caab1d02bf1c65753aa2ad3b95403478f2869b93ee29c837e95fb6b9924f74a3289ddad78bac3990e5ab8897d", "ct" : "d1ffffffffffffffffffffffffffffffacc4198b86a494a1f7152dfd27dba807faffffffffffffffffffffffffffffffd8fb02f8c11606afaeafd52ab8dc2705faffffffffffffffffffffffffffffffd8fb02f8c11606afaeafd52ab8dc2705", "tag" : "0fca702228817d53ee64d142b192e665", "result" : "valid", "flags" : [] }, { "tcId" : 223, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f38ce708bf26aab862d97e1b42f31ef31ffc31ae69399394b8c338674c3dfde92938aca2438b588d5459493e97e7fa33477ec8cf3ea3d4d5d76d85ad2b7f0bb85603478f2869b93ee29c837e95fb6b994b74c3c11dcfa9869c684bf0dbed517c", "ct" : "d0ffffffffffffffffffffffffffffff6c3be2a1e7b27845e258559ea15b790af8ffffffffffffffffffffffffffffffb7788b0b55040251880407d43989ff04f8ffffffffffffffffffffffffffffffb7788b0b55040251880407d43989ff04", "tag" : "efc3b035ded6b460bfce6f494955e677", "result" : "valid", "flags" : [] }, { "tcId" : 224, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "2bfd0d56ece98771756d60d9d9106cd0c6fc106936c7ef347c078fd71c54228164fc903b0438a3978d3a54ef992aa3ae", "ct" : "088e15a1ac30d236e84be13d641c8ddcb53bc366b84c04e5269ce22ef132a662b53bc366b84c04e5269ce22ef132a662", "tag" : "345fc9fe573c136c1be83730500ce662", "result" : "valid", "flags" : [] }, { "tcId" : 225, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f68ce708bf26aab862d97e1b42f31ef37cc2255decdf8e0fe1373591da0e28e42838aca2438b588d5459493e97e7fa33e291fb4838019c51dfb7141515bb53b15703478f2869b93ee29c837e95fb6b99ee9bf0461b6de10294b2da48e5290975", "ct" : "d5ffffffffffffffffffffffffffffff0f05f652625465debbac58683768ac07f9ffffffffffffffffffffffffffffff1297b88c53a64ad580de966c074da70df9ffffffffffffffffffffffffffffff1297b88c53a64ad580de966c074da70d", "tag" : "336f97a5faa995a2a03781b591588da8", "result" : "valid", "flags" : [] }, { "tcId" : 226, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "c68ce708bf26aab862d97e1b42f31ef37ab66f8090c149e452ec7f20327eb2ea0438aca2438b588d5459493e97e7fa338d2613ea0ef8b656b247373ecec015bc7b03478f2869b93ee29c837e95fb6b99812c18e42d94cb05f942f9633e524f78", "ct" : "e5ffffffffffffffffffffffffffffff0971bc8f1e4aa235087712d9df183609d5ffffffffffffffffffffffffffffff7d20502e655f60d2ed2eb547dc36e100d5ffffffffffffffffffffffffffffff7d20502e655f60d2ed2eb547dc36e100", "tag" : "9351c680c8a5d34882d42145e89745c4", "result" : "valid", "flags" : [] }, { "tcId" : 227, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "c68ce708bf26aab862d97e1b42f31ef374b66f8090c149e452ec7f20327eb2ea2e38aca2438b588d5459493e97e7fa33acd9ec859e0866620cc24c8a97d5d9f55103478f2869b93ee29c837e95fb6b99a0d3e78bbd641b3147c782d767478331", "ct" : "e5ffffffffffffffffffffffffffffff0771bc8f1e4aa235087712d9df183609ffffffffffffffffffffffffffffffff5cdfaf41f5afb0e653abcef385232d49ffffffffffffffffffffffffffffffff5cdfaf41f5afb0e653abcef385232d49", "tag" : "d79266cd25a784599a0a8e31fc84d604", "result" : "valid", "flags" : [] }, { "tcId" : 228, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f78ce708bf26aab862d97e1b42f31ef34251cd29b0aaa960557c9ea2828334e4e4e231db0a27fac9ec9e744886eb0133c5232142ddf48b3f185140f0fc05f043", "ct" : "d4ffffffffffffffffffffffffffffff31961e263e2142b10fe7f35b6fe5b00735256286b6535dbb4738c289eef304ff35256286b6535dbb4738c289eef304ff", "tag" : "9d671d407d7660459d5d582d83915efe", "result" : "valid", "flags" : [] }, { "tcId" : 229, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "f58ce708bf26aab862d97e1b42f31ef373bd9f01bf3331b12e31dd14cf11feee1d38aca2438b588d5459493e97e7fa33625c6965f61a1c36118c747076d5b7b76203478f2869b93ee29c837e95fb6b996e56626bd57661655a89ba2d8647ed73", "ct" : "d6ffffffffffffffffffffffffffffff007a4c0e31b8da6074aab0ed22777a0dccffffffffffffffffffffffffffffff925a2aa19dbdcab24ee5f6096423430bccffffffffffffffffffffffffffffff925a2aa19dbdcab24ee5f6096423430b", "tag" : "7b207c2c3278c64f0d6b913fe371fe63", "result" : "valid", "flags" : [] }, { "tcId" : 230, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef3ec0933f0bfb91218cea0d74e061f559e2d38aca2438b588d5459493e97e7fa338d5b67e0acee534ce2d9791487b1ecb25203478f2869b93ee29c837e95fb6b9981516cee8f822e1fa9dcb7497723b676", "ct" : "ffffffffffffffffffffffffffffffff9fcee0ff3132f9c9943bbab7eb79d17dfcffffffffffffffffffffffffffffff7d5d2424c74985c8bdb0fb6d9547180efcffffffffffffffffffffffffffffff7d5d2424c74985c8bdb0fb6d9547180e", "tag" : "3672162bb1f3ff537ece013f1aca4f68", "result" : "valid", "flags" : [] }, { "tcId" : 231, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef3ee83a14f48db696291080edfcc898b882b38aca2438b588d5459493e97e7fa338ad5f6b0283a8b39ebedce92785da9b65403478f2869b93ee29c837e95fb6b9986dffdbe0b56f66aa0e800cf88cff372", "ct" : "ffffffffffffffffffffffffffffffff9d447240c65082b3cb93632621ef0f6bfaffffffffffffffffffffffffffffff7ad3b574439d5dbdb4844ceb6aab5d0afaffffffffffffffffffffffffffffff7ad3b574439d5dbdb4844ceb6aab5d0a", "tag" : "3572163b99284f5f3e4aa94dbab85677", "result" : "valid", "flags" : [] }, { "tcId" : 232, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef3e87dd08ed4e4e04c5877616cbb02cabb2938aca2438b588d5459493e97e7fa33874f0401d457e336f4311f1152f957ba5603478f2869b93ee29c837e95fb6b998b450f0ff73b9e65bf34d14ca26b0d7e", "ct" : "ffffffffffffffffffffffffffffffff9bba03815a6f0b9d02ec0c9556644e58f8ffffffffffffffffffffffffffffff774947c5bff035b2ab589d68400fa306f8ffffffffffffffffffffffffffffff774947c5bff035b2ab589d68400fa306", "tag" : "3472164b815d9e6afec5505c5aa75d86", "result" : "valid", "flags" : [] }, { "tcId" : 233, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "c88ce708bf26aab862d97e1b42f31ef36be436e346f8f2b32f4cbbaef95150ef0438aca2438b588d5459493e97e7fa332fb76b5132e930f6d0acf70875e977b57b03478f2869b93ee29c837e95fb6b9923bd605f11854da59ba93955857b2d71", "ct" : "ebffffffffffffffffffffffffffffff1823e5ecc873196275d7d6571437d40cd5ffffffffffffffffffffffffffffffdfb12895594ee6728fc57571671f8309d5ffffffffffffffffffffffffffffffdfb12895594ee6728fc57571671f8309", "tag" : "3a7216d7ee1da018ce8412f251656b19", "result" : "valid", "flags" : [] }, { "tcId" : 234, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "c58ce708bf26aab862d97e1b42f31ef3783cf9302c7d22914b38aca2e7d374ef1d38aca2438b588d5459493e97e7fa33228f2d23597640d574f8e20c4f6b6bb56203478f2869b93ee29c837e95fb6b992e85262d7a1a3d863ffd2c51bff93171", "ct" : "e6ffffffffffffffffffffffffffffff0bfb2a3fa2f6c94011a3c15b0ab5f00cccffffffffffffffffffffffffffffffd2896ee732d196512b9160755d9d9f09ccffffffffffffffffffffffffffffffd2896ee732d196512b9160755d9d9f09", "tag" : "367216178ff1dc45ce73b02cd21f8755", "result" : "valid", "flags" : [] }, { "tcId" : 235, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef35db72f89d1402b1a0373ff0a9c5cd44b6d67af40798f5455501792953248ec234ca6bfd9ae5c25a3a4d8a62d48a61d53", "ct" : "ffffffffffffffffffffffffffffffff2e70fc865fcbc0cb59e892f3713a50a8bca0fc1dc5fbf327fbb124545a50e9efbca0fc1dc5fbf327fbb124545a50e9ef", "tag" : "0b4961c9525ea2f2cdad6273e1c7824c", "result" : "valid", "flags" : [] }, { "tcId" : 236, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef35f215ec87d62a264cadb519b4ac90a7668d1dd03e56eda6399ac7803e7dd22114910cd9a32bdab956d634cbb9d33d361", "ct" : "ffffffffffffffffffffffffffffffff2ce68dc7f3e949b590403c62a7af8e95b9168e5e591a7d11320acec28fc527ddb9168e5e591a7d11320acec28fc527dd", "tag" : "0a4961d93a93f1fd8d290a8281b6895b", "result" : "valid", "flags" : [] }, { "tcId" : 237, "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060710abb165", "aad" : "ffffffff", "msg" : "dc8ce708bf26aab862d97e1b42f31ef3d15ad590dd0f40ba18acd168f6ac777a0f38aca2438b588d5459493e97e7fa33932a097f1d39a04ad30f1b6c650260bf7003478f2869b93ee29c837e95fb6b999f2002713e55dd19980ad53195903a7b", "ct" : "ffffffffffffffffffffffffffffffffa29d069f5384ab6b4237bc911bcaf399deffffffffffffffffffffffffffffff632c4abb769e76ce8c66991577f49403deffffffffffffffffffffffffffffff632c4abb769e76ce8c66991577f49403", "tag" : "3572161355240943de9406292a64c551", "result" : "valid", "flags" : [] }, { "tcId" : 238, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "40115e67ecd3d4178c4c60e713ab4e5e390ef93aeb61aa307f141323c38e0685fa47139a5f4e3f8e92d7a3b71eb4ff0e259445f4ffc31bce540190edd6ad207876a0085c32ddfcbeb01a8be4c34d5331eda1a5b6139750f973f0d4841baa2cb8", "ct" : "d9ffffffffffffffffffffffffffffffa009d73c6544428cfac0b2d8c7bbef0bedffffffffffffffffffffffffffffff8a5ef60715bc4b07c92b9707376da105edffffffffffffffffffffffffffffff8a5ef60715bc4b07c92b9707376da105", "tag" : "19532d9fa0b5fbd582aaeda830602f1d", "result" : "valid", "flags" : [] }, { "tcId" : 239, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "49115e67ecd3d4178c4c60e713ab4e5ee02b87aeae8c3da8895f8cb0f6b9cc80f447139a5f4e3f8e92d7a3b71eb4ff0ecc4b7b803a5f8f4647df169080fe567a78a0085c32ddfcbeb01a8be4c34d5331047e9bc2d60bc471602e52f94df95aba", "ct" : "d0ffffffffffffffffffffffffffffff792ca9a820a9d5140c8b2d4bf28c250ee3ffffffffffffffffffffffffffffff6381c873d020df8fdaf5117a613ed707e3ffffffffffffffffffffffffffffff6381c873d020df8fdaf5117a613ed707", "tag" : "adbd2cafc8c8f0e51250e7b81c9d0a2d", "result" : "valid", "flags" : [] }, { "tcId" : 240, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "43eadae036f733ea9b5b7eb22aee395db6f51a4d10bc2460810c229651556acf384ad82e3e280cad69f0df25b42b83b0", "ct" : "da047b7825db1802e8e8e1aac6ba88fc2ff2344b9e99ccdc04d8836d556083412ff2344b9e99ccdc04d8836d55608341", "tag" : "973e270a7afcab75348e14dbe19c5156", "result" : "valid", "flags" : [] }, { "tcId" : 241, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "66115e67ecd3d4178c4c60e713ab4e5e891b797521ba925b24090aaf6c4482bae847139a5f4e3f8e92d7a3b71eb4ff0e6d50c32d05a946cb8cea57c9f1442cb164a0085c32ddfcbeb01a8be4c34d5331a565236fe9fd0dfcab1b13a03c432071", "ct" : "ffffffffffffffffffffffffffffffff101c5773af9f7ae7a1ddab5468716b34ffffffffffffffffffffffffffffffffc29a70deefd6160211c050231084adccffffffffffffffffffffffffffffffffc29a70deefd6160211c050231084adcc", "tag" : "e17c273f31758e752322ae4869c1bfbb", "result" : "valid", "flags" : [] }, { "tcId" : 242, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "6a115e67ecd3d4178c4c60e713ab4e5e519cccebf72573dbee8c12f74255d18c0add1035861ffc0b7f40079b969f8c63b2af4fa3ccd16cb38f425c3996140def", "ct" : "f3ffffffffffffffffffffffffffffffc89be2ed79009b676b58b30c466038021d65fc5026ae3c7a12685bd377d48c921d65fc5026ae3c7a12685bd377d48c92", "tag" : "a22390224c5db0f01696743d870725c5", "result" : "valid", "flags" : [] }, { "tcId" : 243, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "e235b8c21384557085c3f2eb2a8fa36058cffd2af743dacf96b4ae4d51b4e488d6703f49d9d7f2027e4853feb4ca0df7", "ct" : "7bdb195a00a87e98f6706df3c6db12c1c1c8d32c7966327313600fb655810d06c1c8d32c7966327313600fb655810d06", "tag" : "437d1efad21b0865a541b5cab62e2a44", "result" : "valid", "flags" : [] }, { "tcId" : 244, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "66115e67ecd3d4178c4c60e713ab4e5e8fab58574a322bac6f394474e4ce7eaec347139a5f4e3f8e92d7a3b71eb4ff0e71532dfb0e9141b00983394722829e7c4fa0085c32ddfcbeb01a8be4c34d5331b966cdb9e2c50a872e727d2eef8592bc", "ct" : "ffffffffffffffffffffffffffffffff16ac7651c417c310eaede58fe0fb9720d4ffffffffffffffffffffffffffffffde999e08e4ee117994a93eadc3421f01d4ffffffffffffffffffffffffffffffde999e08e4ee117994a93eadc3421f01", "tag" : "acf4ffa20c0d06d61a18e9a8d4c84d1d", "result" : "valid", "flags" : [] }, { "tcId" : 245, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "61115e67ecd3d4178c4c60e713ab4e5e5efe679ba17384c55eb8cc193666fe8d04608c3503d217aa3f90a9b0e1b3b313bc12d3a3491c8712cf92f212e138329f", "ct" : "f8ffffffffffffffffffffffffffffffc7f9499d2f566c79db6c6de23253170313d86050a363d7db52b8f5f800f8b3e213d86050a363d7db52b8f5f800f8b3e2", "tag" : "cd466d06e75b7fd18d5fe21d9227d9a7", "result" : "valid", "flags" : [] }, { "tcId" : 246, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "9064b88a282052a1ee44df05ad213da679f8d1f971da17437a2b5e04fbca167151b2650ec945fec70588bc65a616a5f24f354c0c1580af3662d5f8151e3f7e82dd557ec8a4d63df7274594367bef09cd", "ct" : "098a19123b0c79499df7401d41758c07e0ffffffffffffffffffffffffffffff460a896b69f43eb668a0e02d475da503e0ffffffffffffffffffffffffffffff460a896b69f43eb668a0e02d475da503", "tag" : "ce8a3d4d887d95613d829b538ed01196", "result" : "valid", "flags" : [] }, { "tcId" : 247, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "43115e67ecd3d4178c4c60e713ab4e5eeef67bd4795b74015a3493905d544a86e847139a5f4e3f8e92d7a3b71eb4ff0e3197be28eff843592bd8fc8d578421d664a0085c32ddfcbeb01a8be4c34d5331f9a25e6a03ac086e0c29b8e49a832d16", "ct" : "daffffffffffffffffffffffffffffff77f155d2f77e9cbddfe0326b5961a308ffffffffffffffffffffffffffffffff9e5d0ddb05871390b6f2fb67b644a0abffffffffffffffffffffffffffffffff9e5d0ddb05871390b6f2fb67b644a0ab", "tag" : "08289f5199df476fe90475cb95225566", "result" : "valid", "flags" : [] }, { "tcId" : 248, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "6b115e67ecd3d4178c4c60e713ab4e5e1e34412ab0a056e809d5d4b92be1128a4b2a651a62aeab26cf437fb195407574f3583a8c28603b9e3f41241395cbf4f8", "ct" : "f2ffffffffffffffffffffffffffffff87336f2c3e85be548c0175422fd4fb045c92897fc21f6b57a26b23f9740b75855c92897fc21f6b57a26b23f9740b7585", "tag" : "06df93f651ea5cc56911f30d3e58f997", "result" : "valid", "flags" : [] }, { "tcId" : 249, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "3fe606108f35869df4c7aa0128464a1265f8d1f971da17437a2b5e04fbca1671fdbe843a0ad9be25055992ab6dcbc9f153354c0c1580af3662d5f8151e3f7e8271599ffc674a7d152794baf8b03265ce", "ct" : "a608a7889c19ad7587743519c412fbb3fcffffffffffffffffffffffffffffffea06685faa687e546871cee38c80c900fcffffffffffffffffffffffffffffffea06685faa687e546871cee38c80c900", "tag" : "9264fc0f47febb30661254daf9a06189", "result" : "valid", "flags" : [] }, { "tcId" : 250, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "6e8eb98cf7fffe4cd683568cf892991564f8d1f971da17437a2b5e04fbca1671c70f5d8b30c64bf2e6d1d613f40e0bf052354c0c1580af3662d5f8151e3f7e824be8464d5d5588c2c41cfe4029f7a7cf", "ct" : "f7601814e4d3d5a4a530c99414c628b4fdffffffffffffffffffffffffffffffd0b7b1ee90778b838bf98a5b15450b01fdffffffffffffffffffffffffffffffd0b7b1ee90778b838bf98a5b15450b01", "tag" : "69a124fc7f96e220d1a031ced5527279", "result" : "valid", "flags" : [] }, { "tcId" : 251, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "4f115e67ecd3d4178c4c60e713ab4e5e4156269fe3da101eeb0abf8dda20fe8fff47139a5f4e3f8e92d7a3b71eb4ff0e6aece983e64f97e43ff5295bc884fa7773a0085c32ddfcbeb01a8be4c34d5331a2d909c10a1bdcd318046d320583f6b7", "ct" : "d6ffffffffffffffffffffffffffffffd85108996dfff8a26ede1e76de151701e8ffffffffffffffffffffffffffffffc5265a700c30c72da2df2eb129447b0ae8ffffffffffffffffffffffffffffffc5265a700c30c72da2df2eb129447b0a", "tag" : "3ea8f9b2012321e63d5fb5bc2c5d332d", "result" : "valid", "flags" : [] }, { "tcId" : 252, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "66115e67ecd3d4178c4c60e713ab4e5e18f125ef374c1454b680e23427e7dc69e447139a5f4e3f8e92d7a3b71eb4ff0e858b08eb1d581570a7cd1e48593b757568a0085c32ddfcbeb01a8be4c34d53314dbee8a9f10c5e47803c5a21943c79b5", "ct" : "ffffffffffffffffffffffffffffffff81f60be9b969fce8335443cf23d235e7f3ffffffffffffffffffffffffffffff2a41bb18f72745b93ae719a2b8fbf408f3ffffffffffffffffffffffffffffff2a41bb18f72745b93ae719a2b8fbf408", "tag" : "dfaf8a3a15d45e7f4c3430048d8589f0", "result" : "valid", "flags" : [] }, { "tcId" : 253, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "b02ab747a310d6a3bbdb97018a3be8b341f8d1f971da17437a2b5e04fbca1671b7a338bc3423895f0fd96cdb27a787f277354c0c1580af3662d5f8151e3f7e823b44237a59b04a6f2d144488fa5e2bcd", "ct" : "29c416dfb03cfd4bc8680819666f5912d8ffffffffffffffffffffffffffffffa01bd4d99492492e62f13093c6ec8703d8ffffffffffffffffffffffffffffffa01bd4d99492492e62f13093c6ec8703", "tag" : "3408eb2b13a9b76befcedf699422d61f", "result" : "valid", "flags" : [] }, { "tcId" : 254, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "40115e67ecd3d4178c4c60e713ab4e5e380ef93aeb61aa307f141323c38e0685f647139a5f4e3f8e92d7a3b71eb4ff0e3f769a30e8951ff2fb365fa780fdde7e7aa0085c32ddfcbeb01a8be4c34d5331f7437a7204c154c5dcc71bce4dfad2be", "ct" : "d9ffffffffffffffffffffffffffffffa109d73c6544428cfac0b2d8c7bbef0be1ffffffffffffffffffffffffffffff90bc29c302ea4f3b661c584d613d5f03e1ffffffffffffffffffffffffffffff90bc29c302ea4f3b661c584d613d5f03", "tag" : "09f4f2a3936d7461a67ce022176bb8dd", "result" : "valid", "flags" : [] }, { "tcId" : 255, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "40115e67ecd3d4178c4c60e713ab4e5e060ef93aeb61aa307f141323c38e0685ee47139a5f4e3f8e92d7a3b71eb4ff0e2bca70bfcdf1171ab611d12bed5d627a62a0085c32ddfcbeb01a8be4c34d5331e3ff90fd21a55c2d91e09542205a6eba", "ct" : "d9ffffffffffffffffffffffffffffff9f09d73c6544428cfac0b2d8c7bbef0bf9ffffffffffffffffffffffffffffff8400c34c278e47d32b3bd6c10c9de307f9ffffffffffffffffffffffffffffff8400c34c278e47d32b3bd6c10c9de307", "tag" : "2eb2679aadfd824a5fd8fa2e4a55a65c", "result" : "valid", "flags" : [] }, { "tcId" : 256, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "56115e67ecd3d4178c4c60e713ab4e5e6c7e1312c6774fae7d1e5d0cc609028ff547139a5f4e3f8e92d7a3b71eb4ff0e81c9e61cbeeed5546b1ce5d8fef21a7a79a0085c32ddfcbeb01a8be4c34d533149fc065e52ba9e634ceda1b133f516ba", "ct" : "cffffffffffffffffffffffffffffffff5793d144852a712f8cafcf7c23ceb01e2ffffffffffffffffffffffffffffff2e0355ef5491859df636e2321f329b07e2ffffffffffffffffffffffffffffff2e0355ef5491859df636e2321f329b07", "tag" : "5e89349f6b011cd6e24ee6ac2f590c21", "result" : "valid", "flags" : [] }, { "tcId" : 257, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "2ea8410b4dca8c9d5369a033d8db61e46cf8d1f971da17437a2b5e04fbca1671f0f58e8bba6cf1a52146273d8fe0c4fc5a354c0c1580af3662d5f8151e3f7e827c12954dd7ff3295038b0f6e521968c3", "ct" : "b746e0935ee6a77520da3f2b348fd045f5ffffffffffffffffffffffffffffffe74d62ee1add31d44c6e7b756eabc40df5ffffffffffffffffffffffffffffffe74d62ee1add31d44c6e7b756eabc40d", "tag" : "b24537fcb0dcb6200b0285cafc9c3a7d", "result" : "valid", "flags" : [] }, { "tcId" : 258, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "17059a7c8883a28b90bd94ae44d1543662f8d1f971da17437a2b5e04fbca1671a23018bf8e68e413e99ac2d4ab3f8df154354c0c1580af3662d5f8151e3f7e822ed70379e3fb2723cb57ea8776c621ce", "ct" : "8eeb3be49baf8963e30e0bb6a885e597fbffffffffffffffffffffffffffffffb588f4da2ed9246284b29e9c4a748d00fbffffffffffffffffffffffffffffffb588f4da2ed9246284b29e9c4a748d00", "tag" : "43300400ea36e720361153ce0c5d637d", "result" : "valid", "flags" : [] }, { "tcId" : 259, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "aaa1b258fd4b54b497b520806a66d7aa68f8d1f971da17437a2b5e04fbca167199132a234a8c789bf8544547940ec3f35e354c0c1580af3662d5f8151e3f7e8215f431e5271fbbabda996d1449f76fcc", "ct" : "334f13c0ee677f5ce406bf988632660bf1ffffffffffffffffffffffffffffff8eabc646ea3db8ea957c190f7545c302f1ffffffffffffffffffffffffffffff8eabc646ea3db8ea957c190f7545c302", "tag" : "d79a0310124adc30c6b64cdef8993e8d", "result" : "valid", "flags" : [] }, { "tcId" : 260, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "4c115e67ecd3d4178c4c60e713ab4e5ebb5357ed314ad740b9910fad6f01d781f047139a5f4e3f8e92d7a3b71eb4ff0ec8042b414fdd1bba3a6c936b7ed678797ca0085c32ddfcbeb01a8be4c34d53310031cb03a389508d1d9dd702b3d174b9", "ct" : "d5ffffffffffffffffffffffffffffff225479ebbf6f3ffc3c45ae566b343e0fe7ffffffffffffffffffffffffffffff67ce98b2a5a24b73a74694819f16f904e7ffffffffffffffffffffffffffffff67ce98b2a5a24b73a74694819f16f904", "tag" : "e6022cc3ba20e3f9065fdfcc43a9dc40", "result" : "valid", "flags" : [] }, { "tcId" : 261, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "66115e67ecd3d4178c4c60e713ab4e5ef64296975af7fced168181f76c6508e1c947139a5f4e3f8e92d7a3b71eb4ff0e4975060f7ddef4a098699333b30fbf7c45a0085c32ddfcbeb01a8be4c34d53318140e64d918abf97bf98d75a7e08b3bc", "ct" : "ffffffffffffffffffffffffffffffff6f45b891d4d214519355200c6850e16fdeffffffffffffffffffffffffffffffe6bfb5fc97a1a469054394d952cf3e01deffffffffffffffffffffffffffffffe6bfb5fc97a1a469054394d952cf3e01", "tag" : "353e304fd8553286b26e0d59942fe7cd", "result" : "valid", "flags" : [] }, { "tcId" : 262, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "9841cfc927a57dc491ab35427ff935e66ef8d1f971da17437a2b5e04fbca1671a683c8f9f9e6780fda4940ddedd76bf258354c0c1580af3662d5f8151e3f7e822a64d33f9475bb3ff884688e302ec7cd", "ct" : "01af6e513489562ce218aa5a93ad8447f7ffffffffffffffffffffffffffffffb13b249c5957b87eb7611c950c9c6b03f7ffffffffffffffffffffffffffffffb13b249c5957b87eb7611c950c9c6b03", "tag" : "0aeb04ecf7def40c42025bbae5509169", "result" : "valid", "flags" : [] }, { "tcId" : 263, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "42115e67ecd3d4178c4c60e713ab4e5e0b61bf9b7caf83cc34da625593514289e847139a5f4e3f8e92d7a3b71eb4ff0e696a5c7fb9da9cd4a39c8591086db42d64a0085c32ddfcbeb01a8be4c34d5331a15fbc3d558ed7e3846dc1f8c56ab8ed", "ct" : "dbffffffffffffffffffffffffffffff9266919df28a6b70b10ec3ae9764ab07ffffffffffffffffffffffffffffffffc6a0ef8c53a5cc1d3eb6827be9ad3550ffffffffffffffffffffffffffffffffc6a0ef8c53a5cc1d3eb6827be9ad3550", "tag" : "8fc4f77a6ee052a4c314780b8df9a2d0", "result" : "valid", "flags" : [] }, { "tcId" : 264, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "4b115e67ecd3d4178c4c60e713ab4e5ef28e4d0f20ca1644470c9cdac6000887ed47139a5f4e3f8e92d7a3b71eb4ff0e1464775bacd5c69fe26e1a74968ea27e61a0085c32ddfcbeb01a8be4c34d5331dc51971940818da8c59f5e1d5b89aebe", "ct" : "d2ffffffffffffffffffffffffffffff6b896309aeeffef8c2d83d21c235e109faffffffffffffffffffffffffffffffbbaec4a846aa96567f441d9e774e2303faffffffffffffffffffffffffffffffbbaec4a846aa96567f441d9e774e2303", "tag" : "232ff78a96f347b453ba711b79367ee0", "result" : "valid", "flags" : [] }, { "tcId" : 265, "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "00010203040506072dd4cd40", "aad" : "ffffffff", "msg" : "4d115e67ecd3d4178c4c60e713ab4e5e6ee628fc4b5830184cd293364a213e84fe47139a5f4e3f8e92d7a3b71eb4ff0e29db953ad5458fea61f013ea1854fe7572a0085c32ddfcbeb01a8be4c34d5331e1ee75783911c4dd46015783d553f2b5", "ct" : "d4fffffffffffffffffffffffffffffff7e106fac57dd8a4c90632cd4e14d70ae9ffffffffffffffffffffffffffffff861126c93f3adf23fcda1400f9947f08e9ffffffffffffffffffffffffffffff861126c93f3adf23fcda1400f9947f08", "tag" : "e00d2e8bae5d09c28e9bf59409545d09", "result" : "valid", "flags" : [] }, { "tcId" : 266, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "19de9b9ec8b247d42bbee2016d6715babc286fd979807951b183a188930ad15edcf0b056a2eecc51d30838e640615e14890e659fd3028c904e65018fdfd6038333d14da7b4f76f9f68fa8903138d563c33b7fb50c3e7ebca970f6f89a88a82d6", "ct" : "f9ffffffffffffffffffffffffffffff015d1565924f6c7418de9babf8be4407edffffffffffffffffffffffffffffff2e110e5e1c0468cbaad99c8abeffff07edffffffffffffffffffffffffffffff2e110e5e1c0468cbaad99c8abeffff07", "tag" : "47e5d4294239db73b836c04070ff5b2d", "result" : "valid", "flags" : [] }, { "tcId" : 267, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715ba839f811ad0310c77052f45320b0d9560c4f0b056a2eecc51d30838e640615e1470d6b14fd209fedf261fd1d250d3478d2bd14da7b4f76f9f68fa8903138d563cca6f2f80c2ec9985ff75bfd4278fc6d8", "ct" : "ffffffffffffffffffffffffffffffff3eeafba63bfe1952ac727f1160b90039f5ffffffffffffffffffffffffffffffd7c9da8e1d0f1a84c2a34cd731fabb09f5ffffffffffffffffffffffffffffffd7c9da8e1d0f1a84c2a34cd731fabb09", "tag" : "232c882f7a1a2f808ccf26496cff5b3d", "result" : "valid", "flags" : [] }, { "tcId" : 268, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "97311cd6e2d25a7b4eaa16f0a61ca6246b8a85431430eada56a2c5dc944b6aa695136310b6b6b5c17c9f8c02ba7d0aeb71e0943e30f91ba41b4362fa9ed6037b7a329ee1a0af160fc76d3de7e99102c3", "ct" : "771078b7d59fe2509aeb0b0e34844c61d6ffffffffffffffffffffffffffffffa41c2cb9eba7866f50684b1b05e3ab00d6ffffffffffffffffffffffffffffffa41c2cb9eba7866f50684b1b05e3ab00", "tag" : "d71bc70d5adc74e7dfd89406fc15f044", "result" : "valid", "flags" : [] }, { "tcId" : 269, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "34de9b9ec8b247d42bbee2016d6715ba74cf7e9d82b7e8ed9ec965f6ea310951dc104940e08a4222556828eba459f65a4a006d28729d95d79d2372f77aeeab35", "ct" : "d4ffffffffffffffffffffffffffffffc9ba04216978fdc837945fd581859c08ed1f06e9bd9b718c799feff21bc757b1ed1f06e9bd9b718c799feff21bc757b1", "tag" : "21e63987d494673f3040ae9de2bc0da0", "result" : "valid", "flags" : [] }, { "tcId" : 270, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "e72b83514e5e50509070359c1cac7e1c428a85431430eada56a2c5dc944b6aa6dad35950d8a9b55a472f9bb8860a526358e0943e30f91ba41b4362fa9ed6037b35f2a4a1ceb01694fcdd2a5dd5e65a4b", "ct" : "070ae7307913e87b443128628e349459ffffffffffffffffffffffffffffffffebdc16f985b886f46bd85ca13994f388ffffffffffffffffffffffffffffffffebdc16f985b886f46bd85ca13994f388", "tag" : "e4fb945d6a2d0b947834317cc415f024", "result" : "valid", "flags" : [] }, { "tcId" : 271, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "8c6165f445443588041b6e044fb6baae728a85431430eada56a2c5dc944b6aa6881a54c09516a1f1cae7b9dd71130ee168e0943e30f91ba41b4362fa9ed6037b673ba931830f023f7115083822ff06c9", "ct" : "6c40019572098da3d05a73fadd2e50ebcfffffffffffffffffffffffffffffffb9151b69c807925fe6107ec4ce8daf0acfffffffffffffffffffffffffffffffb9151b69c807925fe6107ec4ce8daf0a", "tag" : "c0424863a20e5fa04ccd9784c015f034", "result" : "valid", "flags" : [] }, { "tcId" : 272, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "18e36174545fa7ec9ea9f05d7057c5ca638a85431430eada56a2c5dc944b6aa6434e1c5e71005b690ca5cb8d580b89ed79e0943e30f91ba41b4362fa9ed6037bac6fe1af6719f8a7b7577a680be781c5", "ct" : "f8c2051563121fc74ae8eda3e2cf2f8fdeffffffffffffffffffffffffffffff724153f72c1168c720520c94e7952806deffffffffffffffffffffffffffffff724153f72c1168c720520c94e7952806", "tag" : "aa7293ffe5db30a31f2581e0e7ae56ed", "result" : "valid", "flags" : [] }, { "tcId" : 273, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "12de9b9ec8b247d42bbee2016d6715ba54305dff6b61c40b775c352d025c1a56d7f0b056a2eecc51d30838e640615e14bce574e9e11afedbdca021e53bb9188338d14da7b4f76f9f68fa8903138d563c065cea26f1ff998105ca4fe34ce599d6", "ct" : "f2ffffffffffffffffffffffffffffffe945274380aed12ede010f0e69e88f0fe6ffffffffffffffffffffffffffffff1bfa1f282e1c1a80381cbce05a90e407e6ffffffffffffffffffffffffffffff1bfa1f282e1c1a80381cbce05a90e407", "tag" : "42e5d43d1e808e79f017144d4498c235", "result" : "valid", "flags" : [] }, { "tcId" : 274, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715badf0599194b0ce890cc1d8eb383b57f38dcf0b056a2eecc51d30838e640615e1435df81077d068077ce805ea592f6f88833d14da7b4f76f9f68fa8903138d563c8f661fc86de3e72d17ea30a3e5aa79dd", "ct" : "ffffffffffffffffffffffffffffffff6270e3a5a0c3fdb56540b490e801ea61edffffffffffffffffffffffffffffff92c0eac6b200642c2a3cc3a0f3df040cedffffffffffffffffffffffffffffff92c0eac6b200642c2a3cc3a0f3df040c", "tag" : "6cf2f9230af8679e7ecb19421362fce3", "result" : "valid", "flags" : [] }, { "tcId" : 275, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "39de9b9ec8b247d42bbee2016d6715ba4092e1f9a22c8b18184d805c128ade57c7f0b056a2eecc51d30838e640615e1464fe8b9bdd215a620973affefe93398528d14da7b4f76f9f68fa8903138d563cde471554cdc43d38d019c1f889cfb8d0", "ct" : "d9fffffffffffffffffffffffffffffffde79b4549e39e3db110ba7f793e4b0ef6ffffffffffffffffffffffffffffffc3e1e05a1227be39edcf32fb9fbac501f6ffffffffffffffffffffffffffffffc3e1e05a1227be39edcf32fb9fbac501", "tag" : "6d46d2230a9848d518f9d94bb2c49caa", "result" : "valid", "flags" : [] }, { "tcId" : 276, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "12de9b9ec8b247d42bbee2016d6715ba327f3a1befb4287c17450391ed0eb854d6f0b056a2eecc51d30838e640615e141460d3545c29ddc790711b8e7533698539d14da7b4f76f9f68fa8903138d563caed94d9b4cccba9d491b7588026fe8d0", "ct" : "f2ffffffffffffffffffffffffffffff8f0a40a7047b3d59be1839b286ba2d0de7ffffffffffffffffffffffffffffffb37fb895932f399c74cd868b141a9501e7ffffffffffffffffffffffffffffffb37fb895932f399c74cd868b141a9501", "tag" : "74dda12e0558877bc0e40c3eace0af29", "result" : "valid", "flags" : [] }, { "tcId" : 277, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1bde9b9ec8b247d42bbee2016d6715ba85b67664ee49fa347fbfd2dd92007c57def0b056a2eecc51d30838e640615e14fb27ee075b3c0f0f682babdde63dad8731d14da7b4f76f9f68fa8903138d563c419e70c84bd96855b141c5db91612cd2", "ct" : "fbffffffffffffffffffffffffffffff38c30cd80586ef11d6e2e8fef9b4e90eefffffffffffffffffffffffffffffff5c3885c6943aeb548c9736d887145103efffffffffffffffffffffffffffffff5c3885c6943aeb548c9736d887145103", "tag" : "502455343d39db87947d7346a8e0af39", "result" : "valid", "flags" : [] }, { "tcId" : 278, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "36de9b9ec8b247d42bbee2016d6715ba1132811b2f18321ba99b12432c7f865aa3352cd2d7ac70b4c6f5419767926e20352508ba45bba7410ebe1b8bb925334f", "ct" : "d6ffffffffffffffffffffffffffffffac47fba7c4d7273e00c6286047cb1303923a637b8abd431aea02868ed80ccfcb923a637b8abd431aea02868ed80ccfcb", "tag" : "14fba149d1c0edc8aa665851126b5afd", "result" : "valid", "flags" : [] }, { "tcId" : 279, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715baf999461058f6d7733e5cd0d1639d9025cbf0b056a2eecc51d30838e640615e14520a0da50439db00e289e1791342068e24d14da7b4f76f9f68fa8903138d563ce8b3936a14dcbc5a3be38f7f641e87db", "ct" : "ffffffffffffffffffffffffffffffff44ec3cacb339c2569701eaf20829057cfafffffffffffffffffffffffffffffff5156664cb3f3f5b06357c7c726bfa0afafffffffffffffffffffffffffffffff5156664cb3f3f5b06357c7c726bfa0a", "tag" : "bf7fbd422cbf0e700fd1605be8fd212f", "result" : "valid", "flags" : [] }, { "tcId" : 280, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "15de9b9ec8b247d42bbee2016d6715bacc1629a40cd11eafdf04138b45afe458eff0b056a2eecc51d30838e640615e14340ac9b45a5896a418a8cee8032e078f00d14da7b4f76f9f68fa8903138d563c8eb3577b4abdf1fec1c2a0ee747286da", "ct" : "f5ffffffffffffffffffffffffffffff71635318e71e0b8a765929a82e1b7101deffffffffffffffffffffffffffffff9315a275955e72fffc1453ed6207fb0bdeffffffffffffffffffffffffffffff9315a275955e72fffc1453ed6207fb0b", "tag" : "c6f23204865b0adde0070037d6538dd3", "result" : "valid", "flags" : [] }, { "tcId" : 281, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "31de9b9ec8b247d42bbee2016d6715baff746ef53ec3357cbc3c3ce4ab1d2d51ed9eb456dc9d9b59f656a5d2d974d26a7b8e903e4e8a4cac3e1dffce07c38f05", "ct" : "d1ffffffffffffffffffffffffffffff42011449d50c2059156106c7c0a9b808dc91fbff818ca8f7daa162cb66ea7381dc91fbff818ca8f7daa162cb66ea7381", "tag" : "8cff61b7b3919ed6bde72b36e0d31326", "result" : "valid", "flags" : [] }, { "tcId" : 282, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "19de9b9ec8b247d42bbee2016d6715babf286fd979807951b183a188930ad15ecef0b056a2eecc51d30838e640615e1464413d71939b9cb0a4d32ef115da9e1021d14da7b4f76f9f68fa8903138d563cdef8a3be837efbea7db940f762861f45", "ct" : "f9ffffffffffffffffffffffffffffff025d1565924f6c7418de9babf8be4407ffffffffffffffffffffffffffffffffc35e56b05c9d78eb406fb3f474f36294ffffffffffffffffffffffffffffffffc35e56b05c9d78eb406fb3f474f36294", "tag" : "369cf17011cae47539e2723f010cf980", "result" : "valid", "flags" : [] }, { "tcId" : 283, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "19de9b9ec8b247d42bbee2016d6715babd286fd979807951b183a188930ad15ee3f0b056a2eecc51d30838e640615e14f25e78fe1b53ae416d1fbc698522618f0cd14da7b4f76f9f68fa8903138d563c48e7e6310bb6c91bb475d26ff27ee0da", "ct" : "f9ffffffffffffffffffffffffffffff005d1565924f6c7418de9babf8be4407d2ffffffffffffffffffffffffffffff5541133fd4554a1a89a3216ce40b9d0bd2ffffffffffffffffffffffffffffff5541133fd4554a1a89a3216ce40b9d0b", "tag" : "532eb8e272a8d171378b0d42dff2bed9", "result" : "valid", "flags" : [] }, { "tcId" : 284, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "32de9b9ec8b247d42bbee2016d6715ba258d5d3e441683f546beba2e23755f5ccef0b056a2eecc51d30838e640615e149d13fdf8fa899836fa5c410d4ccd25ea21d14da7b4f76f9f68fa8903138d563c27aa6337ea6cff6c23362f0b3b91a4bf", "ct" : "d2ffffffffffffffffffffffffffffff98f82782afd996d0efe3800d48c1ca05ffffffffffffffffffffffffffffffff3a0c9639358f7c6d1ee0dc082de4d96effffffffffffffffffffffffffffffff3a0c9639358f7c6d1ee0dc082de4d96e", "tag" : "d1be7426cd12446fe52e8d45331e0835", "result" : "valid", "flags" : [] }, { "tcId" : 285, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715bad64add2aa3c5a30a31d9e65e90f93ad1cbf0b056a2eecc51d30838e640615e14de9aeab86144d5464811b2373ba4cc8324d14da7b4f76f9f68fa8903138d563c6423747771a1b21c917bdc314cf84dd6", "ct" : "ffffffffffffffffffffffffffffffff6b3fa796480ab62f9884dc7dfb4daf88faffffffffffffffffffffffffffffff79858179ae42311dacad2f325a8d3007faffffffffffffffffffffffffffffff79858179ae42311dacad2f325a8d3007", "tag" : "62630c18de8c10876adb9f30f300963f", "result" : "valid", "flags" : [] }, { "tcId" : 286, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715bacc3492272b8a4b112a4e7d7ccf092692cef0b056a2eecc51d30838e640615e1430ce678e9375b2af0b82c2d2fbd7928c21d14da7b4f76f9f68fa8903138d563c8a77f9418390d5f5d2e8acd48c8b13d9", "ct" : "ffffffffffffffffffffffffffffffff7141e89bc0455e348313475fa4bdb3cbffffffffffffffffffffffffffffffff97d10c4f5c7356f4ef3e5fd79afe6e08ffffffffffffffffffffffffffffffff97d10c4f5c7356f4ef3e5fd79afe6e08", "tag" : "feb6412b9031f076eddcd9426fff5b31", "result" : "valid", "flags" : [] }, { "tcId" : 287, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "34de9b9ec8b247d42bbee2016d6715ba722b6549c9df0f4b04b5f7432203fa54cef0b056a2eecc51d30838e640615e1487de186cd28e43544c73de628fd1d60e21d14da7b4f76f9f68fa8903138d563c3d6786a3c26b240e9519b064f88d575b", "ct" : "d4ffffffffffffffffffffffffffffffcf5e1ff522101a6eade8cd6049b76f0dffffffffffffffffffffffffffffffff20c173ad1d88a70fa8cf4367eef82a8affffffffffffffffffffffffffffffff20c173ad1d88a70fa8cf4367eef82a8a", "tag" : "dafdf430c8124483c175404b6bff5b41", "result" : "valid", "flags" : [] }, { "tcId" : 288, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "3dde9b9ec8b247d42bbee2016d6715bac5629699cfd4d9036cef478ed705be5650f575882c3800f757ea6e0f8c6d47acc6e551e0be2fd7029fa1341352da1ac3", "ct" : "ddffffffffffffffffffffffffffffff7817ec25241bcc26c5b27dadbcb12b0f61fa3a21712933597b1da91633f3e64761fa3a21712933597b1da91633f3e647", "tag" : "f8800c5b6283dddfc41f935c01bd0d24", "result" : "valid", "flags" : [] }, { "tcId" : 289, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715ba66d624f288f52941ca24865ce96f0d9736ff33a27c23f4976fc74f1fcd82f5cca0ef17caee342362a78c15031335a8a3", "ct" : "ffffffffffffffffffffffffffffffffdba35e4e633a3c646379bc7f82db98ce07f07c0b2132c73943308806721c542707f07c0b2132c73943308806721c5427", "tag" : "38bfb8318c627d86c34bab1f1ebd0db0", "result" : "valid", "flags" : [] }, { "tcId" : 290, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "f4ebbe3fca96bc4885b35582c43e0eb3588a85431430eada56a2c5dc944b6aa6b4570e8446e886bcbff82a24f49be5ed42e0943e30f91ba41b4362fa9ed6037b5b76f37550f12572040a9bc1a777edc5", "ct" : "14cada5efddb046351f2487c56a6e4f6e5ffffffffffffffffffffffffffffff8558412d1bf9b512930fed3d4b054406e5ffffffffffffffffffffffffffffff8558412d1bf9b512930fed3d4b054406", "tag" : "af7293eb09957d9de7432dd41316f0e4", "result" : "valid", "flags" : [] }, { "tcId" : 291, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1ade9b9ec8b247d42bbee2016d6715ba571a3fca3cda7def4c93d4a382ca3a57eaf0b056a2eecc51d30838e640615e1476cddbee2f185776174f6df3bbe5b38105d14da7b4f76f9f68fa8903138d563ccc7445213ffd302cce2503f5ccb932d4", "ct" : "faffffffffffffffffffffffffffffffea6f4576d71568cae5ceee80e97eaf0edbffffffffffffffffffffffffffffffd1d2b02fe01eb32df3f3f0f6dacc4f05dbffffffffffffffffffffffffffffffd1d2b02fe01eb32df3f3f0f6dacc4f05", "tag" : "e178b0d5eb9bc551fa645c49f9f17667", "result" : "valid", "flags" : [] }, { "tcId" : 292, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "1fde9b9ec8b247d42bbee2016d6715babe31a501536a7c91e4a102cc27cdfe09d2f0b056a2eecc51d30838e640615e14dd9416a12e2f81bdee023d462feef7833dd14da7b4f76f9f68fa8903138d563c672d886e3ecae6e73768534058b276d6", "ct" : "ffffffffffffffffffffffffffffffff0344dfbdb8a569b44dfc38ef4c796b50e3ffffffffffffffffffffffffffffff7a8b7d60e12965e60abea0434ec70b07e3ffffffffffffffffffffffffffffff7a8b7d60e12965e60abea0434ec70b07", "tag" : "bdbf63db237d195ecefdc251f5f17677", "result" : "valid", "flags" : [] }, { "tcId" : 293, "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "iv" : "000102030405060703e76f6f", "aad" : "ffffffff", "msg" : "3ede9b9ec8b247d42bbee2016d6715ba8567a7fde812a3aa2f552a33c1718c58e2f0b056a2eecc51d30838e640615e14bb8729fd148f23b2a916b7f40f2f29810dd14da7b4f76f9f68fa8903138d563c013eb732046a44e8707cd9f27873a8d4", "ct" : "deffffffffffffffffffffffffffffff3812dd4103ddb68f86081010aac51901d3ffffffffffffffffffffffffffffff1c98423cdb89c7e94daa2af16e06d505d3ffffffffffffffffffffffffffffff1c98423cdb89c7e94daa2af16e06d505", "tag" : "b4ccb422bc5f7264aff73f3675ff5b19", "result" : "valid", "flags" : [] } ] }, { "ivSize" : 0, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 294, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 64, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 295, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "0001020304050607", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 88, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 296, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 104, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 297, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b0c", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 112, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 298, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b0c0d", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 128, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 299, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b0c0d0e0f", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] }, { "ivSize" : 160, "keySize" : 256, "tagSize" : 128, "type" : "AeadTest", "tests" : [ { "tcId" : 300, "comment" : "invalid nonce size", "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "iv" : "000102030405060708090a0b0c0d0e0f10111213", "aad" : "", "msg" : "", "ct" : "", "tag" : "", "result" : "invalid", "flags" : [] } ] } ] } s2a-go-0.1.8/internal/record/internal/aeadcrypter/testutil/000077500000000000000000000000001464711036600237065ustar00rootroot00000000000000s2a-go-0.1.8/internal/record/internal/aeadcrypter/testutil/common.go000066400000000000000000000041411464711036600255250ustar00rootroot00000000000000/* * * Copyright 2021 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 testutil is a collection of test utilities for the AEAD crypter. package testutil import ( "encoding/hex" ) // Constants indicating whether the test vector is valid or not. const ( ValidResult = "valid" InvalidResult = "invalid" ) // CryptoTestVector is a struct representing a test vector for an S2AAEADCrypter // instance. type CryptoTestVector struct { Desc string ID int Key, Plaintext, Ciphertext, Tag, Nonce, Aad []byte Result string AllocateDst bool } // TestVector is a struct for a WycheProof test vector. type TestVector struct { TcID int `json:"tcId"` Comment string `json:"comment"` Key string `json:"key"` IV string `json:"iv"` Aad string `json:"aad"` Msg string `json:"msg"` Ct string `json:"ct"` Tag string `json:"tag"` Result string `json:"result"` } // TestGroup is a struct for a WycheProof test group. type TestGroup struct { IVSize int `json:"ivSize"` KeySize int `json:"keySize"` TagSize int `json:"tagSize"` Tests []TestVector `json:"tests"` } // TestFile is a struct for a WycheProof test file. type TestFile struct { TestGroups []TestGroup `json:"testGroups"` } // Dehex converts a byte string into a byte array. func Dehex(s string) []byte { if len(s) == 0 { return make([]byte, 0) } b, err := hex.DecodeString(s) if err != nil { panic(err) } return b } s2a-go-0.1.8/internal/record/internal/aeadcrypter/testutil/wycheproofutil.go000066400000000000000000000043711464711036600273250ustar00rootroot00000000000000/* * * Copyright 2021 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 testutil import ( "bytes" "encoding/json" "os" "testing" ) // ParseWycheProofTestVectors takes a path to a WycheProof test vector, a test // group filter, and returns the resulting CryptoTestVector. The test group // filter will be used to filter out unsupported test inputs. func ParseWycheProofTestVectors(jsonFilePath string, shouldFilter func(TestGroup) bool, t *testing.T) []CryptoTestVector { jsonFile, err := os.Open(jsonFilePath) if err != nil { t.Fatalf("failed to open wycheproof json test vectors file: %v", err) } defer jsonFile.Close() dec := json.NewDecoder(jsonFile) var tf TestFile if err = dec.Decode(&tf); err != nil { t.Fatalf("failed to decode wycheproof json file: %v", err) } var testVectors []CryptoTestVector for _, testGroup := range tf.TestGroups { // Skip over unsupported inputs. if shouldFilter(testGroup) { continue } for _, test := range testGroup.Tests { testVectors = append(testVectors, CryptoTestVector{ Key: Dehex(test.Key), Plaintext: Dehex(test.Msg), Ciphertext: Dehex(test.Ct), Tag: Dehex(test.Tag), Nonce: Dehex(test.IV), Aad: Dehex(test.Aad), Result: test.Result, Desc: test.Comment, ID: test.TcID, AllocateDst: true, }) } } return testVectors } // IsFailure takes in test result validity, error message, test output, // expected test output, and returns true if the test failed. func IsFailure(result string, err error, got, expected []byte) bool { return (result == ValidResult && (err != nil || !bytes.Equal(got, expected))) || (result == InvalidResult && err == nil && bytes.Equal(got, expected)) } s2a-go-0.1.8/internal/record/internal/halfconn/000077500000000000000000000000001464711036600213165ustar00rootroot00000000000000s2a-go-0.1.8/internal/record/internal/halfconn/ciphersuite.go000066400000000000000000000075061464711036600242010ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import ( "crypto/sha256" "crypto/sha512" "fmt" "hash" s2apb "github.com/google/s2a-go/internal/proto/common_go_proto" "github.com/google/s2a-go/internal/record/internal/aeadcrypter" ) // ciphersuite is the interface for retrieving ciphersuite-specific information // and utilities. type ciphersuite interface { // keySize returns the key size in bytes. This refers to the key used by // the AEAD crypter. This is derived by calling HKDF expand on the traffic // secret. keySize() int // nonceSize returns the nonce size in bytes. nonceSize() int // trafficSecretSize returns the traffic secret size in bytes. This refers // to the secret used to derive the traffic key and nonce, as specified in // https://tools.ietf.org/html/rfc8446#section-7. trafficSecretSize() int // hashFunction returns the hash function for the ciphersuite. hashFunction() func() hash.Hash // aeadCrypter takes a key and creates an AEAD crypter for the ciphersuite // using that key. aeadCrypter(key []byte) (aeadcrypter.S2AAEADCrypter, error) } func newCiphersuite(ciphersuite s2apb.Ciphersuite) (ciphersuite, error) { switch ciphersuite { case s2apb.Ciphersuite_AES_128_GCM_SHA256: return &aesgcm128sha256{}, nil case s2apb.Ciphersuite_AES_256_GCM_SHA384: return &aesgcm256sha384{}, nil case s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256: return &chachapolysha256{}, nil default: return nil, fmt.Errorf("unrecognized ciphersuite: %v", ciphersuite) } } // aesgcm128sha256 is the AES-128-GCM-SHA256 implementation of the ciphersuite // interface. type aesgcm128sha256 struct{} func (aesgcm128sha256) keySize() int { return aeadcrypter.AES128GCMKeySize } func (aesgcm128sha256) nonceSize() int { return aeadcrypter.NonceSize } func (aesgcm128sha256) trafficSecretSize() int { return aeadcrypter.SHA256DigestSize } func (aesgcm128sha256) hashFunction() func() hash.Hash { return sha256.New } func (aesgcm128sha256) aeadCrypter(key []byte) (aeadcrypter.S2AAEADCrypter, error) { return aeadcrypter.NewAESGCM(key) } // aesgcm256sha384 is the AES-256-GCM-SHA384 implementation of the ciphersuite // interface. type aesgcm256sha384 struct{} func (aesgcm256sha384) keySize() int { return aeadcrypter.AES256GCMKeySize } func (aesgcm256sha384) nonceSize() int { return aeadcrypter.NonceSize } func (aesgcm256sha384) trafficSecretSize() int { return aeadcrypter.SHA384DigestSize } func (aesgcm256sha384) hashFunction() func() hash.Hash { return sha512.New384 } func (aesgcm256sha384) aeadCrypter(key []byte) (aeadcrypter.S2AAEADCrypter, error) { return aeadcrypter.NewAESGCM(key) } // chachapolysha256 is the ChaChaPoly-SHA256 implementation of the ciphersuite // interface. type chachapolysha256 struct{} func (chachapolysha256) keySize() int { return aeadcrypter.Chacha20Poly1305KeySize } func (chachapolysha256) nonceSize() int { return aeadcrypter.NonceSize } func (chachapolysha256) trafficSecretSize() int { return aeadcrypter.SHA256DigestSize } func (chachapolysha256) hashFunction() func() hash.Hash { return sha256.New } func (chachapolysha256) aeadCrypter(key []byte) (aeadcrypter.S2AAEADCrypter, error) { return aeadcrypter.NewChachaPoly(key) } s2a-go-0.1.8/internal/record/internal/halfconn/ciphersuite_test.go000066400000000000000000000101671464711036600252350ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import ( "crypto/sha256" "crypto/sha512" "hash" "reflect" "testing" s2apb "github.com/google/s2a-go/internal/proto/common_go_proto" "github.com/google/s2a-go/internal/record/internal/aeadcrypter" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) func TestCiphersuites(t *testing.T) { for _, tc := range []struct { s2aProtoCiphersuite s2apb.Ciphersuite expectedCiphersuite ciphersuite key []byte keySize, NonceSize, trafficSecretSize int hashFunction func() hash.Hash aeadCrypterConstructor func([]byte) (aeadcrypter.S2AAEADCrypter, error) }{ { s2aProtoCiphersuite: s2apb.Ciphersuite_AES_128_GCM_SHA256, expectedCiphersuite: &aesgcm128sha256{}, key: testutil.Dehex("88ee087fd95da9fbf6725aa9d757b0cd"), keySize: aeadcrypter.AES128GCMKeySize, NonceSize: aeadcrypter.NonceSize, trafficSecretSize: aeadcrypter.SHA256DigestSize, hashFunction: sha256.New, aeadCrypterConstructor: aeadcrypter.NewAESGCM, }, { s2aProtoCiphersuite: s2apb.Ciphersuite_AES_256_GCM_SHA384, expectedCiphersuite: &aesgcm256sha384{}, key: testutil.Dehex("83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a823"), keySize: aeadcrypter.AES256GCMKeySize, NonceSize: aeadcrypter.NonceSize, trafficSecretSize: aeadcrypter.SHA384DigestSize, hashFunction: sha512.New384, aeadCrypterConstructor: aeadcrypter.NewAESGCM, }, { s2aProtoCiphersuite: s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256, expectedCiphersuite: &chachapolysha256{}, key: testutil.Dehex("83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a823"), keySize: aeadcrypter.Chacha20Poly1305KeySize, NonceSize: aeadcrypter.NonceSize, trafficSecretSize: aeadcrypter.SHA256DigestSize, hashFunction: sha256.New, aeadCrypterConstructor: aeadcrypter.NewChachaPoly, }, } { t.Run(tc.s2aProtoCiphersuite.String(), func(t *testing.T) { hc, err := newCiphersuite(tc.s2aProtoCiphersuite) if err != nil { t.Fatalf("newCiphersuite(%v) failed: %v", tc.s2aProtoCiphersuite, err) } if got, want := reflect.TypeOf(hc), reflect.TypeOf(tc.expectedCiphersuite); got != want { t.Fatalf("newCiphersuite(%v) = %v, want %v", tc.s2aProtoCiphersuite, got, want) } if got, want := hc.keySize(), tc.keySize; got != want { t.Errorf("hc.keySize() = %v, want %v", got, want) } if got, want := hc.nonceSize(), tc.NonceSize; got != want { t.Errorf("hc.nonceSize() = %v, want %v", got, want) } if got, want := hc.trafficSecretSize(), tc.trafficSecretSize; got != want { t.Errorf("hc.trafficSecretSize() = %v, want %v", got, want) } if got, want := reflect.TypeOf(hc.hashFunction()), reflect.TypeOf(tc.hashFunction); got != want { t.Errorf("hc.hashFunction() = %v, want %v", got, want) } aeadCrypter, err := hc.aeadCrypter(tc.key) if err != nil { t.Fatalf("hc.aeadCrypter(%v) failed: %v", tc.key, err) } tcAEADCrypter, err := tc.aeadCrypterConstructor(make([]byte, tc.keySize)) if err != nil { t.Fatalf("tc.aeadCrypterConstructor(make([]byte, %v)) failed: %v", tc.keySize, err) } if got, want := reflect.TypeOf(aeadCrypter), reflect.TypeOf(tcAEADCrypter); got != want { t.Errorf("hc.aeadCrypter(%v) = %v, want %v", tc.key, got, want) } }) } } s2a-go-0.1.8/internal/record/internal/halfconn/counter.go000066400000000000000000000030201464711036600233170ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import "errors" // counter is a 64-bit counter. type counter struct { val uint64 hasOverflowed bool } // newCounter creates a new counter with the initial value set to val. func newCounter(val uint64) counter { return counter{val: val} } // value returns the current value of the counter. func (c *counter) value() (uint64, error) { if c.hasOverflowed { return 0, errors.New("counter has overflowed") } return c.val, nil } // increment increments the counter and checks for overflow. func (c *counter) increment() { // If the counter is already invalid due to overflow, there is no need to // increase it. We check for the hasOverflowed flag in the call to value(). if c.hasOverflowed { return } c.val++ if c.val == 0 { c.hasOverflowed = true } } // reset sets the counter value to zero and sets the hasOverflowed flag to // false. func (c *counter) reset() { c.val = 0 c.hasOverflowed = false } s2a-go-0.1.8/internal/record/internal/halfconn/counter_test.go000066400000000000000000000060021464711036600243610ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import ( "math" "testing" ) func TestNewCounter(t *testing.T) { counter := newCounter(1) if got, want := counter.val, uint64(1); got != want { t.Errorf("counter.val = %v, want %v", got, want) } if got, want := counter.hasOverflowed, false; got != want { t.Errorf("counter.hasOverflowed = %v, want %v", got, want) } } func TestCounterInc(t *testing.T) { for _, tc := range []struct { desc string counter, expectedCounter uint64 shouldOverflow bool }{ { desc: "basic 1", counter: 0, expectedCounter: 1, }, { desc: "basic 2", counter: 123, expectedCounter: 124, }, { desc: "almost overflow", counter: math.MaxUint64 - 1, expectedCounter: math.MaxUint64, }, { desc: "max overflow", counter: math.MaxUint64, shouldOverflow: true, }, } { t.Run(tc.desc, func(t *testing.T) { c := counter{val: tc.counter} c.increment() val, err := c.value() if got, want := err == nil, !tc.shouldOverflow; got != want { t.Errorf("counter starting with %v, val()=(err=nil)=%v, want %v", tc.counter, got, want) } if got, want := val, tc.expectedCounter; err == nil && got != want { t.Errorf("counter starting with %v, val() = %v, want %v", tc.counter, got, want) } if got, want := tc.shouldOverflow, c.hasOverflowed; got != want { t.Errorf("counter starting with %v, c.hasOverflowed = %v, want %v", tc.counter, got, want) } }) } } func TestCounterReset(t *testing.T) { for _, tc := range []struct { desc string counter uint64 hasOverflowed bool }{ { desc: "non-zero no overflow", counter: 1, hasOverflowed: false, }, { desc: "zero no overflow", counter: 0, hasOverflowed: false, }, { desc: "non-zero has overflow", counter: 1, hasOverflowed: true, }, { desc: "zero has overflow", counter: 0, hasOverflowed: true, }, } { t.Run(tc.desc, func(t *testing.T) { c := counter{tc.counter, tc.hasOverflowed} c.reset() if got, want := c.val, uint64(0); got != want { t.Errorf("counter with value %v, c.value = %v, want %v", tc.counter, got, want) } if got, want := c.hasOverflowed, false; got != want { t.Errorf("counter with value %v, c.hasOverflowed = %v, want %v", tc.counter, got, want) } }) } } s2a-go-0.1.8/internal/record/internal/halfconn/expander.go000066400000000000000000000035141464711036600234560ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import ( "fmt" "hash" "golang.org/x/crypto/hkdf" ) // hkdfExpander is the interface for the HKDF expansion function; see // https://tools.ietf.org/html/rfc5869 for details. its use in TLS 1.3 is // specified in https://tools.ietf.org/html/rfc8446#section-7.2 type hkdfExpander interface { // expand takes a secret, a label, and the output length in bytes, and // returns the resulting expanded key. expand(secret, label []byte, length int) ([]byte, error) } // defaultHKDFExpander is the default HKDF expander which uses Go's crypto/hkdf // for HKDF expansion. type defaultHKDFExpander struct { h func() hash.Hash } // newDefaultHKDFExpander creates an instance of the default HKDF expander // using the given hash function. func newDefaultHKDFExpander(h func() hash.Hash) hkdfExpander { return &defaultHKDFExpander{h: h} } func (d *defaultHKDFExpander) expand(secret, label []byte, length int) ([]byte, error) { outBuf := make([]byte, length) n, err := hkdf.Expand(d.h, secret, label).Read(outBuf) if err != nil { return nil, fmt.Errorf("hkdf.Expand.Read failed with error: %v", err) } if n < length { return nil, fmt.Errorf("hkdf.Expand.Read returned unexpected length, got %d, want %d", n, length) } return outBuf, nil } s2a-go-0.1.8/internal/record/internal/halfconn/expander_test.go000066400000000000000000000050271464711036600245160ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import ( "bytes" "crypto/sha256" "testing" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) func TestExpand(t *testing.T) { // The following test vectors were taken from // https://tools.ietf.org/html/rfc5869. Note that `prk` and `okm` // mentioned in the RFC have been renamed to `secret` and `out`. for _, tc := range []struct { desc string secret, info, out []byte length int }{ { desc: "sha256 basic", secret: testutil.Dehex("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"), info: testutil.Dehex("f0f1f2f3f4f5f6f7f8f9"), out: testutil.Dehex("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"), length: 42, }, { desc: "sha256 longer input/output", secret: testutil.Dehex("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"), info: testutil.Dehex("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), out: testutil.Dehex("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"), length: 82, }, { desc: "sha256 zero length info", secret: testutil.Dehex("19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04"), out: testutil.Dehex("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"), length: 42, }, } { t.Run(tc.desc, func(t *testing.T) { expander := newDefaultHKDFExpander(sha256.New) got, err := expander.expand(tc.secret, tc.info, tc.length) if err != nil { t.Errorf("expand failed with error: %v", err) } if !bytes.Equal(got, tc.out) { t.Errorf("expand(sha256.New, %v, %v, %v) = %v, want %v.", tc.secret, tc.info, tc.length, got, tc.out) } }) } } s2a-go-0.1.8/internal/record/internal/halfconn/halfconn.go000066400000000000000000000147441464711036600234470ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn manages the inbound or outbound traffic of a TLS 1.3 // connection. package halfconn import ( "fmt" "sync" s2apb "github.com/google/s2a-go/internal/proto/common_go_proto" "github.com/google/s2a-go/internal/record/internal/aeadcrypter" "golang.org/x/crypto/cryptobyte" ) // The constants below were taken from Section 7.2 and 7.3 in // https://tools.ietf.org/html/rfc8446#section-7. They are used as the label // in HKDF-Expand-Label. const ( tls13Key = "tls13 key" tls13Nonce = "tls13 iv" tls13Update = "tls13 traffic upd" ) // S2AHalfConnection stores the state of the TLS 1.3 connection in the // inbound or outbound direction. type S2AHalfConnection struct { cs ciphersuite expander hkdfExpander // mutex guards sequence, aeadCrypter, trafficSecret, and nonce. mutex sync.Mutex aeadCrypter aeadcrypter.S2AAEADCrypter sequence counter trafficSecret []byte nonce []byte } // New creates a new instance of S2AHalfConnection given a ciphersuite and a // traffic secret. func New(ciphersuite s2apb.Ciphersuite, trafficSecret []byte, sequence uint64) (*S2AHalfConnection, error) { cs, err := newCiphersuite(ciphersuite) if err != nil { return nil, fmt.Errorf("failed to create new ciphersuite: %v", ciphersuite) } if cs.trafficSecretSize() != len(trafficSecret) { return nil, fmt.Errorf("supplied traffic secret must be %v bytes, given: %v bytes", cs.trafficSecretSize(), len(trafficSecret)) } hc := &S2AHalfConnection{cs: cs, expander: newDefaultHKDFExpander(cs.hashFunction()), sequence: newCounter(sequence), trafficSecret: trafficSecret} if err = hc.updateCrypterAndNonce(hc.trafficSecret); err != nil { return nil, fmt.Errorf("failed to create half connection using traffic secret: %v", err) } return hc, nil } // Encrypt encrypts the plaintext and computes the tag of dst and plaintext. // dst and plaintext may fully overlap or not at all. Note that the sequence // number will still be incremented on failure, unless the sequence has // overflowed. func (hc *S2AHalfConnection) Encrypt(dst, plaintext, aad []byte) ([]byte, error) { hc.mutex.Lock() sequence, err := hc.getAndIncrementSequence() if err != nil { hc.mutex.Unlock() return nil, err } nonce := hc.maskedNonce(sequence) crypter := hc.aeadCrypter hc.mutex.Unlock() return crypter.Encrypt(dst, plaintext, nonce, aad) } // Decrypt decrypts ciphertext and verifies the tag. dst and ciphertext may // fully overlap or not at all. Note that the sequence number will still be // incremented on failure, unless the sequence has overflowed. func (hc *S2AHalfConnection) Decrypt(dst, ciphertext, aad []byte) ([]byte, error) { hc.mutex.Lock() sequence, err := hc.getAndIncrementSequence() if err != nil { hc.mutex.Unlock() return nil, err } nonce := hc.maskedNonce(sequence) crypter := hc.aeadCrypter hc.mutex.Unlock() return crypter.Decrypt(dst, ciphertext, nonce, aad) } // UpdateKey advances the traffic secret key, as specified in // https://tools.ietf.org/html/rfc8446#section-7.2. In addition, it derives // a new key and nonce, and resets the sequence number. func (hc *S2AHalfConnection) UpdateKey() error { hc.mutex.Lock() defer hc.mutex.Unlock() var err error hc.trafficSecret, err = hc.deriveSecret(hc.trafficSecret, []byte(tls13Update), hc.cs.trafficSecretSize()) if err != nil { return fmt.Errorf("failed to derive traffic secret: %v", err) } if err = hc.updateCrypterAndNonce(hc.trafficSecret); err != nil { return fmt.Errorf("failed to update half connection: %v", err) } hc.sequence.reset() return nil } // TagSize returns the tag size in bytes of the underlying AEAD crypter. func (hc *S2AHalfConnection) TagSize() int { return hc.aeadCrypter.TagSize() } // updateCrypterAndNonce takes a new traffic secret and updates the crypter // and nonce. Note that the mutex must be held while calling this function. func (hc *S2AHalfConnection) updateCrypterAndNonce(newTrafficSecret []byte) error { key, err := hc.deriveSecret(newTrafficSecret, []byte(tls13Key), hc.cs.keySize()) if err != nil { return fmt.Errorf("failed to update key: %v", err) } hc.nonce, err = hc.deriveSecret(newTrafficSecret, []byte(tls13Nonce), hc.cs.nonceSize()) if err != nil { return fmt.Errorf("failed to update nonce: %v", err) } hc.aeadCrypter, err = hc.cs.aeadCrypter(key) if err != nil { return fmt.Errorf("failed to update AEAD crypter: %v", err) } return nil } // getAndIncrement returns the current sequence number and increments it. Note // that the mutex must be held while calling this function. func (hc *S2AHalfConnection) getAndIncrementSequence() (uint64, error) { sequence, err := hc.sequence.value() if err != nil { return 0, err } hc.sequence.increment() return sequence, nil } // maskedNonce creates a copy of the nonce that is masked with the sequence // number. Note that the mutex must be held while calling this function. func (hc *S2AHalfConnection) maskedNonce(sequence uint64) []byte { const uint64Size = 8 nonce := make([]byte, len(hc.nonce)) copy(nonce, hc.nonce) for i := 0; i < uint64Size; i++ { nonce[aeadcrypter.NonceSize-uint64Size+i] ^= byte(sequence >> uint64(56-uint64Size*i)) } return nonce } // deriveSecret implements the Derive-Secret function, as specified in // https://tools.ietf.org/html/rfc8446#section-7.1. func (hc *S2AHalfConnection) deriveSecret(secret, label []byte, length int) ([]byte, error) { var hkdfLabel cryptobyte.Builder hkdfLabel.AddUint16(uint16(length)) hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(label) }) // Append an empty `Context` field to the label, as specified in the RFC. // The half connection does not use the `Context` field. hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes([]byte("")) }) hkdfLabelBytes, err := hkdfLabel.Bytes() if err != nil { return nil, fmt.Errorf("deriveSecret failed: %v", err) } return hc.expander.expand(secret, hkdfLabelBytes, length) } s2a-go-0.1.8/internal/record/internal/halfconn/halfconn_test.go000066400000000000000000000360641464711036600245050ustar00rootroot00000000000000/* * * Copyright 2021 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 halfconn import ( "bytes" "math" "testing" s2apb "github.com/google/s2a-go/internal/proto/common_go_proto" "github.com/google/s2a-go/internal/record/internal/aeadcrypter" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) // getHalfConnPair returns a sender/receiver pair of S2A Half Connections. func getHalfConnPair(ciphersuite s2apb.Ciphersuite, trafficSecret []byte, t *testing.T) (*S2AHalfConnection, *S2AHalfConnection) { sender, err := New(ciphersuite, trafficSecret, 0 /* sequence */) if err != nil { t.Fatalf("sender side New(%v, %v) failed: %v", ciphersuite, trafficSecret, err) } receiver, err := New(ciphersuite, trafficSecret, 0 /* sequence */) if err != nil { t.Fatalf("receiver side New(%v, %v) failed: %v", ciphersuite, trafficSecret, err) } return sender, receiver } // aeadCrypterEqual checks whether the given S2AAEADCrypters encrypt a simple // string identically. func aeadCrypterEqual(a aeadcrypter.S2AAEADCrypter, b aeadcrypter.S2AAEADCrypter, t *testing.T) bool { nonce := make([]byte, aeadcrypter.NonceSize) const plaintext = "This is plaintext" ciphertextA, err := a.Encrypt(nil, []byte(plaintext), nonce, nil) if err != nil { t.Errorf("a.Encrypt(nil, %v, %v, nil) failed: %v", []byte(plaintext), nonce, err) } ciphertextB, err := b.Encrypt(nil, []byte(plaintext), nonce, nil) if err != nil { t.Errorf("b.Encrypt(nil, %v, %v, nil) failed: %v", []byte(plaintext), nonce, err) } return bytes.Equal(ciphertextA, ciphertextB) } func testHalfConnRoundtrip(sender *S2AHalfConnection, receiver *S2AHalfConnection, t *testing.T) { // Encrypt first message. const plaintext = "This is plaintext." buf := []byte(plaintext) _, err := sender.Encrypt(buf[:0], buf, nil) if err != nil { t.Fatalf("Encrypt(%v, %v, nil) failed: %v", buf[:0], buf, err) } // Encrypt second message. const plaintext2 = "This is a second plaintext." buf2 := []byte(plaintext2) ciphertext2, err := sender.Encrypt(buf2[:0], buf2, nil) if err != nil { t.Fatalf("Encrypt(%v, %v, nil) failed: %v", buf2[:0], buf2, err) } // Encrypt empty message. const plaintext3 = "" buf3 := []byte(plaintext3) ciphertext3, err := sender.Encrypt(buf3[:0], buf3, nil) if err != nil { t.Fatalf("Encrypt(%v, %v, nil) failed: %v", buf3[:0], buf3, err) } // Decryption fails: cannot decrypt second message before first. if _, err := receiver.Decrypt(nil, ciphertext2, nil); err == nil { t.Errorf("Decrypt(nil, %v, nil) expected an error, received none", ciphertext2) } // Decrypt second message. This works now because the sequence number was // incremented by the previous call to decrypt. decryptedPlaintext2, err := receiver.Decrypt(ciphertext2[:0], ciphertext2, nil) if err != nil { t.Fatalf("Decrypt(%v, %v, nil) failed: %v", ciphertext2[:0], ciphertext2, err) } if got, want := string(decryptedPlaintext2), plaintext2; got != want { t.Fatalf("Decrypt(%v, %v, nil) = %v, want %v", ciphertext2[:0], ciphertext2, got, want) } // Decrypt third (empty) message. decryptedPlaintext3, err := receiver.Decrypt(ciphertext3[:0], ciphertext3, nil) if err != nil { t.Fatalf("Decrypt(%v, %v, nil) failed: %v", ciphertext3[:0], ciphertext3, err) } if got, want := string(decryptedPlaintext3), plaintext3; got != want { t.Fatalf("Decrypt(%v, %v, nil) = %v, want %v", ciphertext3[:0], ciphertext3, got, want) } // Decryption fails: same message decrypted again. if _, err := receiver.Decrypt(nil, ciphertext3, nil); err == nil { t.Errorf("Decrypt(nil, %v, nil) expected an error, received none", ciphertext3) } } func TestGetAndIncrementSequence(t *testing.T) { for _, tc := range []struct { desc string counter, expectedCounter uint64 shouldOverflow bool }{ { desc: "basic 1", counter: 0, expectedCounter: 1, }, { desc: "basic 2", counter: 123, expectedCounter: 124, }, { desc: "almost overflow", counter: math.MaxUint64 - 1, expectedCounter: math.MaxUint64, }, { desc: "max overflow", counter: math.MaxUint64, shouldOverflow: true, }, } { t.Run(tc.desc, func(t *testing.T) { hc := S2AHalfConnection{sequence: counter{val: tc.counter}} // Make first getAndIncrement call. This should return the same value // that was given. value, err := hc.getAndIncrementSequence() if err != nil { t.Errorf("S2A counter starting with %v, hc.getAndIncrementSequence() failed: %v", tc.counter, err) } if value != tc.counter { t.Errorf("S2A counter starting with %v, hc.getAndIncrementSequence() = %v, want %v", tc.counter, value, tc.counter) } // Make second getAndIncrement call. This should verify that the first // getAndIncrement call succeeded in incrementing the value. value, err = hc.getAndIncrementSequence() if got, want := err == nil, !tc.shouldOverflow; got != want { t.Errorf("S2A counter starting with %v, val()=(err=nil)=%v, want %v", tc.counter, got, want) } if got, want := value, tc.expectedCounter; err == nil && got != want { t.Errorf("S2A counter starting with %v, val() = %v, want %v", tc.counter, got, want) } }) } } func TestMaskedNonce(t *testing.T) { for _, tc := range []struct { desc string nonce []byte sequence uint64 maskedNonce []byte }{ { desc: "zero nonce and zero sequence", nonce: testutil.Dehex("000000000000000000000000"), sequence: 0, maskedNonce: testutil.Dehex("000000000000000000000000"), }, { desc: "max nonce and zero sequence", nonce: testutil.Dehex("ffffffffffffffffffffffff"), sequence: 0, maskedNonce: testutil.Dehex("ffffffffffffffffffffffff"), }, { desc: "zero nonce and max sequence", nonce: testutil.Dehex("000000000000000000000000"), sequence: math.MaxUint64, maskedNonce: testutil.Dehex("00000000ffffffffffffffff"), }, { desc: "max nonce and max sequence", nonce: testutil.Dehex("ffffffffffffffffffffffff"), sequence: math.MaxUint64, maskedNonce: testutil.Dehex("ffffffff0000000000000000"), }, { desc: "non-zero nonce and non-zero sequence", nonce: testutil.Dehex("010101010101010101010101"), sequence: 1, maskedNonce: testutil.Dehex("010101010101010101010100"), }, { desc: "cancel out", nonce: testutil.Dehex("00000000ffffffffffffffff"), sequence: math.MaxUint64, maskedNonce: testutil.Dehex("000000000000000000000000"), }, } { t.Run(tc.desc, func(t *testing.T) { hc := S2AHalfConnection{nonce: tc.nonce} if got, want := hc.maskedNonce(tc.sequence), tc.maskedNonce; !bytes.Equal(got, want) { t.Errorf("hc.maskedNonce(%v) = %v, want %v", tc.sequence, got, want) } }) } } func TestNew(t *testing.T) { for _, tc := range []struct { desc string ciphersuite s2apb.Ciphersuite trafficSecret, key, nonce []byte shouldFail bool }{ // The traffic secrets were chosen randomly and are equivalent to the // ones used in C++ and Java. The key and nonce were constructed using // an existing TLS library. { desc: "AES-128-GCM-SHA256 invalid traffic secret", ciphersuite: s2apb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("00"), shouldFail: true, }, { desc: "AES-128-GCM-SHA256 valid", ciphersuite: s2apb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), key: testutil.Dehex("c3ae7509cfced2b803a6186956cda79f"), nonce: testutil.Dehex("b5803d82ad8854d2e598187f"), }, { desc: "AES-256-GCM-SHA384 invalid traffic secret", ciphersuite: s2apb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("00"), shouldFail: true, }, { desc: "AES-256-GCM-SHA384 valid", ciphersuite: s2apb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), key: testutil.Dehex("dac731ae4866677ed2f65c490e18817be5cbbbd03f597ad59041c117b731109a"), nonce: testutil.Dehex("4db152d27d180b1ee48fa89d"), }, { desc: "CHACHA20-POLY1305-SHA256 invalid traffic secret", ciphersuite: s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("00"), shouldFail: true, }, { desc: "CHACHA20-POLY1305-SHA256 valid", ciphersuite: s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), key: testutil.Dehex("130e2000508ace00ef265e172d09892e467256cb90dad9de99543cf548be6a8b"), nonce: testutil.Dehex("b5803d82ad8854d2e598187f"), }, } { t.Run(tc.desc, func(t *testing.T) { hc, err := New(tc.ciphersuite, tc.trafficSecret, 0 /* sequence */) if got, want := err == nil, !tc.shouldFail; got != want { t.Errorf("New(%v, %v)=(err=nil)=%v, want %v", tc.ciphersuite, tc.trafficSecret, got, want) } if err != nil { return } // Check that the traffic secret wasn't changed. if got, want := hc.trafficSecret, tc.trafficSecret; !bytes.Equal(got, want) { t.Errorf("New(%v, %v).trafficSecret=%v, want %v", tc.ciphersuite, tc.trafficSecret, got, want) } if got, want := hc.nonce, tc.nonce; !bytes.Equal(got, want) { t.Errorf("New(%v, %v).nonce=%v, want %v", tc.ciphersuite, tc.trafficSecret, got, want) } cs, err := newCiphersuite(tc.ciphersuite) if err != nil { t.Errorf("newCipherSuite(%v) failed: %v", tc.ciphersuite, err) } aeadCrypter, err := cs.aeadCrypter(tc.key) if err != nil { t.Errorf("cs.aeadCrypter(%v) failed: %v", tc.key, err) } if got, want := hc.aeadCrypter, aeadCrypter; !aeadCrypterEqual(got, want, t) { t.Errorf("aeadCrypterEqual returned false, expected true") } }) } } func TestS2AHalfConnectionRoundtrip(t *testing.T) { for _, tc := range []struct { ciphersuite s2apb.Ciphersuite trafficSecret []byte }{ { ciphersuite: s2apb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), }, { ciphersuite: s2apb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), }, { ciphersuite: s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), }, } { t.Run(tc.ciphersuite.String(), func(t *testing.T) { sender, receiver := getHalfConnPair(tc.ciphersuite, tc.trafficSecret, t) testHalfConnRoundtrip(sender, receiver, t) }) } } func TestS2AHalfConnectionUpdateKey(t *testing.T) { for _, tc := range []struct { ciphersuite s2apb.Ciphersuite trafficSecret, advancedTrafficSecret, key, nonce []byte }{ // The traffic secrets were chosen randomly and are equivalent to the // ones used in C++ and Java. The advanced traffic secret, key, and // nonce were constructed using an existing TLS library. { ciphersuite: s2apb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), advancedTrafficSecret: testutil.Dehex("f38b9455ea5871235a69fc37610c6ca1215779e66b45a047d7390111e00081c4"), key: testutil.Dehex("07dfdfca2fc3f015b6e51e579679b503"), nonce: testutil.Dehex("79fdebc61b5fb9d9a34d9406"), }, { ciphersuite: s2apb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), advancedTrafficSecret: testutil.Dehex("016c835db664beb5526a9bb3d9a4fba63e67255dcfa460a114d9f1ef9a9a1f685a518739f557d0e66fdb89bdafa26257"), key: testutil.Dehex("4ee0f141c9a497a1db6f1ee0995248e804406fe39f35bcdff9f386048108bef1"), nonce: testutil.Dehex("90f241fbc9f9f55100168d8b"), }, { ciphersuite: s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), advancedTrafficSecret: testutil.Dehex("f38b9455ea5871235a69fc37610c6ca1215779e66b45a047d7390111e00081c4"), key: testutil.Dehex("18b61f93ee2d927d2f478f2220409738affb0092602d0812c96b965323e30878"), nonce: testutil.Dehex("79fdebc61b5fb9d9a34d9406"), }, } { t.Run(tc.ciphersuite.String(), func(t *testing.T) { hc, err := New(tc.ciphersuite, tc.trafficSecret, 0 /* sequence */) if err != nil { t.Fatalf("New(%v, %v) failed: %v", tc.ciphersuite, tc.trafficSecret, err) } if err := hc.UpdateKey(); err != nil { t.Fatalf("hc.updateKey() failed: %v", err) } if got, want := hc.trafficSecret, tc.advancedTrafficSecret; !bytes.Equal(got, want) { t.Errorf("hc.trafficSecret = %v, want %v", got, want) } if got, want := hc.nonce, tc.nonce; !bytes.Equal(got, want) { t.Errorf("hc.nonce = %v, want %v", got, want) } cs, err := newCiphersuite(tc.ciphersuite) if err != nil { t.Errorf("newCipherSuite(%v) failed: %v", tc.ciphersuite, err) } aeadCrypter, err := cs.aeadCrypter(tc.key) if err != nil { t.Errorf("cs.aeadCrypter(%v) failed: %v", tc.key, err) } if got, want := hc.aeadCrypter, aeadCrypter; !aeadCrypterEqual(got, want, t) { t.Errorf("aeadCrypterEqual returned false, expected true") } }) } } func TestS2AHalfConnectionTagSize(t *testing.T) { for _, ciphersuite := range []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256, } { t.Run(ciphersuite.String(), func(t *testing.T) { cs, err := newCiphersuite(ciphersuite) if err != nil { t.Fatalf("newCiphersuite(%v) failed: %v", ciphersuite, err) } trafficSecret := make([]byte, cs.trafficSecretSize()) key := make([]byte, cs.keySize()) hc, err := New(ciphersuite, trafficSecret, 0 /* sequence */) if err != nil { t.Fatalf("New(%v, %v) failed: %v", ciphersuite, trafficSecret, err) } crypter, err := aeadcrypter.NewAESGCM(key) if err != nil { t.Fatalf("NewAESGCM(%v) failed: %v", key, err) } if got, want := hc.TagSize(), crypter.TagSize(); got != want { t.Errorf("hc.TagSize() = %v, want %v", got, want) } }) } } s2a-go-0.1.8/internal/record/record.go000066400000000000000000000706661464711036600175360ustar00rootroot00000000000000/* * * Copyright 2021 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 record implements the TLS 1.3 record protocol used by the S2A // transport credentials. package record import ( "encoding/binary" "errors" "fmt" "math" "net" "sync" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" "github.com/google/s2a-go/internal/record/internal/halfconn" "github.com/google/s2a-go/internal/tokenmanager" "google.golang.org/grpc/grpclog" ) // recordType is the `ContentType` as described in // https://tools.ietf.org/html/rfc8446#section-5.1. type recordType byte const ( alert recordType = 21 handshake recordType = 22 applicationData recordType = 23 ) // keyUpdateRequest is the `KeyUpdateRequest` as described in // https://tools.ietf.org/html/rfc8446#section-4.6.3. type keyUpdateRequest byte const ( updateNotRequested keyUpdateRequest = 0 updateRequested keyUpdateRequest = 1 ) // alertDescription is the `AlertDescription` as described in // https://tools.ietf.org/html/rfc8446#section-6. type alertDescription byte const ( closeNotify alertDescription = 0 ) // sessionTicketState is used to determine whether session tickets have not yet // been received, are in the process of being received, or have finished // receiving. type sessionTicketState byte const ( ticketsNotYetReceived sessionTicketState = 0 receivingTickets sessionTicketState = 1 notReceivingTickets sessionTicketState = 2 ) const ( // The TLS 1.3-specific constants below (tlsRecordMaxPlaintextSize, // tlsRecordHeaderSize, tlsRecordTypeSize) were taken from // https://tools.ietf.org/html/rfc8446#section-5.1. // tlsRecordMaxPlaintextSize is the maximum size in bytes of the plaintext // in a single TLS 1.3 record. tlsRecordMaxPlaintextSize = 16384 // 2^14 // tlsRecordTypeSize is the size in bytes of the TLS 1.3 record type. tlsRecordTypeSize = 1 // tlsTagSize is the size in bytes of the tag of the following three // ciphersuites: AES-128-GCM-SHA256, AES-256-GCM-SHA384, // CHACHA20-POLY1305-SHA256. tlsTagSize = 16 // tlsRecordMaxPayloadSize is the maximum size in bytes of the payload in a // single TLS 1.3 record. This is the maximum size of the plaintext plus the // record type byte and 16 bytes of the tag. tlsRecordMaxPayloadSize = tlsRecordMaxPlaintextSize + tlsRecordTypeSize + tlsTagSize // tlsRecordHeaderTypeSize is the size in bytes of the TLS 1.3 record // header type. tlsRecordHeaderTypeSize = 1 // tlsRecordHeaderLegacyRecordVersionSize is the size in bytes of the TLS // 1.3 record header legacy record version. tlsRecordHeaderLegacyRecordVersionSize = 2 // tlsRecordHeaderPayloadLengthSize is the size in bytes of the TLS 1.3 // record header payload length. tlsRecordHeaderPayloadLengthSize = 2 // tlsRecordHeaderSize is the size in bytes of the TLS 1.3 record header. tlsRecordHeaderSize = tlsRecordHeaderTypeSize + tlsRecordHeaderLegacyRecordVersionSize + tlsRecordHeaderPayloadLengthSize // tlsRecordMaxSize tlsRecordMaxSize = tlsRecordMaxPayloadSize + tlsRecordHeaderSize // tlsApplicationData is the application data type of the TLS 1.3 record // header. tlsApplicationData = 23 // tlsLegacyRecordVersion is the legacy record version of the TLS record. tlsLegacyRecordVersion = 3 // tlsAlertSize is the size in bytes of an alert of TLS 1.3. tlsAlertSize = 2 ) const ( // These are TLS 1.3 handshake-specific constants. // tlsHandshakeNewSessionTicketType is the prefix of a handshake new session // ticket message of TLS 1.3. tlsHandshakeNewSessionTicketType = 4 // tlsHandshakeKeyUpdateType is the prefix of a handshake key update message // of TLS 1.3. tlsHandshakeKeyUpdateType = 24 // tlsHandshakeMsgTypeSize is the size in bytes of the TLS 1.3 handshake // message type field. tlsHandshakeMsgTypeSize = 1 // tlsHandshakeLengthSize is the size in bytes of the TLS 1.3 handshake // message length field. tlsHandshakeLengthSize = 3 // tlsHandshakeKeyUpdateMsgSize is the size in bytes of the TLS 1.3 // handshake key update message. tlsHandshakeKeyUpdateMsgSize = 1 // tlsHandshakePrefixSize is the size in bytes of the prefix of the TLS 1.3 // handshake message. tlsHandshakePrefixSize = 4 // tlsMaxSessionTicketSize is the maximum size of a NewSessionTicket message // in TLS 1.3. This is the sum of the max sizes of all the fields in the // NewSessionTicket struct specified in // https://tools.ietf.org/html/rfc8446#section-4.6.1. tlsMaxSessionTicketSize = 131338 ) const ( // outBufMaxRecords is the maximum number of records that can fit in the // ourRecordsBuf buffer. outBufMaxRecords = 16 // outBufMaxSize is the maximum size (in bytes) of the outRecordsBuf buffer. outBufMaxSize = outBufMaxRecords * tlsRecordMaxSize // maxAllowedTickets is the maximum number of session tickets that are // allowed. The number of tickets are limited to ensure that the size of the // ticket queue does not grow indefinitely. S2A also keeps a limit on the // number of tickets that it caches. maxAllowedTickets = 5 ) // preConstructedKeyUpdateMsg holds the key update message. This is needed as an // optimization so that the same message does not need to be constructed every // time a key update message is sent. var preConstructedKeyUpdateMsg = buildKeyUpdateRequest() // conn represents a secured TLS connection. It implements the net.Conn // interface. type conn struct { net.Conn // inConn is the half connection responsible for decrypting incoming bytes. inConn *halfconn.S2AHalfConnection // outConn is the half connection responsible for encrypting outgoing bytes. outConn *halfconn.S2AHalfConnection // pendingApplicationData holds data that has been read from the connection // and decrypted, but has not yet been returned by Read. pendingApplicationData []byte // unusedBuf holds data read from the network that has not yet been // decrypted. This data might not consist of a complete record. It may // consist of several records, the last of which could be incomplete. unusedBuf []byte // outRecordsBuf is a buffer used to store outgoing TLS records before // they are written to the network. outRecordsBuf []byte // nextRecord stores the next record info in the unusedBuf buffer. nextRecord []byte // overheadSize is the overhead size in bytes of each TLS 1.3 record, which // is computed as overheadSize = header size + record type byte + tag size. // Note that there is no padding by zeros in the overhead calculation. overheadSize int // readMutex guards against concurrent calls to Read. This is required since // Close may be called during a Read. readMutex sync.Mutex // writeMutex guards against concurrent calls to Write. This is required // since Close may be called during a Write, and also because a key update // message may be written during a Read. writeMutex sync.Mutex // handshakeBuf holds handshake messages while they are being processed. handshakeBuf []byte // ticketState is the current processing state of the session tickets. ticketState sessionTicketState // sessionTickets holds the completed session tickets until they are sent to // the handshaker service for processing. sessionTickets [][]byte // ticketSender sends session tickets to the S2A handshaker service. ticketSender s2aTicketSender // callComplete is a channel that blocks closing the record protocol until a // pending call to the S2A completes. callComplete chan bool } // ConnParameters holds the parameters used for creating a new conn object. type ConnParameters struct { // NetConn is the TCP connection to the peer. This parameter is required. NetConn net.Conn // Ciphersuite is the TLS ciphersuite negotiated by the S2A handshaker // service. This parameter is required. Ciphersuite commonpb.Ciphersuite // TLSVersion is the TLS version number negotiated by the S2A handshaker // service. This parameter is required. TLSVersion commonpb.TLSVersion // InTrafficSecret is the traffic secret used to derive the session key for // the inbound direction. This parameter is required. InTrafficSecret []byte // OutTrafficSecret is the traffic secret used to derive the session key // for the outbound direction. This parameter is required. OutTrafficSecret []byte // UnusedBuf is the data read from the network that has not yet been // decrypted. This parameter is optional. If not provided, then no // application data was sent in the same flight of messages as the final // handshake message. UnusedBuf []byte // InSequence is the sequence number of the next, incoming, TLS record. // This parameter is required. InSequence uint64 // OutSequence is the sequence number of the next, outgoing, TLS record. // This parameter is required. OutSequence uint64 // HSAddr stores the address of the S2A handshaker service. This parameter // is optional. If not provided, then TLS resumption is disabled. HSAddr string // ConnectionId is the connection identifier that was created and sent by // S2A at the end of a handshake. ConnectionID uint64 // LocalIdentity is the local identity that was used by S2A during session // setup and included in the session result. LocalIdentity *commonpb.Identity // EnsureProcessSessionTickets allows users to wait and ensure that all // available session tickets are sent to S2A before a process completes. EnsureProcessSessionTickets *sync.WaitGroup } // NewConn creates a TLS record protocol that wraps the TCP connection. func NewConn(o *ConnParameters) (net.Conn, error) { if o == nil { return nil, errors.New("conn options must not be nil") } if o.TLSVersion != commonpb.TLSVersion_TLS1_3 { return nil, errors.New("TLS version must be TLS 1.3") } inConn, err := halfconn.New(o.Ciphersuite, o.InTrafficSecret, o.InSequence) if err != nil { return nil, fmt.Errorf("failed to create inbound half connection: %v", err) } outConn, err := halfconn.New(o.Ciphersuite, o.OutTrafficSecret, o.OutSequence) if err != nil { return nil, fmt.Errorf("failed to create outbound half connection: %v", err) } // The tag size for the in/out connections should be the same. overheadSize := tlsRecordHeaderSize + tlsRecordTypeSize + inConn.TagSize() var unusedBuf []byte if o.UnusedBuf == nil { // We pre-allocate unusedBuf to be of size // 2*tlsRecordMaxSize-1 during initialization. We only read from the // network into unusedBuf when unusedBuf does not contain a complete // record and the incomplete record is at most tlsRecordMaxSize-1 // (bytes). And we read at most tlsRecordMaxSize bytes of data from the // network into unusedBuf at one time. Therefore, 2*tlsRecordMaxSize-1 // is large enough to buffer data read from the network. unusedBuf = make([]byte, 0, 2*tlsRecordMaxSize-1) } else { unusedBuf = make([]byte, len(o.UnusedBuf)) copy(unusedBuf, o.UnusedBuf) } tokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() if err != nil { grpclog.Infof("failed to create single token access token manager: %v", err) } s2aConn := &conn{ Conn: o.NetConn, inConn: inConn, outConn: outConn, unusedBuf: unusedBuf, outRecordsBuf: make([]byte, tlsRecordMaxSize), nextRecord: unusedBuf, overheadSize: overheadSize, ticketState: ticketsNotYetReceived, // Pre-allocate the buffer for one session ticket message and the max // plaintext size. This is the largest size that handshakeBuf will need // to hold. The largest incomplete handshake message is the // [handshake header size] + [max session ticket size] - 1. // Then, tlsRecordMaxPlaintextSize is the maximum size that will be // appended to the handshakeBuf before the handshake message is // completed. Therefore, the buffer size below should be large enough to // buffer any handshake messages. handshakeBuf: make([]byte, 0, tlsHandshakePrefixSize+tlsMaxSessionTicketSize+tlsRecordMaxPlaintextSize-1), ticketSender: &ticketSender{ hsAddr: o.HSAddr, connectionID: o.ConnectionID, localIdentity: o.LocalIdentity, tokenManager: tokenManager, ensureProcessSessionTickets: o.EnsureProcessSessionTickets, }, callComplete: make(chan bool), } return s2aConn, nil } // Read reads and decrypts a TLS 1.3 record from the underlying connection, and // copies any application data received from the peer into b. If the size of the // payload is greater than len(b), Read retains the remaining bytes in an // internal buffer, and subsequent calls to Read will read from this buffer // until it is exhausted. At most 1 TLS record worth of application data is // written to b for each call to Read. // // Note that for the user to efficiently call this method, the user should // ensure that the buffer b is allocated such that the buffer does not have any // unused segments. This can be done by calling Read via io.ReadFull, which // continually calls Read until the specified buffer has been filled. Also note // that the user should close the connection via Close() if an error is thrown // by a call to Read. func (p *conn) Read(b []byte) (n int, err error) { p.readMutex.Lock() defer p.readMutex.Unlock() // Check if p.pendingApplication data has leftover application data from // the previous call to Read. if len(p.pendingApplicationData) == 0 { // Read a full record from the wire. record, err := p.readFullRecord() if err != nil { return 0, err } // Now we have a complete record, so split the header and validate it // The TLS record is split into 2 pieces: the record header and the // payload. The payload has the following form: // [payload] = [ciphertext of application data] // + [ciphertext of record type byte] // + [(optionally) ciphertext of padding by zeros] // + [tag] header, payload, err := splitAndValidateHeader(record) if err != nil { return 0, err } // Decrypt the ciphertext. p.pendingApplicationData, err = p.inConn.Decrypt(payload[:0], payload, header) if err != nil { return 0, err } // Remove the padding by zeros and the record type byte from the // p.pendingApplicationData buffer. msgType, err := p.stripPaddingAndType() if err != nil { return 0, err } // Check that the length of the plaintext after stripping the padding // and record type byte is under the maximum plaintext size. if len(p.pendingApplicationData) > tlsRecordMaxPlaintextSize { return 0, errors.New("plaintext size larger than maximum") } // The expected message types are application data, alert, and // handshake. For application data, the bytes are directly copied into // b. For an alert, the type of the alert is checked and the connection // is closed on a close notify alert. For a handshake message, the // handshake message type is checked. The handshake message type can be // a key update type, for which we advance the traffic secret, and a // new session ticket type, for which we send the received ticket to S2A // for processing. switch msgType { case applicationData: if len(p.handshakeBuf) > 0 { return 0, errors.New("application data received while processing fragmented handshake messages") } case alert: return 0, p.handleAlertMessage() case handshake: if err = p.handleHandshakeMessage(); err != nil { return 0, err } return 0, nil default: return 0, errors.New("unknown record type") } } // Write as much application data as possible to b, the output buffer. n = copy(b, p.pendingApplicationData) p.pendingApplicationData = p.pendingApplicationData[n:] return n, nil } // Write divides b into segments of size tlsRecordMaxPlaintextSize, builds a // TLS 1.3 record (of type "application data") from each segment, and sends // the record to the peer. It returns the number of plaintext bytes that were // successfully sent to the peer. func (p *conn) Write(b []byte) (n int, err error) { p.writeMutex.Lock() defer p.writeMutex.Unlock() return p.writeTLSRecord(b, tlsApplicationData) } // writeTLSRecord divides b into segments of size maxPlaintextBytesPerRecord, // builds a TLS 1.3 record (of type recordType) from each segment, and sends // the record to the peer. It returns the number of plaintext bytes that were // successfully sent to the peer. func (p *conn) writeTLSRecord(b []byte, recordType byte) (n int, err error) { // Create a record of only header, record type, and tag if given empty // byte array. if len(b) == 0 { recordEndIndex, _, err := p.buildRecord(b, recordType, 0) if err != nil { return 0, err } // Write the bytes stored in outRecordsBuf to p.Conn. Since we return // the number of plaintext bytes written without overhead, we will // always return 0 while p.Conn.Write returns the entire record length. _, err = p.Conn.Write(p.outRecordsBuf[:recordEndIndex]) return 0, err } numRecords := int(math.Ceil(float64(len(b)) / float64(tlsRecordMaxPlaintextSize))) totalRecordsSize := len(b) + numRecords*p.overheadSize partialBSize := len(b) if totalRecordsSize > outBufMaxSize { totalRecordsSize = outBufMaxSize partialBSize = outBufMaxRecords * tlsRecordMaxPlaintextSize } if len(p.outRecordsBuf) < totalRecordsSize { p.outRecordsBuf = make([]byte, totalRecordsSize) } for bStart := 0; bStart < len(b); bStart += partialBSize { bEnd := bStart + partialBSize if bEnd > len(b) { bEnd = len(b) } partialB := b[bStart:bEnd] recordEndIndex := 0 for len(partialB) > 0 { recordEndIndex, partialB, err = p.buildRecord(partialB, recordType, recordEndIndex) if err != nil { // Return the amount of bytes written prior to the error. return bStart, err } } // Write the bytes stored in outRecordsBuf to p.Conn. If there is an // error, calculate the total number of plaintext bytes of complete // records successfully written to the peer and return it. nn, err := p.Conn.Write(p.outRecordsBuf[:recordEndIndex]) if err != nil { numberOfCompletedRecords := int(math.Floor(float64(nn) / float64(tlsRecordMaxSize))) return bStart + numberOfCompletedRecords*tlsRecordMaxPlaintextSize, err } } return len(b), nil } // buildRecord builds a TLS 1.3 record of type recordType from plaintext, // and writes the record to outRecordsBuf at recordStartIndex. The record will // have at most tlsRecordMaxPlaintextSize bytes of payload. It returns the // index of outRecordsBuf where the current record ends, as well as any // remaining plaintext bytes. func (p *conn) buildRecord(plaintext []byte, recordType byte, recordStartIndex int) (n int, remainingPlaintext []byte, err error) { // Construct the payload, which consists of application data and record type. dataLen := len(plaintext) if dataLen > tlsRecordMaxPlaintextSize { dataLen = tlsRecordMaxPlaintextSize } remainingPlaintext = plaintext[dataLen:] newRecordBuf := p.outRecordsBuf[recordStartIndex:] copy(newRecordBuf[tlsRecordHeaderSize:], plaintext[:dataLen]) newRecordBuf[tlsRecordHeaderSize+dataLen] = recordType payload := newRecordBuf[tlsRecordHeaderSize : tlsRecordHeaderSize+dataLen+1] // 1 is for the recordType. // Construct the header. newRecordBuf[0] = tlsApplicationData newRecordBuf[1] = tlsLegacyRecordVersion newRecordBuf[2] = tlsLegacyRecordVersion binary.BigEndian.PutUint16(newRecordBuf[3:], uint16(len(payload)+tlsTagSize)) header := newRecordBuf[:tlsRecordHeaderSize] // Encrypt the payload using header as aad. encryptedPayload, err := p.outConn.Encrypt(newRecordBuf[tlsRecordHeaderSize:][:0], payload, header) if err != nil { return 0, plaintext, err } recordStartIndex += len(header) + len(encryptedPayload) return recordStartIndex, remainingPlaintext, nil } func (p *conn) Close() error { // Close the connection immediately. return p.Conn.Close() } // stripPaddingAndType strips the padding by zeros and record type from // p.pendingApplicationData and returns the record type. Note that // p.pendingApplicationData should be of the form: // [application data] + [record type byte] + [trailing zeros] func (p *conn) stripPaddingAndType() (recordType, error) { if len(p.pendingApplicationData) == 0 { return 0, errors.New("application data had length 0") } i := len(p.pendingApplicationData) - 1 // Search for the index of the record type byte. for i > 0 { if p.pendingApplicationData[i] != 0 { break } i-- } rt := recordType(p.pendingApplicationData[i]) p.pendingApplicationData = p.pendingApplicationData[:i] return rt, nil } // readFullRecord reads from the wire until a record is completed and returns // the full record. func (p *conn) readFullRecord() (fullRecord []byte, err error) { fullRecord, p.nextRecord, err = parseReadBuffer(p.nextRecord, tlsRecordMaxPayloadSize) if err != nil { return nil, err } // Check whether the next record to be decrypted has been completely // received. if len(fullRecord) == 0 { copy(p.unusedBuf, p.nextRecord) p.unusedBuf = p.unusedBuf[:len(p.nextRecord)] // Always copy next incomplete record to the beginning of the // unusedBuf buffer and reset nextRecord to it. p.nextRecord = p.unusedBuf } // Keep reading from the wire until we have a complete record. for len(fullRecord) == 0 { if len(p.unusedBuf) == cap(p.unusedBuf) { tmp := make([]byte, len(p.unusedBuf), cap(p.unusedBuf)+tlsRecordMaxSize) copy(tmp, p.unusedBuf) p.unusedBuf = tmp } n, err := p.Conn.Read(p.unusedBuf[len(p.unusedBuf):min(cap(p.unusedBuf), len(p.unusedBuf)+tlsRecordMaxSize)]) if err != nil { return nil, err } p.unusedBuf = p.unusedBuf[:len(p.unusedBuf)+n] fullRecord, p.nextRecord, err = parseReadBuffer(p.unusedBuf, tlsRecordMaxPayloadSize) if err != nil { return nil, err } } return fullRecord, nil } // parseReadBuffer parses the provided buffer and returns a full record and any // remaining bytes in that buffer. If the record is incomplete, nil is returned // for the first return value and the given byte buffer is returned for the // second return value. The length of the payload specified by the header should // not be greater than maxLen, otherwise an error is returned. Note that this // function does not allocate or copy any buffers. func parseReadBuffer(b []byte, maxLen uint16) (fullRecord, remaining []byte, err error) { // If the header is not complete, return the provided buffer as remaining // buffer. if len(b) < tlsRecordHeaderSize { return nil, b, nil } msgLenField := b[tlsRecordHeaderTypeSize+tlsRecordHeaderLegacyRecordVersionSize : tlsRecordHeaderSize] length := binary.BigEndian.Uint16(msgLenField) if length > maxLen { return nil, nil, fmt.Errorf("record length larger than the limit %d", maxLen) } if len(b) < int(length)+tlsRecordHeaderSize { // Record is not complete yet. return nil, b, nil } return b[:tlsRecordHeaderSize+length], b[tlsRecordHeaderSize+length:], nil } // splitAndValidateHeader splits the header from the payload in the TLS 1.3 // record and returns them. Note that the header is checked for validity, and an // error is returned when an invalid header is parsed. Also note that this // function does not allocate or copy any buffers. func splitAndValidateHeader(record []byte) (header, payload []byte, err error) { if len(record) < tlsRecordHeaderSize { return nil, nil, fmt.Errorf("record was smaller than the header size") } header = record[:tlsRecordHeaderSize] payload = record[tlsRecordHeaderSize:] if header[0] != tlsApplicationData { return nil, nil, fmt.Errorf("incorrect type in the header") } // Check the legacy record version, which should be 0x03, 0x03. if header[1] != 0x03 || header[2] != 0x03 { return nil, nil, fmt.Errorf("incorrect legacy record version in the header") } return header, payload, nil } // handleAlertMessage handles an alert message. func (p *conn) handleAlertMessage() error { if len(p.pendingApplicationData) != tlsAlertSize { return errors.New("invalid alert message size") } alertType := p.pendingApplicationData[1] // Clear the body of the alert message. p.pendingApplicationData = p.pendingApplicationData[:0] if alertType == byte(closeNotify) { return errors.New("received a close notify alert") } // TODO(matthewstevenson88): Add support for more alert types. return fmt.Errorf("received an unrecognized alert type: %v", alertType) } // parseHandshakeHeader parses a handshake message from the handshake buffer. // It returns the message type, the message length, the message, the raw message // that includes the type and length bytes and a flag indicating whether the // handshake message has been fully parsed. i.e. whether the entire handshake // message was in the handshake buffer. func (p *conn) parseHandshakeMsg() (msgType byte, msgLen uint32, msg []byte, rawMsg []byte, ok bool) { // Handle the case where the 4 byte handshake header is fragmented. if len(p.handshakeBuf) < tlsHandshakePrefixSize { return 0, 0, nil, nil, false } msgType = p.handshakeBuf[0] msgLen = bigEndianInt24(p.handshakeBuf[tlsHandshakeMsgTypeSize : tlsHandshakeMsgTypeSize+tlsHandshakeLengthSize]) if msgLen > uint32(len(p.handshakeBuf)-tlsHandshakePrefixSize) { return 0, 0, nil, nil, false } msg = p.handshakeBuf[tlsHandshakePrefixSize : tlsHandshakePrefixSize+msgLen] rawMsg = p.handshakeBuf[:tlsHandshakeMsgTypeSize+tlsHandshakeLengthSize+msgLen] p.handshakeBuf = p.handshakeBuf[tlsHandshakePrefixSize+msgLen:] return msgType, msgLen, msg, rawMsg, true } // handleHandshakeMessage handles a handshake message. Note that the first // complete handshake message from the handshake buffer is removed, if it // exists. func (p *conn) handleHandshakeMessage() error { // Copy the pending application data to the handshake buffer. At this point, // we are guaranteed that the pending application data contains only parts // of a handshake message. p.handshakeBuf = append(p.handshakeBuf, p.pendingApplicationData...) p.pendingApplicationData = p.pendingApplicationData[:0] // Several handshake messages may be coalesced into a single record. // Continue reading them until the handshake buffer is empty. for len(p.handshakeBuf) > 0 { handshakeMsgType, msgLen, msg, _, ok := p.parseHandshakeMsg() if !ok { // The handshake could not be fully parsed, so read in another // record and try again later. break } switch handshakeMsgType { case tlsHandshakeKeyUpdateType: if msgLen != tlsHandshakeKeyUpdateMsgSize { return errors.New("invalid handshake key update message length") } if len(p.handshakeBuf) != 0 { return errors.New("key update message must be the last message of a handshake record") } if err := p.handleKeyUpdateMsg(msg); err != nil { return err } case tlsHandshakeNewSessionTicketType: // Do nothing for session ticket. default: return errors.New("unknown handshake message type") } } return nil } func buildKeyUpdateRequest() []byte { b := make([]byte, tlsHandshakePrefixSize+tlsHandshakeKeyUpdateMsgSize) b[0] = tlsHandshakeKeyUpdateType b[1] = 0 b[2] = 0 b[3] = tlsHandshakeKeyUpdateMsgSize b[4] = byte(updateNotRequested) return b } // handleKeyUpdateMsg handles a key update message. func (p *conn) handleKeyUpdateMsg(msg []byte) error { keyUpdateRequest := msg[0] if keyUpdateRequest != byte(updateNotRequested) && keyUpdateRequest != byte(updateRequested) { return errors.New("invalid handshake key update message") } if err := p.inConn.UpdateKey(); err != nil { return err } // Send a key update message back to the peer if requested. if keyUpdateRequest == byte(updateRequested) { p.writeMutex.Lock() defer p.writeMutex.Unlock() n, err := p.writeTLSRecord(preConstructedKeyUpdateMsg, byte(handshake)) if err != nil { return err } if n != tlsHandshakePrefixSize+tlsHandshakeKeyUpdateMsgSize { return errors.New("key update request message wrote less bytes than expected") } if err = p.outConn.UpdateKey(); err != nil { return err } } return nil } // bidEndianInt24 converts the given byte buffer of at least size 3 and // outputs the resulting 24 bit integer as a uint32. This is needed because // TLS 1.3 requires 3 byte integers, and the binary.BigEndian package does // not provide a way to transform a byte buffer into a 3 byte integer. func bigEndianInt24(b []byte) uint32 { _ = b[2] // bounds check hint to compiler; see golang.org/issue/14808 return uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16 } func min(a, b int) int { if a < b { return a } return b } s2a-go-0.1.8/internal/record/record_test.go000066400000000000000000001755051464711036600205730ustar00rootroot00000000000000/* * * Copyright 2021 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 record import ( "bytes" "errors" "net" "reflect" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/testing/protocmp" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil" ) var errFakeConnEOF = errors.New("fakeConn is out of bounds") // fakeConn is a fake implementation of the net.Conn interface used for testing. type fakeConn struct { net.Conn // bufCount tracks the current index of the buf. bufCount int buf [][]byte // additionalBuf is used to store records sent through the fakeConn. It is // used in record write tests and TestConnReadKeyUpdates. additionalBuf [][]byte closed bool } // Read returns part of the `in` buffer in sequential order each time it is // called. func (c *fakeConn) Read(b []byte) (n int, err error) { if c.bufCount >= len(c.buf) { return 0, errFakeConnEOF } n = copy(b, c.buf[c.bufCount]) if n < len(c.buf[c.bufCount]) { c.buf[c.bufCount] = c.buf[c.bufCount][n:] } else { c.bufCount++ } return n, nil } // Write copies the given buffer b, stores it in the `out` buffer, and returns // the number of bytes copied. func (c *fakeConn) Write(b []byte) (n int, err error) { buf := make([]byte, len(b)) n = copy(buf, b) c.additionalBuf = append(c.additionalBuf, buf) return n, nil } func (c *fakeConn) Close() error { c.closed = true return nil } type fakeTicketSender struct { sessionTickets [][]byte } func (f *fakeTicketSender) sendTicketsToS2A(sessionTickets [][]byte, callComplete chan bool) { f.sessionTickets = sessionTickets go func() { callComplete <- true close(callComplete) }() } func TestNewS2ARecordConn(t *testing.T) { for _, tc := range []struct { desc string options *ConnParameters outUnusedBytesBuf []byte outOverheadSize int outHandshakerServiceAddr string outConnectionID uint64 outLocalIdentity *commonpb.Identity outErr bool }{ { desc: "nil conn options", outErr: true, }, { desc: "invalid input traffic secret size", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), HSAddr: "test handshaker address", }, outErr: true, }, { desc: "invalid output traffic secret size", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), HSAddr: "test handshaker address", }, outErr: true, }, { desc: "invalid tls version", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, TLSVersion: commonpb.TLSVersion_TLS1_2, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), HSAddr: "test handshaker address", }, outErr: true, }, { desc: "basic with AES-128-GCM-SHA256", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), HSAddr: "test handshaker address", ConnectionID: 1, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, }, // outOverheadSize = header size (5) + record type byte (1) + // tag size (16). outOverheadSize: 22, outHandshakerServiceAddr: "test handshaker address", outConnectionID: 1, outLocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, }, { desc: "basic with AES-256-GCM-SHA384", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), HSAddr: "test handshaker address", ConnectionID: 1, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, }, // outOverheadSize = header size (5) + record type byte (1) + // tag size (16). outOverheadSize: 22, outHandshakerServiceAddr: "test handshaker address", outConnectionID: 1, outLocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, }, { desc: "basic with CHACHA20-POLY1305-SHA256", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), HSAddr: "test handshaker address", ConnectionID: 1, LocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, }, // outOverheadSize = header size (5) + record type byte (1) + // tag size (16). outOverheadSize: 22, outHandshakerServiceAddr: "test handshaker address", outConnectionID: 1, outLocalIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, }, { desc: "basic with unusedBytes", options: &ConnParameters{ NetConn: &fakeConn{}, Ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), UnusedBuf: testutil.Dehex("ffffffff"), HSAddr: "test handshaker address", }, outUnusedBytesBuf: testutil.Dehex("ffffffff"), // outOverheadSize = header size (5) + record type byte (1) + // tag size (16). outOverheadSize: 22, outHandshakerServiceAddr: "test handshaker address", }, } { t.Run(tc.desc, func(t *testing.T) { NetConn, err := NewConn(tc.options) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("NewConn(%v) = (err=nil) = %v, want %v", *tc.options, got, want) } if err != nil { return } conn := NetConn.(*conn) if got, want := conn.unusedBuf, tc.outUnusedBytesBuf; !bytes.Equal(got, want) { t.Errorf("conn.unusedBytes = %v, want %v", got, want) } if got, want := conn.overheadSize, tc.outOverheadSize; got != want { t.Errorf("conn.overheadSize = %v, want %v", got, want) } ticketSender := conn.ticketSender.(*ticketSender) if got, want := ticketSender.hsAddr, tc.outHandshakerServiceAddr; got != want { t.Errorf("ticketSender.hsAddr = %v, want %v", got, want) } if got, want := ticketSender.connectionID, tc.outConnectionID; got != want { t.Errorf("ticketSender.connectionID = %v, want %v", got, want) } if got, want := ticketSender.localIdentity, tc.outLocalIdentity; !cmp.Equal(got, want, protocmp.Transform()) { t.Errorf("ticketSender.localIdentity = %v, want %v", got, want) } }) } } func TestStripPaddingAndType(t *testing.T) { for _, tc := range []struct { desc string pendingApplicationData, outPendingApplicationData []byte outContentType recordType }{ { desc: "no padding", pendingApplicationData: []byte{byte(alert)}, outContentType: alert, }, { desc: "single padding", pendingApplicationData: []byte{byte(applicationData), 0x00}, outContentType: applicationData, }, { desc: "multi padding", pendingApplicationData: []byte{byte(handshake), 0x00, 0x00}, outContentType: handshake, }, { desc: "app data with no padding", pendingApplicationData: []byte{0xff, byte(handshake)}, outPendingApplicationData: []byte{0xff}, outContentType: handshake, }, { desc: "app data with padding", pendingApplicationData: []byte{0xff, byte(handshake), 0x00}, outPendingApplicationData: []byte{0xff}, outContentType: handshake, }, } { t.Run(tc.desc, func(t *testing.T) { c := conn{pendingApplicationData: tc.pendingApplicationData} ct, err := c.stripPaddingAndType() if err != nil { t.Errorf("c.stripPaddingAndType() failed: %v", err) } if got, want := c.pendingApplicationData, tc.outPendingApplicationData; !bytes.Equal(got, want) { t.Errorf("c.pendingApplicationData = %v, want %v", got, want) } if got, want := ct, tc.outContentType; got != want { t.Errorf("ct = %v, want %v", got, want) } }) } } func TestParseRecord(t *testing.T) { for _, tc := range []struct { desc string b []byte maxLen uint16 outCompletedRecord, outRemaining []byte outErr bool }{ { desc: "buffer smaller than header size", b: make([]byte, 1), outRemaining: make([]byte, 1), }, { desc: "header payload size larger than maxLen", b: testutil.Dehex("000000ffff"), maxLen: 1, outRemaining: testutil.Dehex("000000ffff"), outErr: true, }, { desc: "header payload size same as maxLen", b: testutil.Dehex("0000000003ffffff"), maxLen: 3, outCompletedRecord: testutil.Dehex("0000000003ffffff"), }, { desc: "incomplete record", b: testutil.Dehex("0000000001"), maxLen: 10, outRemaining: testutil.Dehex("0000000001"), }, { desc: "complete record", b: testutil.Dehex("0000000001ff"), maxLen: 10, outCompletedRecord: testutil.Dehex("0000000001ff"), }, } { t.Run(tc.desc, func(t *testing.T) { completedRecord, remaining, err := parseReadBuffer(tc.b, tc.maxLen) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("parseReadBuffer(%v, %v) = (err=nil) = %v, want %v", tc.b, tc.maxLen, got, want) } if err != nil { return } if got, want := completedRecord, tc.outCompletedRecord; !bytes.Equal(got, want) { t.Errorf("completedRecord = %v, want %v", got, want) } if got, want := remaining, tc.outRemaining; !bytes.Equal(got, want) { t.Errorf("remaining = %v, want %v", got, want) } }) } } func TestReadCompletedRecord(t *testing.T) { for _, tc := range []struct { desc string connBufs [][]byte nextRecord, unusedBuf []byte outCompletedRecords [][]byte outErr bool }{ { desc: "invalid record header size", nextRecord: testutil.Dehex("170303ffff"), outErr: true, }, { desc: "complete record in single read", connBufs: [][]byte{ testutil.Dehex("1703030001ff"), }, outCompletedRecords: [][]byte{ testutil.Dehex("1703030001ff"), }, }, { desc: "complete record in single read from leftover buffer", nextRecord: testutil.Dehex("1703030001ff"), outCompletedRecords: [][]byte{ testutil.Dehex("1703030001ff"), }, }, { desc: "complete record split in header", connBufs: [][]byte{ testutil.Dehex("170303"), testutil.Dehex("0001ff"), }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030001ff"), }, }, { desc: "complete record split in ciphertext", connBufs: [][]byte{ testutil.Dehex("1703030002ff"), testutil.Dehex("ff"), }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030002ffff"), }, }, { desc: "two complete records split in header", connBufs: [][]byte{ testutil.Dehex("170303"), testutil.Dehex("0002ffff1703030001ff"), }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030002ffff"), testutil.Dehex("1703030001ff"), }, }, { desc: "two complete records split in second header", connBufs: [][]byte{ testutil.Dehex("1703030002ffff1703"), testutil.Dehex("030001ff"), }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030002ffff"), testutil.Dehex("1703030001ff"), }, }, { desc: "two complete records split in ciphertext", connBufs: [][]byte{ testutil.Dehex("1703030002ff"), testutil.Dehex("ff1703030001ff"), }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030002ffff"), testutil.Dehex("1703030001ff"), }, }, { desc: "two complete records split in second ciphertext", connBufs: [][]byte{ testutil.Dehex("1703030002ffff1703030002ff"), testutil.Dehex("ff"), }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030002ffff"), testutil.Dehex("1703030002ffff"), }, }, { desc: "complete record split by each byte", connBufs: [][]byte{ {0x17}, {0x03}, {0x03}, {0x00}, {0x01}, {0xff}, }, unusedBuf: make([]byte, tlsRecordMaxPlaintextSize), outCompletedRecords: [][]byte{ testutil.Dehex("1703030001ff"), }, }, } { t.Run(tc.desc, func(t *testing.T) { fConn := &fakeConn{buf: tc.connBufs} c := &conn{Conn: fConn, nextRecord: tc.nextRecord, unusedBuf: tc.unusedBuf} for _, outCompletedRecord := range tc.outCompletedRecords { completedRecord, err := c.readFullRecord() if got, want := err == nil, !tc.outErr; got != want { t.Errorf("c.readCompletecRecord() = (err=nil) = %v, want %v", got, want) } if err != nil { return } if got, want := completedRecord, outCompletedRecord; !bytes.Equal(got, want) { t.Errorf("c.readFullRecord() = %v, want %v", got, want) } } }) } } func TestSplitAndValidateHeader(t *testing.T) { for _, tc := range []struct { desc string completedRecord []byte outHeader, outCiphertext []byte outErr bool }{ { desc: "invalid header type", completedRecord: make([]byte, tlsRecordHeaderSize), outErr: true, }, { desc: "invalid legacy record version", completedRecord: []byte{byte(tlsApplicationData), 0x00, 0x00, 0x00, 0x00}, outErr: true, }, { desc: "basic with no ciphertext", completedRecord: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x00}, outHeader: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x00}, }, { desc: "basic with ciphertext", completedRecord: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x01, 0xff}, outHeader: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x01}, outCiphertext: []byte{0xff}, }, } { t.Run(tc.desc, func(t *testing.T) { header, ciphertext, err := splitAndValidateHeader(tc.completedRecord) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("splitAndValidateHeader(%v) = (err=nil) = %v, want %v", tc.completedRecord, got, want) } if err != nil { return } if got, want := header, tc.outHeader; !bytes.Equal(got, want) { t.Errorf("header = %v, want %v", got, want) } if got, want := ciphertext, tc.outCiphertext; !bytes.Equal(got, want) { t.Errorf("ciphertext = %v, want %v", got, want) } }) } } func TestConnReadApplicationData(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite trafficSecret []byte completedRecords [][]byte outPlaintexts [][]byte outErr bool }{ // The traffic secrets were chosen randomly and are equivalent to the // ones used in C++ and Java. The ciphertext was constructed using an // existing TLS library. { desc: "AES-128-GCM-SHA256 with no padding", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"), testutil.Dehex("170303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-128-GCM-SHA256 with padding", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030021f2e4e411ac6760e84726e4886d7432e39b34f0fccfc1f4558303c68a19535c0ff5"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "AES-128-GCM-SHA256 empty", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030011d47cb2ec040f26cc8989330339c669dd4e"), }, outPlaintexts: [][]byte{ []byte(""), }, }, { desc: "AES-256-GCM-SHA384 with no padding", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"), testutil.Dehex("170303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-256-GCM-SHA384 with padding", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303002124efee5af1a621e8a4d1f269930e7835cfdd05e2d0bec5b01a67decfa6372c2af7"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "AES-256-GCM-SHA384 empty", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303001102a04134d38c1118f36b01d177c5d2dcf7"), }, outPlaintexts: [][]byte{ []byte(""), }, }, { desc: "CHACHA20-POLY1305-SHA256 with no padding", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"), testutil.Dehex("170303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 with padding", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030021c947ffa4703043f063e7b6a0519fbd0956cf3a7c9730c13597eec17ec7e700f140"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 empty", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030011ef8f7a428ddc84ee5968cd6306bf1d2d1b"), }, outPlaintexts: [][]byte{ []byte(""), }, }, { desc: "AES-128-GCM-SHA256 split in first record", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760"), testutil.Dehex("e4e3f074a36574c45ee4c1906103db0d"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "AES-256-GCM-SHA384 split in first record", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303001724efee5af1a6"), testutil.Dehex("2170ad5a95f899d038b965386a1a7daed9"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 split in first record", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017c947ffa470"), testutil.Dehex("304370338bb07ce468e6b8a0944a338ba402"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "AES-128-GCM-SHA256 split in first record header", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("17"), testutil.Dehex("03030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "AES-256-GCM-SHA384 split in first record header", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("17"), testutil.Dehex("0303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 split in first record header", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("17"), testutil.Dehex("03030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"), }, outPlaintexts: [][]byte{ []byte("123456"), }, }, { desc: "AES-128-GCM-SHA256 split in second record", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d170303001ad7"), testutil.Dehex("853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-256-GCM-SHA384 split in second record", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9170303001a83"), testutil.Dehex("2a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 split in second record", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402170303001a0c"), testutil.Dehex("edeb922170c110c172262542c67916b78fa0d1c1261709cd00"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-128-GCM-SHA256 split in second record header", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d17"), testutil.Dehex("0303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-256-GCM-SHA384 split in second record header", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed917"), testutil.Dehex("0303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 split in second record header", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba40217"), testutil.Dehex("0303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-128-GCM-SHA256 split randomly", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760e4"), testutil.Dehex("e3f074a36574c45ee4c1906103db0d17"), testutil.Dehex("0303001ad7853afd6d7ceaab"), testutil.Dehex("ab950a0b6707905d2b908894871c7c62021f"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "AES-256-GCM-SHA384 split randomly", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("170303001724efee"), testutil.Dehex("5af1a62170ad5a95f899d038b965386a1a7daed917"), testutil.Dehex("03"), testutil.Dehex("03001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, { desc: "CHACHA20-POLY1305-SHA256 split randomly", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("17"), testutil.Dehex("03030017c947ffa470304370338bb07ce468e6b8a0944a338ba40217"), testutil.Dehex("0303001a0cedeb922170"), testutil.Dehex("c110c172262542c67916b78fa0d1c1261709cd00"), }, outPlaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, }, } { t.Run(tc.desc, func(t *testing.T) { c, err := NewConn(&ConnParameters{ NetConn: &fakeConn{buf: tc.completedRecords}, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) if err != nil { t.Fatalf("NewConn() failed: %v", err) } for _, outPlaintext := range tc.outPlaintexts { plaintext := make([]byte, tlsRecordMaxPlaintextSize) n, err := c.Read(plaintext) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("c.Read(plaintext) = (err=nil) = %v, want %v", got, want) } if err != nil { return } plaintext = plaintext[:n] if got, want := plaintext, outPlaintext; !bytes.Equal(got, want) { t.Errorf("c.Read(plaintext) = %v, want %v", got, want) } } }) } } func TestConnReadAlert(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite trafficSecret []byte completedRecord []byte }{ // The records below are TLS 1.3 records that hold the ciphertext // obtained by encrypting (with or without padding) the close notify // alert {0x01, 0x00} using the keys derived from the given traffic // secrets and the sequence number zero. { desc: "AES-128-GCM-SHA256 with no padding", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("1703030013c2d6c245fb80969de1dd9d14499261b67735b0"), }, { desc: "AES-128-GCM-SHA256 with padding", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("170303001dc2d6c225995177e84726e4886d5ea79383e5d529cd8339fbbfcafe2418"), }, { desc: "AES-256-GCM-SHA384 with no padding", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("170303001314ddc8f3b3856660bb5ac81533c157582f8b4c"), }, { desc: "AES-256-GCM-SHA384 with padding", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("170303001d14ddc86ec49036e8a4d1f269933545f03b0fe9ffd8b02acd1e41f7139e"), }, { desc: "CHACHA20-POLY1305-SHA256 with no padding", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("1703030013f975d9cb2f116d85d4e3859f5288a9b013d778"), }, { desc: "CHACHA20-POLY1305-SHA256 with padding", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("170303001df975d990450654f063e7b6a0514c2714c9827e796071389802f451585a"), }, // The records below are TLS 1.3 records that hold the ciphertext // obtained by encrypting the alert {0x01, 0x2c} using the keys derived // from the given traffic secrets and the sequence number zero. { desc: "AES-128-GCM-SHA256 other alert", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("1703030013c2fac23f995cbe79a8d1e4c8f0353afefeaac9"), }, { desc: "AES-256-GCM-SHA384 other alert", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("170303001314f1c80add85193c9598219ae9dc26f2479ccf"), }, { desc: "CHACHA20-POLY1305-SHA256 other alert", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("1703030013f959d96fed92bdc7e85e04e86c19eaf154b052"), }, // The records below are TLS 1.3 records that hold the ciphertext // obtained by encrypting the message {0x01} using the keys derived // from the given traffic secrets and the sequence number zero. The // first byte of this message indicates that it should be an alert // message, but the length of the message is too small. { desc: "AES-128-GCM-SHA256 invalid", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("1703030012c2c351fc48d9ac84fa165adcc9a26ffbc3c7"), }, { desc: "AES-256-GCM-SHA384 invalid", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("170303001214c8476102a460b5cf9e9ba59e1726215ca9"), }, { desc: "CHACHA20-POLY1305-SHA256 invalid", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecord: testutil.Dehex("1703030012f9606a83ac17b165a51f3fe764da8560c706"), }, } { t.Run(tc.desc, func(t *testing.T) { f := &fakeConn{buf: [][]byte{tc.completedRecord}} c, err := NewConn(&ConnParameters{ NetConn: f, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) if err != nil { t.Fatalf("NewConn() failed: %v", err) } plaintext := make([]byte, tlsRecordMaxPlaintextSize) _, err = c.Read(plaintext) if got, want := err == nil, false; got != want { t.Errorf("c.Read(plaintext) = (err=nil) = %v, want %v", got, want) } }) } } func TestConnReadKeyUpdate(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite trafficSecret []byte completedRecords [][]byte plaintexts [][]byte outPlaintexts [][]byte outWriteBuf [][]byte }{ { desc: "AES-128-GCM-SHA256", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030020dbd6d724994777e84726e4886d7432e311a73b42d0073f28ea60e30e8eb498fd"), testutil.Dehex("1703030017dd99ebef48292cd4c372a000740372d2ae9aad31cfd274"), }, plaintexts: [][]byte{ []byte("123456"), }, outPlaintexts: [][]byte{ []byte(""), []byte("123456"), }, outWriteBuf: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"), }, }, { desc: "AES-256-GCM-SHA384", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("17030300200ddddd6fc48636e8a4d1f269930e7835adc07e732ba7fd617ff9a65a51c36b6d"), testutil.Dehex("17030300179cd5972e76baf56af644c92235460301c0a013ad35be00"), }, plaintexts: [][]byte{ []byte("123456"), }, outPlaintexts: [][]byte{ []byte(""), []byte("123456"), }, outWriteBuf: [][]byte{ testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"), }, }, { desc: "CHACHA20-POLY1305-SHA256", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030020e075cc91451054f063e7b6a0519fbd098e83bda4b515bea5196cccc008556ad0"), testutil.Dehex("1703030017c4e48ccaf036bd9bc146bbc6192404f9a2d2da5d1afe78"), }, plaintexts: [][]byte{ []byte("123456"), }, outPlaintexts: [][]byte{ []byte(""), []byte("123456"), }, outWriteBuf: [][]byte{ testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"), }, }, { desc: "AES-128-GCM-SHA256 send key update request", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030016dbd6d724984756cc7bd50502b024f94b489f1a943df5"), testutil.Dehex("1703030017dd99ebef48292cd4c372a000740372d2ae9aad31cfd274"), }, plaintexts: [][]byte{ []byte("123456"), }, outPlaintexts: [][]byte{ []byte(""), []byte("123456"), }, outWriteBuf: [][]byte{ testutil.Dehex("1703030016dbd6d7249947cdda08655a3c2622891c1758fb0c0d0e"), testutil.Dehex("1703030017dd99ebef48292cd4c372a000740372d2ae9aad31cfd274"), }, }, { desc: "AES-256-GCM-SHA384 send key update request", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("17030300160ddddd6fc5862e8275a95a35a9a43502a1da78f8a416"), testutil.Dehex("17030300179cd5972e76baf56af644c92235460301c0a013ad35be00"), }, plaintexts: [][]byte{ []byte("123456"), }, outPlaintexts: [][]byte{ []byte(""), []byte("123456"), }, outWriteBuf: [][]byte{ testutil.Dehex("17030300160ddddd6fc486a82b55d4457e3dc846f77b6d3f24de45"), testutil.Dehex("17030300179cd5972e76baf56af644c92235460301c0a013ad35be00"), }, }, { desc: "CHACHA20-POLY1305-SHA256 send key update request", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), completedRecords: [][]byte{ testutil.Dehex("1703030016e075cc914410ffeb7e4d960f8e3b1e830c137cc69692"), testutil.Dehex("1703030017c4e48ccaf036bd9bc146bbc6192404f9a2d2da5d1afe78"), }, plaintexts: [][]byte{ []byte("123456"), }, outPlaintexts: [][]byte{ []byte(""), []byte("123456"), }, outWriteBuf: [][]byte{ testutil.Dehex("1703030016e075cc914510bc0dbc87cfc12f394b235147042f42d0"), testutil.Dehex("1703030017c4e48ccaf036bd9bc146bbc6192404f9a2d2da5d1afe78"), }, }, } { t.Run(tc.desc, func(t *testing.T) { fConn := &fakeConn{buf: tc.completedRecords} c, err := NewConn(&ConnParameters{ NetConn: fConn, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) if err != nil { t.Fatalf("NewConn() failed: %v", err) } for _, outPlaintext := range tc.outPlaintexts { plaintext := make([]byte, tlsRecordMaxPlaintextSize) n, err := c.Read(plaintext) if err != nil { t.Fatalf("c.Read(plaintext) failed: %v", err) } plaintext = plaintext[:n] if got, want := plaintext, outPlaintext; !bytes.Equal(got, want) { t.Errorf("c.Read(plaintext) = %v, want %v", got, want) } } // Check that the outbound traffic secret was updated properly. This // is done by writing plaintexts after the key update and verifying // the output. for _, plaintext := range tc.plaintexts { n, err := c.Write(plaintext) if err != nil { t.Fatalf("c.Write(plaintext) failed: %v", err) } if got, want := n, len(plaintext); got != want { t.Fatalf("c.Write(plaintext) = %v, want %v", got, want) } } if got, want := fConn.additionalBuf, tc.outWriteBuf; !cmp.Equal(fConn.additionalBuf, tc.outWriteBuf) { t.Errorf("fConn.additionalBuf = %x, want %x", got, want) } if got, want := len(c.(*conn).pendingApplicationData), 0; got != want { t.Errorf("len(c.(*conn).pendingApplicationData) = %v, want %v", got, want) } // If a key update message is produced on request, verify that it // can be decrypted properly by a new Conn object. Also, verify that // messages written by the original Conn object after the key update // can be decrypted properly by the new Conn object. fConn2 := &fakeConn{buf: tc.outWriteBuf} c2, err := NewConn(&ConnParameters{ NetConn: fConn2, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) if err != nil { t.Fatalf("NewConn() failed: %v", err) } for range tc.outWriteBuf { plaintext := make([]byte, tlsRecordMaxPlaintextSize) _, err := c2.Read(plaintext) if err != nil { t.Fatalf("c.Read(plaintext) failed: %v", err) } } }) } } func TestWrite(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite trafficSecret []byte plaintexts [][]byte outRecords [][]byte outBytesWritten []int outErr bool }{ // The traffic secrets were chosen randomly and are equivalent to the // ones used in C++ and Java. The ciphertext was constructed using an // existing TLS library. { desc: "AES-128-GCM-SHA256", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, outRecords: [][]byte{ testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"), testutil.Dehex("170303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"), }, outBytesWritten: []int{6, 9}, }, { desc: "AES-128-GCM-SHA256 empty", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte(""), }, outRecords: [][]byte{ testutil.Dehex("1703030011d47cb2ec040f26cc8989330339c669dd4e"), }, outBytesWritten: []int{0}, }, { desc: "AES-256-GCM-SHA384", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, outRecords: [][]byte{ testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"), testutil.Dehex("170303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"), }, outBytesWritten: []int{6, 9}, }, { desc: "AES-256-GCM-SHA384 empty", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte(""), }, outRecords: [][]byte{ testutil.Dehex("170303001102a04134d38c1118f36b01d177c5d2dcf7"), }, outBytesWritten: []int{0}, }, { desc: "CHACHA20-POLY1305-SHA256", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, outRecords: [][]byte{ testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"), testutil.Dehex("170303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"), }, outBytesWritten: []int{6, 9}, }, { desc: "CHACHA20-POLY1305-SHA256 empty", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte(""), }, outRecords: [][]byte{ testutil.Dehex("1703030011ef8f7a428ddc84ee5968cd6306bf1d2d1b"), }, outBytesWritten: []int{0}, }, } { t.Run(tc.desc, func(t *testing.T) { fConn := &fakeConn{} newConn, err := NewConn(&ConnParameters{ NetConn: fConn, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) c := newConn.(*conn) if err != nil { t.Fatalf("NewConn() failed: %v", err) } for i, plaintext := range tc.plaintexts { bytesWritten, err := c.writeTLSRecord(plaintext, tlsApplicationData) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", got, want) } if bytesWritten != tc.outBytesWritten[i] { t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, tc.outBytesWritten[i]) } } if !reflect.DeepEqual(fConn.additionalBuf, tc.outRecords) { t.Errorf("Incorrect Record: got: %v, want: %v", fConn.additionalBuf, tc.outRecords) } }) } } func TestWriteTwoRecords(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite trafficSecret []byte plaintext []byte numRecordBytes int outBytesWritten int outErr bool }{ // The plaintext of size tlsRecordMaxPlaintextSize + 1 will be written // to the underlying connection in 2 TLS records: one containing 2^14 // bytes of plaintext, and the other containing 1 byte of plaintext, // resulting in 23+tlsRecordMaxSize total record bytes written, // including the overheads. { desc: "AES-128-GCM-SHA256", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize), // 2^14+1 numRecordBytes: 23 + tlsRecordMaxSize, outBytesWritten: 1 + tlsRecordMaxPlaintextSize, }, { desc: "AES-256-GCM-SHA384", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize), // 2^14+1 numRecordBytes: 23 + tlsRecordMaxSize, outBytesWritten: 1 + tlsRecordMaxPlaintextSize, }, { desc: "CHACHA20-POLY1305-SHA256", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize), // 2^14+1 numRecordBytes: 23 + tlsRecordMaxSize, outBytesWritten: 1 + tlsRecordMaxPlaintextSize, }, } { t.Run(tc.desc, func(t *testing.T) { fConn := &fakeConn{} newConn, err := NewConn(&ConnParameters{ NetConn: fConn, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) c := newConn.(*conn) if err != nil { t.Fatalf("NewConn() failed: %v", err) } bytesWritten, err := c.writeTLSRecord(tc.plaintext, tlsApplicationData) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", got, want) } if bytesWritten != tc.outBytesWritten { t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, tc.outBytesWritten) } if len(fConn.additionalBuf[0]) != tc.numRecordBytes { t.Errorf("Incorrect number of bytes prepared: got: %v, want: %v", len(fConn.additionalBuf[0]), tc.numRecordBytes) } }) } } func TestExceedBufferSize(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite trafficSecret []byte plaintext []byte expectedOutRecordBufSize int expectedNumWrites int outErr bool }{ // plaintext is set to 1+tlsRecordMaxPlaintextSize, 1 byte more than the maximum number of // plaintext bytes in a single record, expectedOutRecordBufSize is set // to 16406, as it is the maximum size of a single record. { desc: "AES-128-GCM-SHA256", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords), expectedOutRecordBufSize: outBufMaxSize, expectedNumWrites: 2, }, { desc: "AES-256-GCM-SHA384", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords), expectedOutRecordBufSize: outBufMaxSize, expectedNumWrites: 2, }, { desc: "CHACHA20-POLY1305-SHA256", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords), expectedOutRecordBufSize: outBufMaxSize, expectedNumWrites: 2, }, } { t.Run(tc.desc, func(t *testing.T) { fConn := &fakeConn{} newConn, err := NewConn(&ConnParameters{ NetConn: fConn, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.trafficSecret, OutTrafficSecret: tc.trafficSecret, }) c := newConn.(*conn) if err != nil { t.Fatalf("NewConn() failed: %v", err) } bytesWritten, err := c.writeTLSRecord(tc.plaintext, tlsApplicationData) if got, want := err == nil, !tc.outErr; got != want { t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", err, want) } if bytesWritten != len(tc.plaintext) { t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, len(tc.plaintext)) } if len(c.outRecordsBuf) != tc.expectedOutRecordBufSize { t.Errorf("Incorrect buf size: got: %v, want: %v", len(c.outRecordsBuf), tc.expectedOutRecordBufSize) } if len(fConn.additionalBuf) != tc.expectedNumWrites { t.Errorf("Inforrect number of records: got: %v, want: %v,", len(fConn.additionalBuf), tc.expectedNumWrites) } }) } } func TestRoundtrip(t *testing.T) { for _, tc := range []struct { desc string ciphersuite commonpb.Ciphersuite inTrafficSecret []byte outTrafficSecret []byte plaintexts [][]byte plaintextBytesWritten []int numRecordBytes []int }{ // numRecordBytes is calculated as // len(plaintext)+header(5)+tag(16)+record_type(1) { desc: "AES-128-GCM-SHA256", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, plaintextBytesWritten: []int{6, 9}, numRecordBytes: []int{28, 31}, }, { desc: "AES-128-GCM-SHA256 different traffic secrets", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, plaintextBytesWritten: []int{6, 9}, numRecordBytes: []int{28, 31}, }, { desc: "AES-128-GCM-SHA256 empty", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte(""), }, plaintextBytesWritten: []int{0}, numRecordBytes: []int{22}, }, { desc: "AES-128-GCM-SHA256 max buffer size", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ make([]byte, tlsRecordMaxPlaintextSize*outBufMaxRecords), }, plaintextBytesWritten: []int{tlsRecordMaxPlaintextSize * outBufMaxRecords}, numRecordBytes: []int{outBufMaxSize}, }, { desc: "AES-128-GCM-SHA256 exceed buffer size", ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords), }, plaintextBytesWritten: []int{1 + tlsRecordMaxPlaintextSize*outBufMaxRecords}, numRecordBytes: []int{outBufMaxSize, 23}, }, { desc: "AES-256-GCM-SHA384", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, plaintextBytesWritten: []int{6, 9}, numRecordBytes: []int{28, 31}, }, { desc: "AES-256-GCM-SHA384 different traffic secrets", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, plaintextBytesWritten: []int{6, 9}, numRecordBytes: []int{28, 31}, }, { desc: "AES-256-GCM-SHA384 empty", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte(""), }, plaintextBytesWritten: []int{0}, numRecordBytes: []int{22}, }, { desc: "AES-256-GCM-SHA384 max buffer size", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ make([]byte, tlsRecordMaxPlaintextSize*outBufMaxRecords), }, plaintextBytesWritten: []int{tlsRecordMaxPlaintextSize * outBufMaxRecords}, numRecordBytes: []int{outBufMaxSize}, }, { desc: "AES-256-GCM-SHA384 exceed buffer size", ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords), }, plaintextBytesWritten: []int{1 + tlsRecordMaxPlaintextSize*outBufMaxRecords}, numRecordBytes: []int{outBufMaxSize, 23}, }, { desc: "CHACHA20-POLY1305-SHA256", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, plaintextBytesWritten: []int{6, 9}, numRecordBytes: []int{28, 31}, }, { desc: "CHACHA20-POLY1305-SHA256 different traffic secrets", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b"), plaintexts: [][]byte{ []byte("123456"), []byte("789123456"), }, plaintextBytesWritten: []int{6, 9}, numRecordBytes: []int{28, 31}, }, { desc: "CHACHA20-POLY1305-SHA256 empty", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ []byte(""), }, plaintextBytesWritten: []int{0}, numRecordBytes: []int{22}, }, { desc: "CHACHA20-POLY1305-SHA256 max buffer size", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ make([]byte, tlsRecordMaxPlaintextSize*outBufMaxRecords), }, plaintextBytesWritten: []int{tlsRecordMaxPlaintextSize * outBufMaxRecords}, numRecordBytes: []int{outBufMaxSize}, }, { desc: "CHACHA20-POLY1305-SHA256 max buffer size", ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256, inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"), plaintexts: [][]byte{ make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords), }, plaintextBytesWritten: []int{1 + tlsRecordMaxPlaintextSize*outBufMaxRecords}, numRecordBytes: []int{outBufMaxSize, 23}, }, } { t.Run(tc.desc, func(t *testing.T) { fConnClient := &fakeConn{} client, err := NewConn(&ConnParameters{ NetConn: fConnClient, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.inTrafficSecret, OutTrafficSecret: tc.outTrafficSecret, }) if err != nil { t.Fatalf("NewConn() failed: %v", err) } fConnServer := &fakeConn{} server, err := NewConn(&ConnParameters{ NetConn: fConnServer, Ciphersuite: tc.ciphersuite, TLSVersion: commonpb.TLSVersion_TLS1_3, InTrafficSecret: tc.outTrafficSecret, OutTrafficSecret: tc.inTrafficSecret, }) if err != nil { t.Fatalf("NewConn() failed: %v", err) } err = sendRecordsRoundtrip(t, client, server, fConnClient, fConnServer, tc.plaintexts, tc.plaintextBytesWritten, tc.numRecordBytes) if err != nil { return } sendRecordsRoundtrip(t, server, client, fConnServer, fConnClient, tc.plaintexts, tc.plaintextBytesWritten, tc.numRecordBytes) }) } } func sendRecordsRoundtrip(t *testing.T, src net.Conn, dst net.Conn, fConnSrc *fakeConn, fConnDst *fakeConn, plaintexts [][]byte, plaintextBytesWritten []int, recordBytes []int) error { for i, plaintext := range plaintexts { bytesWritten, err := src.Write(plaintext) if got, want := err == nil, true; got != want { t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", err, want) return errors.New("Write returned unexpected output") } if bytesWritten != plaintextBytesWritten[i] { t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, plaintextBytesWritten[i]) return errors.New("Write returned unexpected output") } if len(fConnSrc.additionalBuf[i]) != recordBytes[i] { t.Errorf("Incorrect number of bytes prepared: got: %v, want: %v", len(fConnSrc.additionalBuf[i]), recordBytes[i]) return errors.New("Write returned unexpected output") } } fConnDst.buf = fConnSrc.additionalBuf for _, outPlaintext := range plaintexts { n := 0 for n < len(outPlaintext) { plaintext := make([]byte, tlsRecordMaxPlaintextSize) dn, err := dst.Read(plaintext) if got, want := err == nil, true; got != want { t.Errorf("c.Read(plaintext) = (err=nil) = %v, want %v", err, want) return errors.New("Read returned unexpected output") } if got, want := plaintext[:dn], outPlaintext[n:n+dn]; !bytes.Equal(got, want) { t.Errorf("c.Read(plaintext) = %v, want %v", len(got), len(want)) return errors.New("Read returned unexpected output") } n += dn } } return nil } s2a-go-0.1.8/internal/record/ticketsender.go000066400000000000000000000127771464711036600207430ustar00rootroot00000000000000/* * * Copyright 2021 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 record import ( "context" "fmt" "sync" "time" "github.com/google/s2a-go/internal/handshaker/service" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" "github.com/google/s2a-go/internal/tokenmanager" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" ) // sessionTimeout is the timeout for creating a session with the S2A handshaker // service. const sessionTimeout = time.Second * 5 // s2aTicketSender sends session tickets to the S2A handshaker service. type s2aTicketSender interface { // sendTicketsToS2A sends the given session tickets to the S2A handshaker // service. sendTicketsToS2A(sessionTickets [][]byte, callComplete chan bool) } // ticketStream is the stream used to send and receive session information. type ticketStream interface { Send(*s2apb.SessionReq) error Recv() (*s2apb.SessionResp, error) } type ticketSender struct { // hsAddr stores the address of the S2A handshaker service. hsAddr string // connectionID is the connection identifier that was created and sent by // S2A at the end of a handshake. connectionID uint64 // localIdentity is the local identity that was used by S2A during session // setup and included in the session result. localIdentity *commonpb.Identity // tokenManager manages access tokens for authenticating to S2A. tokenManager tokenmanager.AccessTokenManager // ensureProcessSessionTickets allows users to wait and ensure that all // available session tickets are sent to S2A before a process completes. ensureProcessSessionTickets *sync.WaitGroup } // sendTicketsToS2A sends the given sessionTickets to the S2A handshaker // service. This is done asynchronously and writes to the error logs if an error // occurs. func (t *ticketSender) sendTicketsToS2A(sessionTickets [][]byte, callComplete chan bool) { // Note that the goroutine is in the function rather than at the caller // because the fake ticket sender used for testing must run synchronously // so that the session tickets can be accessed from it after the tests have // been run. if t.ensureProcessSessionTickets != nil { t.ensureProcessSessionTickets.Add(1) } go func() { if err := func() error { defer func() { if t.ensureProcessSessionTickets != nil { t.ensureProcessSessionTickets.Done() } }() ctx, cancel := context.WithTimeout(context.Background(), sessionTimeout) defer cancel() // The transportCreds only needs to be set when talking to S2AV2 and also // if mTLS is required. hsConn, err := service.Dial(ctx, t.hsAddr, nil) if err != nil { return err } client := s2apb.NewS2AServiceClient(hsConn) session, err := client.SetUpSession(ctx) if err != nil { return err } defer func() { if err := session.CloseSend(); err != nil { grpclog.Error(err) } }() return t.writeTicketsToStream(session, sessionTickets) }(); err != nil { grpclog.Errorf("failed to send resumption tickets to S2A with identity: %v, %v", t.localIdentity, err) } callComplete <- true close(callComplete) }() } // writeTicketsToStream writes the given session tickets to the given stream. func (t *ticketSender) writeTicketsToStream(stream ticketStream, sessionTickets [][]byte) error { if err := stream.Send( &s2apb.SessionReq{ ReqOneof: &s2apb.SessionReq_ResumptionTicket{ ResumptionTicket: &s2apb.ResumptionTicketReq{ InBytes: sessionTickets, ConnectionId: t.connectionID, LocalIdentity: t.localIdentity, }, }, AuthMechanisms: t.getAuthMechanisms(), }, ); err != nil { return err } sessionResp, err := stream.Recv() if err != nil { return err } if sessionResp.GetStatus().GetCode() != uint32(codes.OK) { return fmt.Errorf("s2a session ticket response had error status: %v, %v", sessionResp.GetStatus().GetCode(), sessionResp.GetStatus().GetDetails()) } return nil } func (t *ticketSender) getAuthMechanisms() []*s2apb.AuthenticationMechanism { if t.tokenManager == nil { return nil } // First handle the special case when no local identity has been provided // by the application. In this case, an AuthenticationMechanism with no local // identity will be sent. if t.localIdentity == nil { token, err := t.tokenManager.DefaultToken() if err != nil { grpclog.Infof("unable to get token for empty local identity: %v", err) return nil } return []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: token, }, }, } } // Next, handle the case where the application (or the S2A) has specified // a local identity. token, err := t.tokenManager.Token(t.localIdentity) if err != nil { grpclog.Infof("unable to get token for local identity %v: %v", t.localIdentity, err) return nil } return []*s2apb.AuthenticationMechanism{ { Identity: t.localIdentity, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: token, }, }, } } s2a-go-0.1.8/internal/record/ticketsender_test.go000066400000000000000000000151751464711036600217750ustar00rootroot00000000000000/* * * Copyright 2021 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 record import ( "errors" "fmt" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" commonpbv1 "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" "github.com/google/s2a-go/internal/tokenmanager" "google.golang.org/grpc/codes" "google.golang.org/protobuf/testing/protocmp" ) const ( testAccessToken = "test_access_token" ) type fakeStream struct { // returnInvalid is a flag indicating whether the return status of Recv is // OK or not. returnInvalid bool // returnRecvErr is a flag indicating whether an error should be returned by // Recv. returnRecvErr bool } func (fs *fakeStream) Send(req *s2apb.SessionReq) error { if len(req.GetResumptionTicket().GetInBytes()) == 0 { return errors.New("fakeStream Send received an empty InBytes") } if req.GetResumptionTicket().GetConnectionId() == 0 { return errors.New("fakeStream Send received a 0 ConnectionId") } if req.GetResumptionTicket().GetLocalIdentity() == nil { return errors.New("fakeStream Send received an empty LocalIdentity") } return nil } func (fs *fakeStream) Recv() (*s2apb.SessionResp, error) { if fs.returnRecvErr { return nil, errors.New("fakeStream Recv error") } if fs.returnInvalid { return &s2apb.SessionResp{ Status: &s2apb.SessionStatus{Code: uint32(codes.InvalidArgument)}, }, nil } return &s2apb.SessionResp{ Status: &s2apb.SessionStatus{Code: uint32(codes.OK)}, }, nil } type fakeAccessTokenManager struct { acceptedIdentity *commonpbv1.Identity accessToken string allowEmptyIdentity bool } func (m *fakeAccessTokenManager) DefaultToken() (string, error) { if !m.allowEmptyIdentity { return "", fmt.Errorf("not allowed to get token for empty identity") } return m.accessToken, nil } func (m *fakeAccessTokenManager) Token(identity interface{}) (string, error) { switch v := identity.(type) { case *commonpbv1.Identity: // valid type. case *commonpb.Identity: // valid type. default: return "", fmt.Errorf("Incorrect identity type: %v", v) } if identity == nil || cmp.Equal(identity, &commonpbv1.Identity{}, protocmp.Transform()) || cmp.Equal(identity, &commonpb.Identity{}, protocmp.Transform()) { if !m.allowEmptyIdentity { return "", fmt.Errorf("not allowed to get token for empty identity") } return m.accessToken, nil } if cmp.Equal(identity, m.acceptedIdentity, protocmp.Transform()) { return m.accessToken, nil } return "", fmt.Errorf("unable to get token") } func TestWriteTicketsToStream(t *testing.T) { for _, tc := range []struct { returnInvalid bool returnRecvError bool }{ { // Both flags are set to false. }, { returnInvalid: true, }, { returnRecvError: true, }, } { sender := ticketSender{ connectionID: 1, localIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "test_spiffe_id", }, }, } fs := &fakeStream{returnInvalid: tc.returnInvalid, returnRecvErr: tc.returnRecvError} if got, want := sender.writeTicketsToStream(fs, make([][]byte, 1)) == nil, !tc.returnRecvError && !tc.returnInvalid; got != want { t.Errorf("sender.writeTicketsToStream(%v, _) = (err=nil) = %v, want %v", fs, got, want) } } } func TestGetAuthMechanism(t *testing.T) { sortProtos := cmpopts.SortSlices(func(m1, m2 *s2apb.AuthenticationMechanism) bool { return m1.String() < m2.String() }) for _, tc := range []struct { description string localIdentity *commonpbv1.Identity tokenManager tokenmanager.AccessTokenManager expectedAuthMechanisms []*s2apb.AuthenticationMechanism }{ { description: "token manager is nil", tokenManager: nil, expectedAuthMechanisms: nil, }, { description: "token manager expects empty identity", tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, allowEmptyIdentity: true, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, { description: "token manager does not expect empty identity", tokenManager: &fakeAccessTokenManager{ allowEmptyIdentity: false, }, expectedAuthMechanisms: nil, }, { description: "token manager expects SPIFFE ID", localIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, tokenManager: &fakeAccessTokenManager{ accessToken: testAccessToken, acceptedIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, }, expectedAuthMechanisms: []*s2apb.AuthenticationMechanism{ { Identity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_SpiffeId{ SpiffeId: "allowed_spiffe_id", }, }, MechanismOneof: &s2apb.AuthenticationMechanism_Token{ Token: testAccessToken, }, }, }, }, { description: "token manager does not expect hostname", localIdentity: &commonpbv1.Identity{ IdentityOneof: &commonpbv1.Identity_Hostname{ Hostname: "disallowed_hostname", }, }, tokenManager: &fakeAccessTokenManager{}, expectedAuthMechanisms: nil, }, } { t.Run(tc.description, func(t *testing.T) { ticketSender := &ticketSender{ localIdentity: tc.localIdentity, tokenManager: tc.tokenManager, } authMechanisms := ticketSender.getAuthMechanisms() if got, want := (authMechanisms == nil), (tc.expectedAuthMechanisms == nil); got != want { t.Errorf("authMechanisms == nil: %t, tc.expectedAuthMechanisms == nil: %t", got, want) } if authMechanisms != nil && tc.expectedAuthMechanisms != nil { if diff := cmp.Diff(authMechanisms, tc.expectedAuthMechanisms, protocmp.Transform(), sortProtos); diff != "" { t.Errorf("ticketSender.getAuthMechanisms() returned incorrect slice, (-want +got):\n%s", diff) } } }) } } s2a-go-0.1.8/internal/tokenmanager/000077500000000000000000000000001464711036600171075ustar00rootroot00000000000000s2a-go-0.1.8/internal/tokenmanager/tokenmanager.go000066400000000000000000000051101464711036600221060ustar00rootroot00000000000000/* * * Copyright 2021 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 tokenmanager provides tokens for authenticating to S2A. package tokenmanager import ( "fmt" "os" commonpbv1 "github.com/google/s2a-go/internal/proto/common_go_proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" ) const ( s2aAccessTokenEnvironmentVariable = "S2A_ACCESS_TOKEN" ) // AccessTokenManager manages tokens for authenticating to S2A. type AccessTokenManager interface { // DefaultToken returns a token that an application with no specified local // identity must use to authenticate to S2A. DefaultToken() (token string, err error) // Token returns a token that an application with local identity equal to // identity must use to authenticate to S2A. Token(identity interface{}) (token string, err error) } type singleTokenAccessTokenManager struct { token string } // NewSingleTokenAccessTokenManager returns a new AccessTokenManager instance // that will always manage the same token. // // The token to be managed is read from the s2aAccessTokenEnvironmentVariable // environment variable. If this environment variable is not set, then this // function returns an error. func NewSingleTokenAccessTokenManager() (AccessTokenManager, error) { token, variableExists := os.LookupEnv(s2aAccessTokenEnvironmentVariable) if !variableExists { return nil, fmt.Errorf("%s environment variable is not set", s2aAccessTokenEnvironmentVariable) } return &singleTokenAccessTokenManager{token: token}, nil } // DefaultToken always returns the token managed by the // singleTokenAccessTokenManager. func (m *singleTokenAccessTokenManager) DefaultToken() (string, error) { return m.token, nil } // Token always returns the token managed by the singleTokenAccessTokenManager. func (m *singleTokenAccessTokenManager) Token(identity interface{}) (string, error) { switch v := identity.(type) { case *commonpbv1.Identity: // valid type. case *commonpb.Identity: // valid type. default: return "", fmt.Errorf("Incorrect identity type: %v", v) } return m.token, nil } s2a-go-0.1.8/internal/tokenmanager/tokenmanager_test.go000066400000000000000000000042101464711036600231450ustar00rootroot00000000000000/* * * Copyright 2021 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 tokenmanager import ( "os" "testing" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" ) const testAccessToken = "test_access_token" func TestNewSingleTokenAccessTokenManagerFailure(t *testing.T) { os.Unsetenv(s2aAccessTokenEnvironmentVariable) if _, err := NewSingleTokenAccessTokenManager(); err == nil { t.Errorf("expected NewSingleTokenAccessTokenManager() to return non-nil error") } } func TestNewSingleTokenAccessTokenManagerDefaultTokenSuccess(t *testing.T) { os.Setenv(s2aAccessTokenEnvironmentVariable, testAccessToken) tokenManager, err := NewSingleTokenAccessTokenManager() if err != nil { t.Errorf("NewSingleTokenAccessTokenManager() returned unexpected error: %v", err) } token, err := tokenManager.DefaultToken() if err != nil { t.Errorf("tokenManager.DefaultToken() returned unexpected error: %v", err) } if got, want := token, testAccessToken; got != want { t.Errorf("tokenManager.DefaultToken()= %v, want %s", got, want) } } func TestNewSingleTokenAccessTokenManagerTokenSuccess(t *testing.T) { os.Setenv(s2aAccessTokenEnvironmentVariable, testAccessToken) tokenManager, err := NewSingleTokenAccessTokenManager() if err != nil { t.Errorf("NewSingleTokenAccessTokenManager() returned unexpected error: %v", err) } token, err := tokenManager.Token(&commonpb.Identity{}) if err != nil { t.Errorf("tokenManager.Token() returned unexpected error: %v", err) } if got, want := token, testAccessToken; got != want { t.Errorf("tokenManager.Token(%v)= %v, want %s", &commonpb.Identity{}, got, want) } } s2a-go-0.1.8/internal/v2/000077500000000000000000000000001464711036600147635ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/README.md000066400000000000000000000001221464711036600162350ustar00rootroot00000000000000**This directory has the implementation of the S2Av2's gRPC-Go client libraries** s2a-go-0.1.8/internal/v2/certverifier/000077500000000000000000000000001464711036600174545ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/certverifier/certverifier.go000066400000000000000000000110611464711036600224730ustar00rootroot00000000000000/* * * 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 certverifier offloads verifications to S2Av2. package certverifier import ( "crypto/x509" "fmt" "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" ) // VerifyClientCertificateChain builds a SessionReq, sends it to S2Av2 and // receives a SessionResp. func VerifyClientCertificateChain(verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, s2AStream stream.S2AStream) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { // Offload verification to S2Av2. if grpclog.V(1) { grpclog.Infof("Sending request to S2Av2 for client peer cert chain validation.") } if err := s2AStream.Send(&s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_ValidatePeerCertificateChainReq{ ValidatePeerCertificateChainReq: &s2av2pb.ValidatePeerCertificateChainReq{ Mode: verificationMode, PeerOneof: &s2av2pb.ValidatePeerCertificateChainReq_ClientPeer_{ ClientPeer: &s2av2pb.ValidatePeerCertificateChainReq_ClientPeer{ CertificateChain: rawCerts, }, }, }, }, }); err != nil { grpclog.Infof("Failed to send request to S2Av2 for client peer cert chain validation.") return err } // Get the response from S2Av2. resp, err := s2AStream.Recv() if err != nil { grpclog.Infof("Failed to receive client peer cert chain validation response from S2Av2.") return err } // Parse the response. if (resp.GetStatus() != nil) && (resp.GetStatus().Code != uint32(codes.OK)) { return fmt.Errorf("failed to offload client cert verification to S2A: %d, %v", resp.GetStatus().Code, resp.GetStatus().Details) } if resp.GetValidatePeerCertificateChainResp().ValidationResult != s2av2pb.ValidatePeerCertificateChainResp_SUCCESS { return fmt.Errorf("client cert verification failed: %v", resp.GetValidatePeerCertificateChainResp().ValidationDetails) } return nil } } // VerifyServerCertificateChain builds a SessionReq, sends it to S2Av2 and // receives a SessionResp. func VerifyServerCertificateChain(hostname string, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, s2AStream stream.S2AStream, serverAuthorizationPolicy []byte) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { // Offload verification to S2Av2. if grpclog.V(1) { grpclog.Infof("Sending request to S2Av2 for server peer cert chain validation.") } if err := s2AStream.Send(&s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_ValidatePeerCertificateChainReq{ ValidatePeerCertificateChainReq: &s2av2pb.ValidatePeerCertificateChainReq{ Mode: verificationMode, PeerOneof: &s2av2pb.ValidatePeerCertificateChainReq_ServerPeer_{ ServerPeer: &s2av2pb.ValidatePeerCertificateChainReq_ServerPeer{ CertificateChain: rawCerts, ServerHostname: hostname, SerializedUnrestrictedClientPolicy: serverAuthorizationPolicy, }, }, }, }, }); err != nil { grpclog.Infof("Failed to send request to S2Av2 for server peer cert chain validation.") return err } // Get the response from S2Av2. resp, err := s2AStream.Recv() if err != nil { grpclog.Infof("Failed to receive server peer cert chain validation response from S2Av2.") return err } // Parse the response. if (resp.GetStatus() != nil) && (resp.GetStatus().Code != uint32(codes.OK)) { return fmt.Errorf("failed to offload server cert verification to S2A: %d, %v", resp.GetStatus().Code, resp.GetStatus().Details) } if resp.GetValidatePeerCertificateChainResp().ValidationResult != s2av2pb.ValidatePeerCertificateChainResp_SUCCESS { return fmt.Errorf("server cert verification failed: %v", resp.GetValidatePeerCertificateChainResp().ValidationDetails) } return nil } } s2a-go-0.1.8/internal/v2/certverifier/certverifier_test.go000066400000000000000000000267231464711036600235450ustar00rootroot00000000000000/* * * 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 certverifier import ( "context" "errors" "fmt" "log" "net" "sync" "testing" "time" _ "embed" "github.com/google/s2a-go/internal/v2/fakes2av2" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( defaultTimeout = 10.0 * time.Second fakeServerAuthorizationPolicy = "fake server authorization policy" ) var ( //go:embed testdata/client_root_cert.der clientRootDERCert []byte //go:embed testdata/client_intermediate_cert.der clientIntermediateDERCert []byte //go:embed testdata/client_leaf_cert.der clientLeafDERCert []byte //go:embed testdata/server_root_cert.der serverRootDERCert []byte //go:embed testdata/server_intermediate_cert.der serverIntermediateDERCert []byte //go:embed testdata/server_leaf_cert.der serverLeafDERCert []byte ) func startFakeS2Av2Server(wg *sync.WaitGroup, enableServerAuthorizationPolicyCheck bool) (stop func(), address string, err error) { listener, err := net.Listen("tcp", ":0") if err != nil { log.Fatalf("Failed to listen on address %s: %v", address, err) } address = listener.Addr().String() s := grpc.NewServer() log.Printf("Server: started gRPC fake S2Av2 Server on address: %s", address) if enableServerAuthorizationPolicyCheck { s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ ServerAuthorizationPolicy: []byte(fakeServerAuthorizationPolicy), }) } else { s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{}) } go func() { wg.Done() if err := s.Serve(listener); err != nil { log.Printf("Failed to serve: %v", err) } }() return func() { s.Stop() }, address, nil } // TestVerifyClientCertChain runs unit tests for VerifyClientCertificateChain. func TestVerifyClientCertChain(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, false) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } for _, tc := range []struct { description string rawCerts [][]byte expectedErr error }{ { description: "empty chain", rawCerts: nil, expectedErr: errors.New("client cert verification failed: client peer verification failed: client cert chain is empty"), }, { description: "chain of length 1", rawCerts: [][]byte{clientRootDERCert}, expectedErr: nil, }, { description: "chain of length 2 correct", rawCerts: [][]byte{clientLeafDERCert, clientIntermediateDERCert}, expectedErr: nil, }, { description: "chain of length 2 error: missing intermediate", rawCerts: [][]byte{clientLeafDERCert, clientRootDERCert}, expectedErr: errors.New("failed to offload client cert verification to S2A: 3, client peer verification failed: x509: certificate signed by unknown authority (possibly because of \"crypto/rsa: verification error\" while trying to verify candidate authority certificate \"s2a_test_cert\")"), }, } { t.Run(tc.description, func(t *testing.T) { // Create new stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") // TODO(rmehta19): Add verificationMode to struct, and vary between tests. VerifyPeerCertificateFunc := VerifyClientCertificateChain(s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, cstream) got, want := VerifyPeerCertificateFunc(tc.rawCerts, nil), tc.expectedErr if want == nil { if got != nil { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } } else { if got == nil { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } if got.Error() != want.Error() { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } } }) } stop() } // TestVerifyServerCertChainWithServerAuthorizationPolicy runs unit tests for VerifyServerCertificateChain with server authorization policy check. func TestVerifyServerCertChainWithServerAuthorizationPolicy(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, true) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } for _, tc := range []struct { description string hostname string rawCerts [][]byte expectedErr error serverAuthorizationPolicy []byte }{ { description: "empty chain", hostname: "host", rawCerts: nil, expectedErr: errors.New("server cert verification failed: server peer verification failed: server cert chain is empty"), serverAuthorizationPolicy: []byte(fakeServerAuthorizationPolicy), }, { description: "invalid server authorization policy", hostname: "host", rawCerts: [][]byte{serverRootDERCert}, expectedErr: fmt.Errorf("rpc error: code = Unknown desc = server peer verification failed: invalid server authorization policy, expected: %s, got: ", fakeServerAuthorizationPolicy), serverAuthorizationPolicy: nil, }, { description: "chain of length 1", hostname: "host", rawCerts: [][]byte{serverRootDERCert}, expectedErr: nil, serverAuthorizationPolicy: []byte(fakeServerAuthorizationPolicy), }, { description: "chain of length 2 correct", hostname: "host", rawCerts: [][]byte{serverLeafDERCert, serverIntermediateDERCert}, expectedErr: nil, serverAuthorizationPolicy: []byte(fakeServerAuthorizationPolicy), }, } { t.Run(tc.description, func(t *testing.T) { // Create new stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") // TODO(rmehta19): Add verificationMode to struct, and vary between tests. VerifyPeerCertificateFunc := VerifyServerCertificateChain(tc.hostname, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, cstream, tc.serverAuthorizationPolicy) got, want := VerifyPeerCertificateFunc(tc.rawCerts, nil), tc.expectedErr if want == nil { if got != nil { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } } else { if got == nil { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } if got.Error() != want.Error() { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } } }) } stop() } // TestVerifyServerCertChainWithoutServerAuthorizationPolicy runs unit tests for VerifyServerCertificateChain without server authorization policy check. func TestVerifyServerCertChainWithoutServerAuthorizationPolicy(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, false) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } for _, tc := range []struct { description string hostname string rawCerts [][]byte expectedErr error serverAuthorizationPolicy []byte }{ { description: "empty chain", hostname: "host", rawCerts: nil, expectedErr: errors.New("server cert verification failed: server peer verification failed: server cert chain is empty"), serverAuthorizationPolicy: []byte(fakeServerAuthorizationPolicy), }, { description: "chain of length 1", hostname: "host", rawCerts: [][]byte{serverRootDERCert}, expectedErr: nil, serverAuthorizationPolicy: nil, }, { description: "chain of length 2 correct", hostname: "host", rawCerts: [][]byte{serverLeafDERCert, serverIntermediateDERCert}, expectedErr: nil, serverAuthorizationPolicy: nil, }, } { t.Run(tc.description, func(t *testing.T) { // Create new stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") VerifyPeerCertificateFunc := VerifyServerCertificateChain(tc.hostname, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, cstream, tc.serverAuthorizationPolicy) got, want := VerifyPeerCertificateFunc(tc.rawCerts, nil), tc.expectedErr if want == nil { if got != nil { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } } else { if got == nil { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } if got.Error() != want.Error() { t.Errorf("Peer certificate verification failed, got: %v, want: %v", got, want) } } }) } stop() } s2a-go-0.1.8/internal/v2/certverifier/testdata/000077500000000000000000000000001464711036600212655ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/certverifier/testdata/client_intermediate_cert.der000066400000000000000000000017461464711036600270160ustar00rootroot0000000000000000ʠMTկX̺0OYn0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220615213637Z 420615213637Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 þ|'_Pw 8ˈ 4tHcOh)2'.w5 u@l{)a xlAuaq|Ya>Wj|:4@U| k$Ow9yOL/a"'cgY!Lko|Z!"J4<-*U|?S# ɖ="^B8b96>м\qHbhwY+!97 o p׿bD0B0U#0@Sx lLJi%0 U00U 0domain0  *H  $ do|ڮ\m'[U\ɴ uT\)v0ckI95r5@27=vLh}av'Zj=t86*hd{&y) Fm̎=>&|R 6E<| !B;Fz?>R:5p+ZO{ O匉{nG8"rda:&^̀m,rqN|m_$ it[9cs2a-go-0.1.8/internal/v2/certverifier/testdata/client_intermediate_cert.pem000066400000000000000000000025771464711036600270300ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID4jCCAsqgAwIBAgIUTe5U1a+hWMy6E90wGQMdT1m8kG4wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNjE1MjEzNjM3WhcNNDIwNjE1MjEzNjM3WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAMO+fKYnXxZQ7Xff8wvzwzi8y4illQ00dEgbuGMH+k9oixSR/xAZKTLp 3Cf0Lnc14hUN6HX94tVAbHuQ9ylh6A67C3hsQdZ1YXG+j5V891kSYT4GV2rmz8x8 HNw6NEDhzlV8C2uE3CTztU93COk5eY9PA9FML/WcYf4iyifr5pvCAWNnWSFMa298 WiEX57AixBRKmjTs0jwtrf+isLgqvhGCVXy/0T8aE8fik1MjDfPJlq7hmwfQ677q qO89IvSWXkKbAurIxzhiOTbcGOyvPtC8Blxxvkiro71iaHepWarDKyE5tvc3qMYG IPmQGm8LcI7Xv/cWqaDLx8bg559i4/MCAwEAAaNEMEIwHwYDVR0jBBgwFoAUqEBT ie7SH+WueCBsga/Hh6PRaSUwDAYDVR0TBAUwAwEB/zARBgNVHREECjAIggZkb21h aW4wDQYJKoZIhvcNAQELBQADggEBAK4kgQqkqWRvzQ++if+TfKDarlzw+W2665Qn W+HmVc5cEJXzybQJ3nVUXCm8djBja0k5NQPz4/eecrY1QIKNMpfCN98fPfV2l4BM aIF9pcfQ1GF2J/MT7lqdaj3EdBzO68z+ODalKhK5ALUTG6+Oxmhke9jhJnmVKaH3 DUbEHm3Mjj2bPiYFfLVS38/inN0cpJ0LnQv12jZF/zz+fA0Fk8bNIehC4u4eO4xG eqA/PqSqUsj0Ot81cCtaq097jwnno0/WxsjljIl7bkeuksk4rraFIoNyHWTYYfM6 JohezYBt5o4OEixy5oRxg89OGnzO/uPCbd5fJLUUrQppdM5bOWM= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/certverifier/testdata/client_intermediate_key.pem000066400000000000000000000032171464711036600266530ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAw758pidfFlDtd9/zC/PDOLzLiKWVDTR0SBu4Ywf6T2iLFJH/ EBkpMuncJ/QudzXiFQ3odf3i1UBse5D3KWHoDrsLeGxB1nVhcb6PlXz3WRJhPgZX aubPzHwc3Do0QOHOVXwLa4TcJPO1T3cI6Tl5j08D0Uwv9Zxh/iLKJ+vmm8IBY2dZ IUxrb3xaIRfnsCLEFEqaNOzSPC2t/6KwuCq+EYJVfL/RPxoTx+KTUyMN88mWruGb B9Drvuqo7z0i9JZeQpsC6sjHOGI5NtwY7K8+0LwGXHG+SKujvWJod6lZqsMrITm2 9zeoxgYg+ZAabwtwjte/9xapoMvHxuDnn2Lj8wIDAQABAoIBAQCxOeHP6ivMn78x 3wFGnBDwaPd7JDhcuVZjBz4d49Y9WXE7Uah3IeDMaTLctdfwNUgaOfp0AkgDPo46 Hpm5zRx3YeDTymidzK9Kdfe4qGmnKt4Cc2lor8wK34Cd4ND4wbm4alRIqAVOK53I cgUObOxj1W2mbW2q2kla+JLCLHMiJ6A8IMf0ZmciZ0YcY9NStstJEX/QwCCxM0Wd 6lCVOnRu5+tMnEGLfipqTgKLy+Xkm9mbI+pNV6uo37TF1ugo7f62b4kpPnZSCcf5 sMB4+MAYdXJQ4uqFLg7UsplFchD/b+mPOmrRv39V6Sh4P+MmHayJcIAS8N81xNuM 06jCT+DhAoGBAPvoCfRERBNUJz/i3J7X+ro9u/Zr0ehjTo7WxTGMSOJPwB90K/dY GjiVQ/naH6yke9MM0t18Sgp/INKr74naxqjx98m4vvyo5o0H3R73hTe3S6yc3SOr rB8Z4xculgfH5rVi1cbRn8XnPTYxI2SjiZERSqOuaiIdjHIMZ1ptFEXxAoGBAMbs zla4YFzvcxOKQT1U1On+m66631OCHD+B+4bYIu3DbCXRY/LJ3a7IrLz9O51UJUO5 0HykrxS1UW8TENxbl2hc0N7x2eL+p5IpaPzXQZaKqX2crkf52mkSMndgZtJvIASo 8aNXneDjYbzv3WPuKkjm97cybe+t/lwKqh/KDpQjAoGBAM5YwO6qjOkYYh5fA0HK wcOVlkbBA21NC6jOHTH9LCbWFRau3uT58mCvRMOB/bg59IRpWMG9chkvEgAAf3N5 FoqFyugewbPN1y1nZ6ZaM3H0X7TBuhPiKFhBqFfw/UzaXw3uLBd012ARj364ublS jPmcJHv3/1B6y/UQXAkimRzBAoGAQDV7vN4yrIzV1j7QJB3Xw9fdJJ9JKslamN05 9SKa06g6plJaMqoaFirMJwyOS5A3nw7BTxpRMRv9tx6uWJJv4s3i1bO3IuAT8sfP DZ3lm9QSNWt3jeAGMdgf1gyV4+LesOJfbNwBJ+/9QmEiUvkzSOjUmJt8hNriuY7v rucnoYUCgYBXDa7ZR8QN/boJkfegYSba2w6Buy/GU4XrBt/El/Y9Xii0PkkEFkRp KRrcwIa202wXpK7N3OzyfgDIAtDyLMfsQIHxpVwEc7n36ryMrPv1IS1IJ6gFEGv2 9vdxI/DqT0928osv6hRX+EnfS4yXePLF/MWWgWwQB2eItrZ/Og7kmw== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/certverifier/testdata/client_leaf_cert.der000066400000000000000000000021731464711036600252460ustar00rootroot000000000000000w0_ZdRg[0T0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220615214113Z 420615214113Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 awߨ#Rmk i"~09ocQqʝCe` z8级sVxnMA#8m-jEe 3u"S!C i<$)]deuUЧdM6$~R5*`F\i#FJs(NPllQ14 ꩷uɵƔ:f)$3k pu f@c [00U#001 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.comMTկX̺0OYn0 U00U 0domain0  *H  #O[&mj7*.Hmuo24ЊCv{[aYXm%iN4:lL6!7㫸ڭIUXqiV /%Eqo{> ( Ζ۹k&ۙ4~;sjKfπqI 'Iu7ĉ$ ڙEsءzUs2a-go-0.1.8/internal/v2/certverifier/testdata/client_leaf_cert.pem000066400000000000000000000031121464711036600252470ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEdzCCA1+gAwIBAgIUDv1aq8fQZA6jA1Jnr1v6tjDsVOswDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNjE1MjE0MTEzWhcNNDIwNjE1MjE0MTEzWjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOThYZoVB3ffqIgSgqwTpSO8uf2rUvYbbWufqYEXggxp8f4CIn6RMO/g ObrWGm9jUd5xyp1DZZuxYIWKHQu2ehy1OP+C57qni8v5kPVzoFYYeG7/rU1B4u8j kKyjOG0Q2i0cauP1RWWg1QsPM5uRwnWRIghT+pAhzsriQwy6aeW+PCSDKeHjXb+B HWTZZXVV0KdkTYo2jdJ/6/ir0iR+Up41gCoR3WCGxAOaRlym95dpI4G7E7+IRtzr tvVKc9kouk5Qqfz9mamxbGyu1QHExVGoMTS0IOqpt4KwdRjJtf+vxpS4OvwPZu4p s+0kATNrCqHIcKwQdZ2uDBtmQGMEClsCAwEAAaOB2DCB1TCBsQYDVR0jBIGpMIGm oYGNpIGKMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVN1 bm55dmFsZTEQMA4GA1UECgwHQ29tcGFueTERMA8GA1UECwwIRGl2aXNpb24xFjAU BgNVBAMMDXMyYV90ZXN0X2NlcnQxGjAYBgkqhkiG9w0BCQEWC3h5ekB4eXouY29t ghRN7lTVr6FYzLoT3TAZAx1PWbyQbjAMBgNVHRMEBTADAQH/MBEGA1UdEQQKMAiC BmRvbWFpbjANBgkqhkiG9w0BAQsFAAOCAQEAI81PW+0mbcZqFzcEKtrpLq1IwBtt x3US/vXBnNvzbwcyNIug0IpDqHZ7nvDwiFv/YVme8ckC/aFYbfIlhWlOusw0FcDW OqOYbJkBFvlMlcTz/jYhN+OruPHaredJlFXylFj/F/tx4WlWIIH/5dYvqyUUReCY cW977T4duKweugkoFwzOlqIAH9PbuWsmlYzbmTTqmgD9fjuAHHOgv2qQPERWdEoy vs1/uTkAsdxsyHV24Eh9xqvU2i+GviBt9QLYNTQibzyu6V97bz9Rw/pf6kcJkxyJ fUCO6liI0g8CPktmz4BxSSDvJwjDz0l1gfv91DefxIkkINqZ2kVz2KF6VQ== -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/certverifier/testdata/client_leaf_key.pem000066400000000000000000000032171464711036600251100ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA5OFhmhUHd9+oiBKCrBOlI7y5/atS9htta5+pgReCDGnx/gIi fpEw7+A5utYab2NR3nHKnUNlm7FghYodC7Z6HLU4/4LnuqeLy/mQ9XOgVhh4bv+t TUHi7yOQrKM4bRDaLRxq4/VFZaDVCw8zm5HCdZEiCFP6kCHOyuJDDLpp5b48JIMp 4eNdv4EdZNlldVXQp2RNijaN0n/r+KvSJH5SnjWAKhHdYIbEA5pGXKb3l2kjgbsT v4hG3Ou29Upz2Si6TlCp/P2ZqbFsbK7VAcTFUagxNLQg6qm3grB1GMm1/6/GlLg6 /A9m7imz7SQBM2sKochwrBB1na4MG2ZAYwQKWwIDAQABAoIBAByJSSz30D2O4ilM /YPM0zsYbawF70sF8meHuY+BydIYZ3Z+96QGIC7YKvpzdUpL/MoaL+PZolJ+FAWy SZrLPoBTy+53eMLZ3uEolX001FnHpURZllbajxu3uHL9yqw2fK1BLMaNLwDTw5wk Yg/UZYVY+gBF0CimPm0nNqrglxFwoQ4npSMNoN4alLTqELiVd4qmBbp++UoGS62q dJeHy4VyuBleUTyDs6g5iiwjyPHY39FzPVGcMLR7K50gKpp3u8KUhtXzkVOh2N7r B25rRgszUFXlPlPDhjwREoCmjZsn8Rhnv/CTS1Fy2/xFvt6XSHwSf+Rnu0UkPBqu /KW+3skCgYEA/Ne00cubD12wUHE1EhVp7aXZ6Mj99HpyUdNZPiYCk7RmaZralKxN tu5/lQlqMnOiDNkEKS101TA0YQCBrfWWT2iyuAXJYUXX95ljEOLJ3iL9aWP7JxZz 3L5wy8Czuo3RS9x2jIYSwg9K9GxU7XbZ+MA/QK//uDCUfP3/TtyED3UCgYEA570S amy66jo7PFDDQpe2/0suNT3kzBFahwERt13PNUWJXGxdFKtrxP5iNRRDyRFMaNQK 44an4JAdkEixmNjwvvpJNwi0elWGqnhg5zJqBGYMQ4A3gxY6Xb14wkKneN6BY55R 5lgPIdrywSjXgCEBwzsUE2oT8iCzYhiDAUr8yI8CgYEAnzNuzh5mXvF939i4Ms+6 6ADiyTks9i/XJYBvE7u5KamQRnRTpwMq18EqIfxQmr3GTlKi1Q6jHs0AXgeEn7Uf 1JY22boDB7WDe4pgHzS9KJpdd2uVqxHvGBHtUc3fHNrI6vxAxNBypTAd4PMJMpAA RSk/aoqm+CHWjTEc/VnJ6TUCgYAOj6zWjxp3mU0bjx+V0Z6oD/tJUShNQlHj5cdN NFHO0R2+dviqUdMlv65AE5Pm0HVyqNA+V7m4vJV++XJfXlJSTbvH/34HqdQaZhIA tQRAXoEqxKW4UO898Kfj3PhU+fY7YjlXNfVNdUqHpJ9V570KnW23gpTaQ//BjDS/ Ig0cNQKBgQDANW1GIXJC0LaNLm7E03vVgRzE4Ww2zHZbxJE309PSsL4zkHkSwLHX WOnesAYGgItB/oxyb4ySVtE+WyqCGxEeyefjPbylUDqBSaf3/A++dwkB+VaEtZ/C H9nK6uVAcp1Pw55Rtaooe+oPv5j9+RFw+ctb5J4MZTR2+izprsQN1Q== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/certverifier/testdata/client_root_cert.der000066400000000000000000000017651464711036600253300ustar00rootroot0000000000000000٠)se^G"Od0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220531200315Z 420526200315Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 ㅸ~Fħw@?-nGt"a/}zr߄ C1S/-Mi#GS0Q0U@Sx lLJi%0U#0@Sx lLJi%0U00  *H  O6sC$zr WS}'}"JVeõp=Ւ?X=kIQ+ӜFXL7fLe Hz'Cbg@B'3K.q+p?OP\Pnw )exRPYhL5-@3)DZD>,uÞv\C_m+elFl80~oY}O)Vcݰb7(%W=s2a-go-0.1.8/internal/v2/certverifier/testdata/client_root_cert.pem000066400000000000000000000026241464711036600253320ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu 0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 /P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco pKklVz0= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/certverifier/testdata/client_root_key.pem000066400000000000000000000032131464711036600251600ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj +Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G 4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh 68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ /+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx 2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm 56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/certverifier/testdata/domain.ext000066400000000000000000000001641464711036600232570ustar00rootroot00000000000000authorityKeyIdentifier=keyid,issuer basicConstraints=CA:TRUE subjectAltName = @alt_names [alt_names] DNS.1 = domain s2a-go-0.1.8/internal/v2/certverifier/testdata/server_intermediate_cert.der000066400000000000000000000017461464711036600270460ustar00rootroot0000000000000000ʠ0X迖ȜfvتU0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220615215158Z 420615215158Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 W* (fp/)Ei^/n.筏\s7ɮаiCKUi|`:7WI[%!EX%mrϢ+2:kIɭޱ u*4PJ_4\#M3UrXI ]Mm3l`3K>92zd CvkKǸHcq?9FƠ=g_\G.{Qv^TF,1D0B0U#0 A iQ +UTTY0 U00U 0domain0  *H  8'@OjQ֑S=˻MBOJuv9IX 6~ x!/ASl \{{h'ˆoS{q.3P;bRsqs95'VB#O6^-tt]KnXY&j&Ain'K\"fo@b/HV!f"KSb)g/D) % y]|2<1by 0Y-s2a-go-0.1.8/internal/v2/certverifier/testdata/server_intermediate_cert.pem000066400000000000000000000025771464711036600270600ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID4jCCAsqgAwIBAgIUMH/0WOi/luXSyJyOZnaS2KpViZUwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNjE1MjE1MTU4WhcNNDIwNjE1MjE1MTU4WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAK5X4SoJ+ihmcBKCLylFsmn3Xi9uLvcd2uetj7lcAqTxznM3ya6y0LBp Q0tVabB8sGDYOss3V5hJWx6f+qjr2iXjl/Ie1iFFWL+jJeBtcs+irrEruvsyOhJr q0nJrRGHFPTese0clgoDdcECKqUbHY2t/jS7k1D0BKLCGUr02dFfGjS4XCP/0ORN vzOIVZuRCHKO+OqRGYYOzViuSQqMXfeNTQWLbTNs6GDO5O7KMwO1qks+OTIe8Hpk pgxDEnafymuCo0ub7ce4hR0YSMC/yuNjEnE/f6mG7p3G6qc5p0bGoMsEPWeCxl/F XKlHqIcue6hREBn5dl6eVEbnHh8skTECAwEAAaNEMEIwHwYDVR0jBBgwFoAUDJBB C4xpv5hRCqMrx1VU6gdUWZcwDAYDVR0TBAUwAwEB/zARBgNVHREECjAIggZkb21h aW4wDQYJKoZIhvcNAQELBQADggEBADgnk/NA509qoVES6/zWkR8WmVObupE9x8u7 TRfx00KUT9nv8YbdSvt1dtzp5OA5SVgMNsp+rQmzeM7PwJkhL0FTl2zrmQj6CQxc 93uOuHuArZykaCccy4a6l7zcH85vU3sVqh/u5MVx3RcuGzMei/1Q5Mw7D2IXUq+o 3xjU3RPrc7zJ8nHrc8U5NZ0nVsC1QiNPNl6w4y0WjaC+dHRdS4JujVhZJmrvoA+z Jpu/ja1BaW4nS1zW5SJm977stQS37gFvAO9A7GKenC9IVvUQIWayld/p0CIZS5Kz U2KWGSlnkC9E6xoT5sopCyW2CXm9Xdp8MjzHMeBiedALMMdZ3y0= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/certverifier/testdata/server_intermediate_key.pem000066400000000000000000000032171464711036600267030ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEArlfhKgn6KGZwEoIvKUWyafdeL24u9x3a562PuVwCpPHOczfJ rrLQsGlDS1VpsHywYNg6yzdXmElbHp/6qOvaJeOX8h7WIUVYv6Ml4G1yz6KusSu6 +zI6EmurScmtEYcU9N6x7RyWCgN1wQIqpRsdja3+NLuTUPQEosIZSvTZ0V8aNLhc I//Q5E2/M4hVm5EIco746pEZhg7NWK5JCoxd941NBYttM2zoYM7k7sozA7WqSz45 Mh7wemSmDEMSdp/Ka4KjS5vtx7iFHRhIwL/K42MScT9/qYbuncbqpzmnRsagywQ9 Z4LGX8VcqUeohy57qFEQGfl2Xp5URuceHyyRMQIDAQABAoIBAGQ8FDFmQRPfKUoK 3PB+qL/xv43HbGsZGBUhHUO1mbOZbleh2Gt/VSpHqq/yMGyOk51qVAsoC017x06J LcTWrLoh6ucCQZwpUYgEVa99XYfxATzNZpgrXWXfz0ACGmW8YxkRu/wV9lFVgerw wvHf8BLX2RIaUe02DkBBFeeZdG3BqxO/ACRLovRjBVAUlkZLxwTHPAkPKzYwYSDx +BOJ9qpilghgVwHWCwlFtewCNL9fqEQygNi03yaWmVRhddhunbs5If1wNhXbeDtV G/KlDLMRs3Q3vBCD+JUBgrIWJG9zA0H9eGhSbqoqcKv5MWM8mKSsUpEKGNIIO/uk buXwPhECgYEA5IYUVJflioQM8/kZztoGUfX7uHTBJ0Z7EIHEAwQoo0a9AtII/MIt Ve8UnCyogfJgVQ2H9zEStJKoLrZ5Oqzxj9Xeb9cKiO/U6dxI8b434ThLT7QeoGXr KRLNxF6rMO9UrwsqFqACV4Ebw0S0d5dDbqaRXY+ASu23beTn6w5alUUCgYEAw04i iDimikp/hTFNDHzdiE1r5p43Wkr3jnCBRLsI0G/Ix4VpWHNjXyp/pg1IIpax00no vtjERTsHRy1+RqE0RW3h6V37h6gRRtYMvokLDz8Ww+M3MjFdn8YcETCnzR0Q5ALu +R3dQ0fbX/cWNy2cJLQLGuJi3zjv/ZKGeBJ9nP0CgYEApKkPwRxp4vLfOnRE6k0i vK/XnsNR4fDg/7Xg/KNkfLGdw4h/vVBUxlSsrxNmn6t7Sg2j6LNNXRtHX9FPbL3s mM1rp351MtJMwe1eCgIb1YZwjY+lecG2PjQ0W8gy5eGtTStoOkE1LsPyszKwLnOp vPL8T0P1FwhOYTrM+QuwrVkCgYEAlX1R+zh5aPKa5uUUl5Ffs7um8m956Nfm4pUE rQoINhrJ8MYSG0y+7BHIgN47r5Xu6M3yo1mh6WfEK1wMAp3TN61itNBl/bDMAI9I U/LrjzD4CNn63qVghzIJO7MlTV+JFS2VowKT4LK4nJyw2W1EzectdNeBXGDleQ7V dESa9zUCgYAT1YG0D8C0TmM5xSvhOme4K3El8f7fxSbIjF+TC8fbXuGGqvA7n3EL rYGNivz94ZhedOfURaCPWbkucaiTDeVz90BCnzcvH++eSmFeBRz3H+vYlimhyy3Y 6qkfc6/vpSmacqAEWrXdu5ZXh8shWeS3raO4zEcj8wsgup3l0Xeuyg== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/certverifier/testdata/server_leaf_cert.der000066400000000000000000000021731464711036600252760ustar00rootroot000000000000000w0_)P z\DL~>0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220615220039Z 420615220039Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 &:}uIG vV`p//Y0|0w3-wڌW2G/$1d<^ hp/u$nA\ϨӄMfᗽ4Cřv%hfw3: GPr &&R 2MBqe@^uZGy5eKd@`Vob'ɾ2yѪ[8VCc ?U?00U#001 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0X迖ȜfvتU0 U00U 0domain0  *H  kiGgLCyД?;z/%F Bgf~뛄[P@X*uW R njI9$H=59FdZ鷟-rA(&? ̋ea!s=t喺7^Su`0"HKå9nx;3>f=gR8&Q~1Ɨrdc 1 ~m4̛RC#D~zT s2a-go-0.1.8/internal/v2/certverifier/testdata/server_leaf_cert.pem000066400000000000000000000031121464711036600252770ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEdzCCA1+gAwIBAgIUKRfziVAbC9B6XOi25UTmHUz6fj4wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNjE1MjIwMDM5WhcNNDIwNjE1MjIwMDM5WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAMCIJro63RfCfXWLSUfs6Q0D5HbrVmBwL4EvkxSxDg+rWbMw9al8sMPn vjATrbW1d6kzLXeRwJTD2oxX+DJHE+eiLyQeMb/nxxrKZLC3vu2ZPLbKGl6MCtxo cM4vwYB1vum84dLbJG5BrQMfXOvPqNOE7aDkmE2GZo3hl700Q9vQxZmqHgH0diUb aGb+d72OM7r7z8c6DbhHUHLbDSb4JlIWue8J0umZADL53U1CmJHm5nESiGW30kBe 9XVaR3mQ3xcI5qfwGsA1ZUuH86FkQOPVE2BWuprUb6liqfmnJ8m+MheC5nnRqvFb hJY41lZD3vNjtb4gPxrK1fnwjRyfVT8CAwEAAaOB2DCB1TCBsQYDVR0jBIGpMIGm oYGNpIGKMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCVN1 bm55dmFsZTEQMA4GA1UECgwHQ29tcGFueTERMA8GA1UECwwIRGl2aXNpb24xFjAU BgNVBAMMDXMyYV90ZXN0X2NlcnQxGjAYBgkqhkiG9w0BCQEWC3h5ekB4eXouY29t ghQwf/RY6L+W5dLInI5mdpLYqlWJlTAMBgNVHRMEBTADAQH/MBEGA1UdEQQKMAiC BmRvbWFpbjANBgkqhkiG9w0BAQsFAAOCAQEAa2n8FdRHlGdMvQGqQ4V5E9CUjz8X O4UEjXovJbUbRg3hBIeN+abRQsEBjmfMZn60+rTT65uEklvSGFAb0R5AEVjKKnVX CexSgQrHjKZJ9jnWJOpIt+XWzT2u1x81OR7vRmSkhfmiWum3ny1yQSgmij+2HLy/ C8yLZRXZFNDP3+SOYZL8xCFzPXTllroGN8HM5F5TdeUUmO5gMCJIS8Olp/k5q26H A6F4HfY7hDOB9j6UZj1nwIFSONkbAyaiuabcEQOwxlGwt34xxpdyi69kos5/Y6fX ydjV4qwOAwox+AzFfvmN422c9uk0BcybolK4vvdD4iPjAkTDfst6gFTUCQ== -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/certverifier/testdata/server_leaf_key.pem000066400000000000000000000032171464711036600251400ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA5OFhmhUHd9+oiBKCrBOlI7y5/atS9htta5+pgReCDGnx/gIi fpEw7+A5utYab2NR3nHKnUNlm7FghYodC7Z6HLU4/4LnuqeLy/mQ9XOgVhh4bv+t TUHi7yOQrKM4bRDaLRxq4/VFZaDVCw8zm5HCdZEiCFP6kCHOyuJDDLpp5b48JIMp 4eNdv4EdZNlldVXQp2RNijaN0n/r+KvSJH5SnjWAKhHdYIbEA5pGXKb3l2kjgbsT v4hG3Ou29Upz2Si6TlCp/P2ZqbFsbK7VAcTFUagxNLQg6qm3grB1GMm1/6/GlLg6 /A9m7imz7SQBM2sKochwrBB1na4MG2ZAYwQKWwIDAQABAoIBAByJSSz30D2O4ilM /YPM0zsYbawF70sF8meHuY+BydIYZ3Z+96QGIC7YKvpzdUpL/MoaL+PZolJ+FAWy SZrLPoBTy+53eMLZ3uEolX001FnHpURZllbajxu3uHL9yqw2fK1BLMaNLwDTw5wk Yg/UZYVY+gBF0CimPm0nNqrglxFwoQ4npSMNoN4alLTqELiVd4qmBbp++UoGS62q dJeHy4VyuBleUTyDs6g5iiwjyPHY39FzPVGcMLR7K50gKpp3u8KUhtXzkVOh2N7r B25rRgszUFXlPlPDhjwREoCmjZsn8Rhnv/CTS1Fy2/xFvt6XSHwSf+Rnu0UkPBqu /KW+3skCgYEA/Ne00cubD12wUHE1EhVp7aXZ6Mj99HpyUdNZPiYCk7RmaZralKxN tu5/lQlqMnOiDNkEKS101TA0YQCBrfWWT2iyuAXJYUXX95ljEOLJ3iL9aWP7JxZz 3L5wy8Czuo3RS9x2jIYSwg9K9GxU7XbZ+MA/QK//uDCUfP3/TtyED3UCgYEA570S amy66jo7PFDDQpe2/0suNT3kzBFahwERt13PNUWJXGxdFKtrxP5iNRRDyRFMaNQK 44an4JAdkEixmNjwvvpJNwi0elWGqnhg5zJqBGYMQ4A3gxY6Xb14wkKneN6BY55R 5lgPIdrywSjXgCEBwzsUE2oT8iCzYhiDAUr8yI8CgYEAnzNuzh5mXvF939i4Ms+6 6ADiyTks9i/XJYBvE7u5KamQRnRTpwMq18EqIfxQmr3GTlKi1Q6jHs0AXgeEn7Uf 1JY22boDB7WDe4pgHzS9KJpdd2uVqxHvGBHtUc3fHNrI6vxAxNBypTAd4PMJMpAA RSk/aoqm+CHWjTEc/VnJ6TUCgYAOj6zWjxp3mU0bjx+V0Z6oD/tJUShNQlHj5cdN NFHO0R2+dviqUdMlv65AE5Pm0HVyqNA+V7m4vJV++XJfXlJSTbvH/34HqdQaZhIA tQRAXoEqxKW4UO898Kfj3PhU+fY7YjlXNfVNdUqHpJ9V570KnW23gpTaQ//BjDS/ Ig0cNQKBgQDANW1GIXJC0LaNLm7E03vVgRzE4Ww2zHZbxJE309PSsL4zkHkSwLHX WOnesAYGgItB/oxyb4ySVtE+WyqCGxEeyefjPbylUDqBSaf3/A++dwkB+VaEtZ/C H9nK6uVAcp1Pw55Rtaooe+oPv5j9+RFw+ctb5J4MZTR2+izprsQN1Q== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/certverifier/testdata/server_root_cert.der000066400000000000000000000017651464711036600253600ustar00rootroot0000000000000000٠(*be{6F"̟0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220531200825Z 420526200825Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 C76 AcΓL.vy>Z(4jS~_/LKυjNd|X< :TوRvA3TI>D,r<EުȚ\=«ϓ`\*x^d_2&ƫۣ }uS}QR9Ճ)EvG뇬; K.zWHMyE(ٌ'  ŋIdKyԦ\Bx%قuXۨIS0Q0U A iQ +UTTY0U#0 A iQ +UTTY0U00  *H  8hbr{Y3 D%^ +X]#|9뜚YÈ=g*.ϗ<=t!> '}"d+>Y=hD(|{J蒬eVSOXHvK\K ܘΒjUvMw}lPsz& ; %2_E%xju]adJI) ֮='稻P~Di !UAEP7J彇Ϭ& s2a-go-0.1.8/internal/v2/certverifier/testdata/server_root_cert.pem000066400000000000000000000026241464711036600253620ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKCoDuLtiZXvhsBY2RoDm0ugizJ8wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwODI1WhcNNDIwNTI2MjAwODI1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKK1++PXQ+M3hjYH/v0K4UEYl5ljzpNM1i52eQM+gFooojT87PDSaphT fs0PXy/PTAjHBEvPhWpOpmQXfJNYzjwcCvg66hbqkv++/VTZiFLAsHagzkEz+FRJ qT5Eq7G5FLyw1izX1uxyPN7tAEWEEg7eqsiaXD3Cq8+TYN9cjirPeF7RZF8yFCYE xqvbo+Yc6RL6xw19iXVTfctRgQe581KQuIY5/LXo3dWDEilFdsADAe8XAEcO64es Ow0g1UvXLnpXSE151kXBFb3sKH/ZjCecDYMCIMEb4sWLSblkSxJ5sNSmXIG4wtr2 Qnii7CXZgnVYraQE/Jyh+NMQANuoSdMCAwEAAaNTMFEwHQYDVR0OBBYEFAyQQQuM ab+YUQqjK8dVVOoHVFmXMB8GA1UdIwQYMBaAFAyQQQuMab+YUQqjK8dVVOoHVFmX MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADj0vQ6ykWhicoqR e6VZMwlEJV7/DSvWWKBd9MUjfKye0A4565ya5lmnzP3DiD3nqGe3miqmLsXKDs+X POqlPXTWIamP7D4MJ32XtSLwZB4ru+I+Ao/P/VngPepoRPQoBnzHe7jww0rokqxl AZERjlbTUwUAy/BPWPSzSJZ2j0tcs6ZLDNyYzpK4ao8R9/1VmQ92Tcp3feJs1QTg odRQc3om/AkWOwsll+oyX0UbJeHkFHiLanUPXbdh+/BkSvZJ8ynL+feSDdaurPe+ PSfnqLtQft9/neecGRdEaQzzzSFVQUVQzTdK1Q7hA7b55b2HvIa3ktDiks+sJsYN Dhm6uZM= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/certverifier/testdata/server_root_key.pem000066400000000000000000000032171464711036600252140ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAorX749dD4zeGNgf+/QrhQRiXmWPOk0zWLnZ5Az6AWiiiNPzs 8NJqmFN+zQ9fL89MCMcES8+Fak6mZBd8k1jOPBwK+DrqFuqS/779VNmIUsCwdqDO QTP4VEmpPkSrsbkUvLDWLNfW7HI83u0ARYQSDt6qyJpcPcKrz5Ng31yOKs94XtFk XzIUJgTGq9uj5hzpEvrHDX2JdVN9y1GBB7nzUpC4hjn8tejd1YMSKUV2wAMB7xcA Rw7rh6w7DSDVS9cueldITXnWRcEVvewof9mMJ5wNgwIgwRvixYtJuWRLEnmw1KZc gbjC2vZCeKLsJdmCdVitpAT8nKH40xAA26hJ0wIDAQABAoIBACaNR+lsD8G+XiZf LqN1+HkcAo9tfnyYMAdCOtnx7SdviT9Uzi8hK/B7mAeuJLeHPlS2EuaDfPD7QaFl jza6S+MiIdc+3kgfvESsVAnOoOY6kZUJ9NSuI6CU82y1iJjLaYZrv9NQMLRFPPb0 4KOX709mosB1EnXvshW0rbc+jtDFhrm1SxMt+k9TuzmMxjbOeW4LOLXPgU8X1T3Q Xy0hMZZtcgBs9wFIo8yCtmOixax9pnFE8rRltgDxTodn9LLdz1FieyntNgDksZ0P nt4kV7Mqly7ELaea+Foaj244mKsesic2e3GhAlMRLun/VSunSf7mOCxfpITB8dp1 drDhOYECgYEA19151dVxRcviuovN6Dar+QszMTnU8pDJ8BjLFjXjP/hNBBwMTHDE duMuWk2qnwZqMooI/shxrF/ufmTgS0CFrh2+ANBZu27vWConJNXcyNtdigI4wt50 L0Y2qcZn2mg67qFXHwoR3QNwrwnPwEjRXA09at9CSRZzcwDQ0ETXhYsCgYEAwPaG 06QdK8Zyly7TTzZJwxzv9uGiqzodmGtX6NEKjgij2JaCxHpukqZBJoqa0jKeK1cm eNVkOvT5ff9TMzarSHQLr3pZen2/oVLb5gaFkbcJt/klv9Fd+ZRilHY3i6QwS6pD uMiPOWS4DrLHDRVoVlAZTDjT1RVwwTs+P2NhJdkCgYEAsriXysbxBYyMp05gqEW7 lHIFbFgpSrs9th+Q5U6wW6JEgYaHWDJ1NslY80MiZI93FWjbkbZ7BvBWESeL3EIL a+EMErht0pVCbIhZ6FF4foPAqia0wAJVx14mm+G80kNBp5jE/NnleEsE3KcO7nBb hg8gLn+x7bk81JZ0TDrzBYkCgYEAuQKluv47SeF3tSScTfKLPpvcKCWmxe1uutkQ 7JShPhVioyOMNb39jnYBOWbjkm4d4QgqRuiytSR0oi3QI+Ziy5EYMyNn713qAk9j r2TJZDDPDKnBW+zt4YI4EohWMXk3JRUW4XDKggjjwJQA7bZ812TtHHvP/xoThfG7 eSNb3eECgYBw6ssgCtMrdvQiEmjKVX/9yI38mvC2kSGyzbrQnGUfgqRGomRpeZuD B5E3kysA4td5pT5lvcLgSW0TbOz+YbiriXjwOihPIelCvc9gE2eOUI71/byUWPFz 7u5F/xQ4NaGr5suLF+lBC6h7pSbM4El9lIHQAQadpuEdzHqrw+hs3g== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/fakes2av2/000077500000000000000000000000001464711036600165475ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/fakes2av2/fakes2av2.go000066400000000000000000000370211464711036600206650ustar00rootroot00000000000000/* * * 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 fakes2av2 is a fake S2Av2 Go implementation. package fakes2av2 import ( "bytes" "crypto" "crypto/rand" "crypto/rsa" "crypto/tls" "crypto/x509" "errors" "fmt" "log" "time" "google.golang.org/grpc/codes" _ "embed" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2ctx "github.com/google/s2a-go/internal/proto/v2/s2a_context_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) var ( //go:embed testdata/client_root_cert.pem clientCert []byte //go:embed testdata/client_root_cert.der clientDERCert []byte //go:embed testdata/client_root_key.pem clientKey []byte //go:embed testdata/server_root_cert.pem serverCert []byte //go:embed testdata/server_root_cert.der serverDERCert []byte //go:embed testdata/server_root_key.pem serverKey []byte ) // Server is a fake S2A Server for testing. type Server struct { s2av2pb.UnimplementedS2AServiceServer // ExpectedToken is the token S2Av2 expects to be attached to the SessionReq. ExpectedToken string // ShouldNotReturnClientCredentials indicates whether the fake S2Av2 should // not return credentials when GetTlsConfiguration is called by a client. ShouldNotReturnClientCredentials bool isAssistingClientSide bool ServerAuthorizationPolicy []byte // TODO(rmehta19): Decide whether to also store validationResult (bool). // Set this after validating token attached to first SessionReq. Check // this field before completing subsequent SessionReq. } // SetUpSession receives SessionReq, performs request, and returns a // SessionResp, all on the server stream. func (s *Server) SetUpSession(stream s2av2pb.S2AService_SetUpSessionServer) error { for { req, err := stream.Recv() if err != nil { log.Printf("Fake S2A Service: failed to receive SessionReq: %v", err) return err } // Call one of the 4 possible RespOneof's // TODO(rmehta19): Consider validating the body of the request. var resp *s2av2pb.SessionResp switch x := req.ReqOneof.(type) { case *s2av2pb.SessionReq_GetTlsConfigurationReq: if err := s.hasValidToken(req.GetAuthenticationMechanisms()); err != nil { log.Printf("Fake S2A Service: authentication error: %v", err) return err } if err := s.findConnectionSide(req); err != nil { resp = &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.InvalidArgument), Details: err.Error(), }, } break } resp, err = getTLSConfiguration(req.GetGetTlsConfigurationReq(), s.ShouldNotReturnClientCredentials) if err != nil { log.Printf("Fake S2A Service: failed to build SessionResp with GetTlsConfigurationResp: %v", err) return err } case *s2av2pb.SessionReq_OffloadPrivateKeyOperationReq: resp, err = offloadPrivateKeyOperation(req.GetOffloadPrivateKeyOperationReq(), s.isAssistingClientSide) if err != nil { log.Printf("Fake S2A Service: failed to build SessionResp with OffloadPrivateKeyOperationResp: %v", err) return err } case *s2av2pb.SessionReq_OffloadResumptionKeyOperationReq: // TODO(rmehta19): Implement fake. case *s2av2pb.SessionReq_ValidatePeerCertificateChainReq: resp, err = validatePeerCertificateChain(req.GetValidatePeerCertificateChainReq(), s.ServerAuthorizationPolicy) if err != nil { log.Printf("Fake S2A Service: failed to build SessionResp with ValidatePeerCertificateChainResp: %v", err) return err } default: return fmt.Errorf("SessionReq.ReqOneof has unexpected type %T", x) } if err := stream.Send(resp); err != nil { log.Printf("Fake S2A Service: failed to send SessionResp: %v", err) return err } } } func (s *Server) findConnectionSide(req *s2av2pb.SessionReq) error { switch connSide := req.GetGetTlsConfigurationReq().GetConnectionSide(); connSide { case commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT: s.isAssistingClientSide = true case commonpb.ConnectionSide_CONNECTION_SIDE_SERVER: s.isAssistingClientSide = false default: return fmt.Errorf("unknown ConnectionSide: %v", connSide) } return nil } func (s *Server) hasValidToken(authMechanisms []*s2av2pb.AuthenticationMechanism) error { if len(authMechanisms) == 0 { return nil } for _, v := range authMechanisms { token := v.GetToken() if token == s.ExpectedToken { return nil } } return errors.New("SessionReq has no AuthenticationMechanism with a valid token") } func offloadPrivateKeyOperation(req *s2av2pb.OffloadPrivateKeyOperationReq, isAssistingClientSide bool) (*s2av2pb.SessionResp, error) { switch x := req.GetOperation(); x { case s2av2pb.OffloadPrivateKeyOperationReq_SIGN: var root tls.Certificate var err error // Retrieve S2Av2 implementation of crypto.Signer. if isAssistingClientSide { root, err = tls.X509KeyPair(clientCert, clientKey) if err != nil { return nil, err } } else { root, err = tls.X509KeyPair(serverCert, serverKey) if err != nil { return nil, err } } var signedBytes []byte if req.GetSignatureAlgorithm() == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256 { signedBytes, err = root.PrivateKey.(crypto.Signer).Sign(rand.Reader, req.GetSha256Digest(), crypto.SHA256) if err != nil { return nil, err } } else if req.GetSignatureAlgorithm() == s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256 { opts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256} signedBytes, err = root.PrivateKey.(crypto.Signer).Sign(rand.Reader, req.GetSha256Digest(), opts) if err != nil { return nil, err } } else { return &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.InvalidArgument), Details: fmt.Sprintf("invalid signature algorithm: %v", req.GetSignatureAlgorithm()), }, }, nil } return &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_OffloadPrivateKeyOperationResp{ OffloadPrivateKeyOperationResp: &s2av2pb.OffloadPrivateKeyOperationResp{ OutBytes: signedBytes, }, }, }, nil case s2av2pb.OffloadPrivateKeyOperationReq_DECRYPT: return nil, errors.New("decrypt operation not implemented yet") default: return nil, fmt.Errorf("unspecified private key operation requested: %d", x) } } func validatePeerCertificateChain(req *s2av2pb.ValidatePeerCertificateChainReq, serverAuthorizationPolicy []byte) (*s2av2pb.SessionResp, error) { switch x := req.PeerOneof.(type) { case *s2av2pb.ValidatePeerCertificateChainReq_ClientPeer_: return verifyClientPeer(req) case *s2av2pb.ValidatePeerCertificateChainReq_ServerPeer_: return verifyServerPeer(req, serverAuthorizationPolicy) default: err := fmt.Errorf("peer verification failed: invalid Peer type %T", x) return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), err.Error(), s2av2pb.ValidatePeerCertificateChainResp_FAILURE, err.Error(), &s2av2ctx.S2AContext{}), err } } // TODO(rmehta19): Update this to return ciphersuites in Client/Server TlsConfiguration. func getTLSConfiguration(req *s2av2pb.GetTlsConfigurationReq, shouldNotReturnClientCredentials bool) (*s2av2pb.SessionResp, error) { if req.GetConnectionSide() == commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT { if shouldNotReturnClientCredentials { return &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_GetTlsConfigurationResp{ GetTlsConfigurationResp: &s2av2pb.GetTlsConfigurationResp{ TlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration_{ ClientTlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration{ MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, }, }, }, }, }, nil } return &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_GetTlsConfigurationResp{ GetTlsConfigurationResp: &s2av2pb.GetTlsConfigurationResp{ TlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration_{ ClientTlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration{ CertificateChain: []string{ string(clientCert), }, MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, }, }, }, }, }, nil } else if req.GetConnectionSide() == commonpb.ConnectionSide_CONNECTION_SIDE_SERVER { return &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_GetTlsConfigurationResp{ GetTlsConfigurationResp: &s2av2pb.GetTlsConfigurationResp{ TlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_{ ServerTlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ CertificateChain: []string{ string(serverCert), }, MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, TlsResumptionEnabled: false, RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, MaxOverheadOfTicketAead: 0, }, }, }, }, }, nil } return nil, fmt.Errorf("unspecified connection side: %v", req.GetConnectionSide()) } func buildValidatePeerCertificateChainSessionResp(StatusCode uint32, StatusDetails string, ValidationResult s2av2pb.ValidatePeerCertificateChainResp_ValidationResult, ValidationDetails string, Context *s2av2ctx.S2AContext) *s2av2pb.SessionResp { return &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: StatusCode, Details: StatusDetails, }, RespOneof: &s2av2pb.SessionResp_ValidatePeerCertificateChainResp{ ValidatePeerCertificateChainResp: &s2av2pb.ValidatePeerCertificateChainResp{ ValidationResult: ValidationResult, ValidationDetails: ValidationDetails, Context: Context, }, }, } } func verifyClientPeer(req *s2av2pb.ValidatePeerCertificateChainReq) (*s2av2pb.SessionResp, error) { derCertChain := req.GetClientPeer().CertificateChain if len(derCertChain) == 0 { s := "client peer verification failed: client cert chain is empty" return buildValidatePeerCertificateChainSessionResp(uint32(codes.OK), "", s2av2pb.ValidatePeerCertificateChainResp_FAILURE, s, &s2av2ctx.S2AContext{}), nil } // Obtain the set of root certificates. rootCertPool := x509.NewCertPool() if ok := rootCertPool.AppendCertsFromPEM(clientCert); ok != true { err := errors.New("client peer verification failed: S2Av2 could not obtain/parse roots") return buildValidatePeerCertificateChainSessionResp(uint32(codes.Internal), err.Error(), s2av2pb.ValidatePeerCertificateChainResp_FAILURE, err.Error(), &s2av2ctx.S2AContext{}), err } // Set the Intermediates: certs between leaf and root, excluding the leaf and root. intermediateCertPool := x509.NewCertPool() for i := 1; i < (len(derCertChain)); i++ { x509Cert, err := x509.ParseCertificate(derCertChain[i]) if err != nil { return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), err.Error(), s2av2pb.ValidatePeerCertificateChainResp_FAILURE, err.Error(), &s2av2ctx.S2AContext{}), err } intermediateCertPool.AddCert(x509Cert) } // Verify the leaf certificate. opts := x509.VerifyOptions{ CurrentTime: time.Now(), Roots: rootCertPool, Intermediates: intermediateCertPool, } x509LeafCert, err := x509.ParseCertificate(derCertChain[0]) if err != nil { s := fmt.Sprintf("client peer verification failed: %v", err) return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), s, s2av2pb.ValidatePeerCertificateChainResp_FAILURE, s, &s2av2ctx.S2AContext{}), err } if _, err := x509LeafCert.Verify(opts); err != nil { s := fmt.Sprintf("client peer verification failed: %v", err) return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), s, s2av2pb.ValidatePeerCertificateChainResp_FAILURE, s, &s2av2ctx.S2AContext{}), nil } return buildValidatePeerCertificateChainSessionResp(uint32(codes.OK), "", s2av2pb.ValidatePeerCertificateChainResp_SUCCESS, "client peer verification succeeded", &s2av2ctx.S2AContext{}), nil } func verifyServerPeer(req *s2av2pb.ValidatePeerCertificateChainReq, serverAuthorizationPolicy []byte) (*s2av2pb.SessionResp, error) { if serverAuthorizationPolicy != nil { if got := req.GetServerPeer().SerializedUnrestrictedClientPolicy; !bytes.Equal(got, serverAuthorizationPolicy) { err := fmt.Errorf("server peer verification failed: invalid server authorization policy, expected: %s, got: %s", serverAuthorizationPolicy, got) return buildValidatePeerCertificateChainSessionResp(uint32(codes.Internal), err.Error(), s2av2pb.ValidatePeerCertificateChainResp_FAILURE, err.Error(), &s2av2ctx.S2AContext{}), err } } derCertChain := req.GetServerPeer().CertificateChain if len(derCertChain) == 0 { s := "server peer verification failed: server cert chain is empty" return buildValidatePeerCertificateChainSessionResp(uint32(codes.OK), "", s2av2pb.ValidatePeerCertificateChainResp_FAILURE, s, &s2av2ctx.S2AContext{}), nil } // Obtain the set of root certificates. rootCertPool := x509.NewCertPool() if ok := rootCertPool.AppendCertsFromPEM(serverCert); ok != true { err := errors.New("server peer verification failed: S2Av2 could not obtain/parse roots") return buildValidatePeerCertificateChainSessionResp(uint32(codes.Internal), err.Error(), s2av2pb.ValidatePeerCertificateChainResp_FAILURE, err.Error(), &s2av2ctx.S2AContext{}), err } // Set the Intermediates: certs between leaf and root, excluding the leaf and root. intermediateCertPool := x509.NewCertPool() for i := 1; i < (len(derCertChain)); i++ { x509Cert, err := x509.ParseCertificate(derCertChain[i]) if err != nil { return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), err.Error(), s2av2pb.ValidatePeerCertificateChainResp_FAILURE, err.Error(), &s2av2ctx.S2AContext{}), err } intermediateCertPool.AddCert(x509Cert) } // Verify the leaf certificate. opts := x509.VerifyOptions{ CurrentTime: time.Now(), Roots: rootCertPool, Intermediates: intermediateCertPool, } x509LeafCert, err := x509.ParseCertificate(derCertChain[0]) if err != nil { s := fmt.Sprintf("server peer verification failed: %v", err) return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), s, s2av2pb.ValidatePeerCertificateChainResp_FAILURE, s, &s2av2ctx.S2AContext{}), err } if _, err := x509LeafCert.Verify(opts); err != nil { s := fmt.Sprintf("server peer verification failed: %v", err) return buildValidatePeerCertificateChainSessionResp(uint32(codes.InvalidArgument), s, s2av2pb.ValidatePeerCertificateChainResp_FAILURE, s, &s2av2ctx.S2AContext{}), nil } return buildValidatePeerCertificateChainSessionResp(uint32(codes.OK), "", s2av2pb.ValidatePeerCertificateChainResp_SUCCESS, "server peer verification succeeded", &s2av2ctx.S2AContext{}), nil } s2a-go-0.1.8/internal/v2/fakes2av2/fakes2av2_test.go000066400000000000000000000437771464711036600217430ustar00rootroot00000000000000/* * * 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 fakes2av2 import ( "context" "crypto" "crypto/rand" "crypto/sha256" "crypto/tls" "errors" "fmt" "log" "net" "sync" "testing" "time" "github.com/google/go-cmp/cmp" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/testing/protocmp" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2ctx "github.com/google/s2a-go/internal/proto/v2/s2a_context_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( defaultTimeout = 10.0 * time.Second ) func startFakeS2Av2Server(wg *sync.WaitGroup) (address string, stop func(), err error) { // Pick unused port. listener, err := net.Listen("tcp", ":0") address = listener.Addr().String() if err != nil { log.Fatalf("Failed to listen on address %s: %v", listener.Addr().String(), err) } s := grpc.NewServer() log.Printf("Server: started gRPC Fake S2Av2 Server on address: %s", listener.Addr().String()) s2av2pb.RegisterS2AServiceServer(s, &Server{ExpectedToken: "valid_token"}) go func() { wg.Done() if err := s.Serve(listener); err != nil { log.Printf("Failed to serve: %v", err) } }() return address, func() { s.Stop() }, nil } func TestSetUpSession(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) address, stop, err := startFakeS2Av2Server(&wg) wg.Wait() if err != nil { log.Fatalf("Failed to set up fake S2Av2 server.") } for _, tc := range []struct { description string request *s2av2pb.SessionReq expErr error expectedResponse *s2av2pb.SessionResp }{ { description: "Get TLS config for client.", request: &s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{Token: "valid_token"}, }, }, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_GetTlsConfigurationResp{ GetTlsConfigurationResp: &s2av2pb.GetTlsConfigurationResp{ TlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration_{ ClientTlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration{ CertificateChain: []string{ string(clientCert), }, MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, }, }, }, }, }, }, { description: "Get TLS config for server.", request: &s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{Token: "valid_token"}, }, }, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_SERVER, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_GetTlsConfigurationResp{ GetTlsConfigurationResp: &s2av2pb.GetTlsConfigurationResp{ TlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_{ ServerTlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ CertificateChain: []string{ string(serverCert), }, MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, TlsResumptionEnabled: false, RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, MaxOverheadOfTicketAead: 0, }, }, }, }, }, }, { description: "Get TLS config error -- invalid connection side", request: &s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{Token: "valid_token"}, }, }, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_UNSPECIFIED, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.InvalidArgument), Details: "unknown ConnectionSide: CONNECTION_SIDE_UNSPECIFIED", }, }, }, { description: "Get TLS config error -- invalid token", request: &s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{Token: "invalid_token"}, }, }, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_UNSPECIFIED, }, }, }, expErr: errors.New("rpc error: code = Unknown desc = SessionReq has no AuthenticationMechanism with a valid token"), }, { description: "Get server TLS config -- empty authmechanisms (S2A_ACCESS_TOKEN env var not set)", request: &s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{}, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_SERVER, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_GetTlsConfigurationResp{ GetTlsConfigurationResp: &s2av2pb.GetTlsConfigurationResp{ TlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_{ ServerTlsConfiguration: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ CertificateChain: []string{ string(serverCert), }, MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, TlsResumptionEnabled: false, RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, MaxOverheadOfTicketAead: 0, }, }, }, }, }, }, { description: "Client Peer Verification", request: &s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_ValidatePeerCertificateChainReq{ ValidatePeerCertificateChainReq: &s2av2pb.ValidatePeerCertificateChainReq{ Mode: s2av2pb.ValidatePeerCertificateChainReq_SPIFFE, PeerOneof: &s2av2pb.ValidatePeerCertificateChainReq_ClientPeer_{ ClientPeer: &s2av2pb.ValidatePeerCertificateChainReq_ClientPeer{ CertificateChain: [][]byte{clientDERCert}, }, }, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), Details: "", }, RespOneof: &s2av2pb.SessionResp_ValidatePeerCertificateChainResp{ ValidatePeerCertificateChainResp: &s2av2pb.ValidatePeerCertificateChainResp{ ValidationResult: s2av2pb.ValidatePeerCertificateChainResp_SUCCESS, ValidationDetails: "client peer verification succeeded", Context: &s2av2ctx.S2AContext{}, }, }, }, }, { description: "Client Peer Verification -- failure", request: &s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_ValidatePeerCertificateChainReq{ ValidatePeerCertificateChainReq: &s2av2pb.ValidatePeerCertificateChainReq{ Mode: s2av2pb.ValidatePeerCertificateChainReq_SPIFFE, PeerOneof: &s2av2pb.ValidatePeerCertificateChainReq_ClientPeer_{ ClientPeer: &s2av2pb.ValidatePeerCertificateChainReq_ClientPeer{ CertificateChain: [][]byte{}, }, }, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), Details: "", }, RespOneof: &s2av2pb.SessionResp_ValidatePeerCertificateChainResp{ ValidatePeerCertificateChainResp: &s2av2pb.ValidatePeerCertificateChainResp{ ValidationResult: s2av2pb.ValidatePeerCertificateChainResp_FAILURE, ValidationDetails: "client peer verification failed: client cert chain is empty", Context: &s2av2ctx.S2AContext{}, }, }, }, }, { description: "Server Peer Verification", request: &s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_ValidatePeerCertificateChainReq{ ValidatePeerCertificateChainReq: &s2av2pb.ValidatePeerCertificateChainReq{ Mode: s2av2pb.ValidatePeerCertificateChainReq_SPIFFE, PeerOneof: &s2av2pb.ValidatePeerCertificateChainReq_ServerPeer_{ ServerPeer: &s2av2pb.ValidatePeerCertificateChainReq_ServerPeer{ CertificateChain: [][]byte{serverDERCert}, }, }, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), Details: "", }, RespOneof: &s2av2pb.SessionResp_ValidatePeerCertificateChainResp{ ValidatePeerCertificateChainResp: &s2av2pb.ValidatePeerCertificateChainResp{ ValidationResult: s2av2pb.ValidatePeerCertificateChainResp_SUCCESS, ValidationDetails: "server peer verification succeeded", Context: &s2av2ctx.S2AContext{}, }, }, }, }, } { t.Run(tc.description, func(t *testing.T) { // Create new stream to server. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") // Send request. if err := cstream.Send(tc.request); err != nil { t.Fatalf("Client: failed to send SessionReq: %v", err) } log.Printf("Client: sent SessionReq") // Get the response. resp, err := cstream.Recv() if err != tc.expErr { if (err != nil) && (tc.expErr != nil) { if err.Error() != tc.expErr.Error() { t.Fatalf("err = %v, expErr = %v", err.Error(), tc.expErr.Error()) } } else { t.Fatalf("err = %v, expErr = %v", err, tc.expErr) } } log.Printf("Client: received SessionResp") if diff := cmp.Diff(tc.expectedResponse, resp, protocmp.Transform()); diff != "" { t.Errorf("cstream.Recv() returned incorrect SessionResp, (-want +got):\n%s", diff) } log.Printf("resp matches tc.expectedResponse") }) } stop() } func TestSetUpSessionPrivateKeyOperation(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) address, stop, err := startFakeS2Av2Server(&wg) wg.Wait() if err != nil { log.Fatalf("Failed to set up fake S2Av2 server.") } // Setup for client and server offloadPrivateKeyOperation test. clientTLSCert, err := tls.X509KeyPair(clientCert, clientKey) if err != nil { log.Fatalf("Failed during test setup: %v", err) } serverTLSCert, err := tls.X509KeyPair(serverCert, serverKey) if err != nil { log.Fatalf("Failed during test setup: %v", err) } testString := "Generate hash and sign this." // TODO(rmehta19): Investigate whether go crypto libraries compute hash. // If so, remove this line, and just pass testString to Sign and as InBytes. hsha256 := sha256.Sum256([]byte(testString)) var opts crypto.Hash = crypto.SHA256 signedWithClientKey, err := clientTLSCert.PrivateKey.(crypto.Signer).Sign(rand.Reader, hsha256[:], opts) if err != nil { log.Fatalf("Failed during test setup: %v", err) } signedWithServerKey, err := serverTLSCert.PrivateKey.(crypto.Signer).Sign(rand.Reader, hsha256[:], opts) if err != nil { log.Fatalf("Failed during test setup: %v", err) } for _, tc := range []struct { description string connSide commonpb.ConnectionSide request *s2av2pb.SessionReq expectedResponse *s2av2pb.SessionResp }{ { description: "client side private key operation", connSide: commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT, request: &s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_OffloadPrivateKeyOperationReq{ OffloadPrivateKeyOperationReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{ Sha256Digest: []byte(hsha256[:]), }, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_OffloadPrivateKeyOperationResp{ OffloadPrivateKeyOperationResp: &s2av2pb.OffloadPrivateKeyOperationResp{ OutBytes: signedWithClientKey, }, }, }, }, { description: "server side private key operation", connSide: commonpb.ConnectionSide_CONNECTION_SIDE_SERVER, request: &s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_OffloadPrivateKeyOperationReq{ OffloadPrivateKeyOperationReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{ Sha256Digest: []byte(hsha256[:]), }, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.OK), }, RespOneof: &s2av2pb.SessionResp_OffloadPrivateKeyOperationResp{ OffloadPrivateKeyOperationResp: &s2av2pb.OffloadPrivateKeyOperationResp{ OutBytes: signedWithServerKey, }, }, }, }, { description: "client side private key operation -- invalid signature algorithm", connSide: commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT, request: &s2av2pb.SessionReq{ ReqOneof: &s2av2pb.SessionReq_OffloadPrivateKeyOperationReq{ OffloadPrivateKeyOperationReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{ Sha256Digest: []byte(hsha256[:]), }, }, }, }, expectedResponse: &s2av2pb.SessionResp{ Status: &s2av2pb.Status{ Code: uint32(codes.InvalidArgument), Details: fmt.Sprintf("invalid signature algorithm: %v", s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED), }, }, }, } { t.Run(tc.description, func(t *testing.T) { // Create new stream to server. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") // Send first SessionReq for TLS Config. Sets isClientSide to ensure correct // private key used to sign transcript. if err := cstream.Send(&s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{ Token: "valid_token", }, }, }, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: tc.connSide, }, }, }); err != nil { t.Fatalf("Setup failed: failed to send initial SessionReq for TLS config: %v", err) } if _, err := cstream.Recv(); err != nil { t.Fatalf("Setup failed: failed to receive initial SessionResp for TLS config: %v", err) } // Send request. if err := cstream.Send(tc.request); err != nil { t.Fatalf("Client: failed to send SessionReq: %v", err) } log.Printf("Client: sent SessionReq") // Get the response. resp, err := cstream.Recv() if err != nil { t.Fatalf("Client: failed to receive SessionResp: %v", err) } log.Printf("Client: received SessionResp") if diff := cmp.Diff(tc.expectedResponse, resp, protocmp.Transform()); diff != "" { t.Errorf("cstream.Recv() returned incorrect SessionResp, (-want +got):\n%s", diff) } log.Printf("resp matches tc.expectedResponse") }) } stop() } s2a-go-0.1.8/internal/v2/fakes2av2/testdata/000077500000000000000000000000001464711036600203605ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/fakes2av2/testdata/client_root_cert.der000066400000000000000000000017651464711036600244230ustar00rootroot0000000000000000٠)se^G"Od0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220531200315Z 420526200315Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 ㅸ~Fħw@?-nGt"a/}zr߄ C1S/-Mi#GS0Q0U@Sx lLJi%0U#0@Sx lLJi%0U00  *H  O6sC$zr WS}'}"JVeõp=Ւ?X=kIQ+ӜFXL7fLe Hz'Cbg@B'3K.q+p?OP\Pnw )exRPYhL5-@3)DZD>,uÞv\C_m+elFl80~oY}O)Vcݰb7(%W=s2a-go-0.1.8/internal/v2/fakes2av2/testdata/client_root_cert.pem000066400000000000000000000026241464711036600244250ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu 0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 /P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco pKklVz0= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/fakes2av2/testdata/client_root_key.pem000066400000000000000000000032131464711036600242530ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj +Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G 4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh 68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ /+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx 2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm 56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/fakes2av2/testdata/server_root_cert.der000066400000000000000000000017651464711036600244530ustar00rootroot0000000000000000٠(*be{6F"̟0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220531200825Z 420526200825Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 C76 AcΓL.vy>Z(4jS~_/LKυjNd|X< :TوRvA3TI>D,r<EުȚ\=«ϓ`\*x^d_2&ƫۣ }uS}QR9Ճ)EvG뇬; K.zWHMyE(ٌ'  ŋIdKyԦ\Bx%قuXۨIS0Q0U A iQ +UTTY0U#0 A iQ +UTTY0U00  *H  8hbr{Y3 D%^ +X]#|9뜚YÈ=g*.ϗ<=t!> '}"d+>Y=hD(|{J蒬eVSOXHvK\K ܘΒjUvMw}lPsz& ; %2_E%xju]adJI) ֮='稻P~Di !UAEP7J彇Ϭ& s2a-go-0.1.8/internal/v2/fakes2av2/testdata/server_root_cert.pem000066400000000000000000000026241464711036600244550ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKCoDuLtiZXvhsBY2RoDm0ugizJ8wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwODI1WhcNNDIwNTI2MjAwODI1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKK1++PXQ+M3hjYH/v0K4UEYl5ljzpNM1i52eQM+gFooojT87PDSaphT fs0PXy/PTAjHBEvPhWpOpmQXfJNYzjwcCvg66hbqkv++/VTZiFLAsHagzkEz+FRJ qT5Eq7G5FLyw1izX1uxyPN7tAEWEEg7eqsiaXD3Cq8+TYN9cjirPeF7RZF8yFCYE xqvbo+Yc6RL6xw19iXVTfctRgQe581KQuIY5/LXo3dWDEilFdsADAe8XAEcO64es Ow0g1UvXLnpXSE151kXBFb3sKH/ZjCecDYMCIMEb4sWLSblkSxJ5sNSmXIG4wtr2 Qnii7CXZgnVYraQE/Jyh+NMQANuoSdMCAwEAAaNTMFEwHQYDVR0OBBYEFAyQQQuM ab+YUQqjK8dVVOoHVFmXMB8GA1UdIwQYMBaAFAyQQQuMab+YUQqjK8dVVOoHVFmX MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADj0vQ6ykWhicoqR e6VZMwlEJV7/DSvWWKBd9MUjfKye0A4565ya5lmnzP3DiD3nqGe3miqmLsXKDs+X POqlPXTWIamP7D4MJ32XtSLwZB4ru+I+Ao/P/VngPepoRPQoBnzHe7jww0rokqxl AZERjlbTUwUAy/BPWPSzSJZ2j0tcs6ZLDNyYzpK4ao8R9/1VmQ92Tcp3feJs1QTg odRQc3om/AkWOwsll+oyX0UbJeHkFHiLanUPXbdh+/BkSvZJ8ynL+feSDdaurPe+ PSfnqLtQft9/neecGRdEaQzzzSFVQUVQzTdK1Q7hA7b55b2HvIa3ktDiks+sJsYN Dhm6uZM= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/fakes2av2/testdata/server_root_key.pem000066400000000000000000000032171464711036600243070ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAorX749dD4zeGNgf+/QrhQRiXmWPOk0zWLnZ5Az6AWiiiNPzs 8NJqmFN+zQ9fL89MCMcES8+Fak6mZBd8k1jOPBwK+DrqFuqS/779VNmIUsCwdqDO QTP4VEmpPkSrsbkUvLDWLNfW7HI83u0ARYQSDt6qyJpcPcKrz5Ng31yOKs94XtFk XzIUJgTGq9uj5hzpEvrHDX2JdVN9y1GBB7nzUpC4hjn8tejd1YMSKUV2wAMB7xcA Rw7rh6w7DSDVS9cueldITXnWRcEVvewof9mMJ5wNgwIgwRvixYtJuWRLEnmw1KZc gbjC2vZCeKLsJdmCdVitpAT8nKH40xAA26hJ0wIDAQABAoIBACaNR+lsD8G+XiZf LqN1+HkcAo9tfnyYMAdCOtnx7SdviT9Uzi8hK/B7mAeuJLeHPlS2EuaDfPD7QaFl jza6S+MiIdc+3kgfvESsVAnOoOY6kZUJ9NSuI6CU82y1iJjLaYZrv9NQMLRFPPb0 4KOX709mosB1EnXvshW0rbc+jtDFhrm1SxMt+k9TuzmMxjbOeW4LOLXPgU8X1T3Q Xy0hMZZtcgBs9wFIo8yCtmOixax9pnFE8rRltgDxTodn9LLdz1FieyntNgDksZ0P nt4kV7Mqly7ELaea+Foaj244mKsesic2e3GhAlMRLun/VSunSf7mOCxfpITB8dp1 drDhOYECgYEA19151dVxRcviuovN6Dar+QszMTnU8pDJ8BjLFjXjP/hNBBwMTHDE duMuWk2qnwZqMooI/shxrF/ufmTgS0CFrh2+ANBZu27vWConJNXcyNtdigI4wt50 L0Y2qcZn2mg67qFXHwoR3QNwrwnPwEjRXA09at9CSRZzcwDQ0ETXhYsCgYEAwPaG 06QdK8Zyly7TTzZJwxzv9uGiqzodmGtX6NEKjgij2JaCxHpukqZBJoqa0jKeK1cm eNVkOvT5ff9TMzarSHQLr3pZen2/oVLb5gaFkbcJt/klv9Fd+ZRilHY3i6QwS6pD uMiPOWS4DrLHDRVoVlAZTDjT1RVwwTs+P2NhJdkCgYEAsriXysbxBYyMp05gqEW7 lHIFbFgpSrs9th+Q5U6wW6JEgYaHWDJ1NslY80MiZI93FWjbkbZ7BvBWESeL3EIL a+EMErht0pVCbIhZ6FF4foPAqia0wAJVx14mm+G80kNBp5jE/NnleEsE3KcO7nBb hg8gLn+x7bk81JZ0TDrzBYkCgYEAuQKluv47SeF3tSScTfKLPpvcKCWmxe1uutkQ 7JShPhVioyOMNb39jnYBOWbjkm4d4QgqRuiytSR0oi3QI+Ziy5EYMyNn713qAk9j r2TJZDDPDKnBW+zt4YI4EohWMXk3JRUW4XDKggjjwJQA7bZ812TtHHvP/xoThfG7 eSNb3eECgYBw6ssgCtMrdvQiEmjKVX/9yI38mvC2kSGyzbrQnGUfgqRGomRpeZuD B5E3kysA4td5pT5lvcLgSW0TbOz+YbiriXjwOihPIelCvc9gE2eOUI71/byUWPFz 7u5F/xQ4NaGr5suLF+lBC6h7pSbM4El9lIHQAQadpuEdzHqrw+hs3g== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/fakes2av2_server/000077500000000000000000000000001464711036600201355ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/fakes2av2_server/fakes2av2_server.go000066400000000000000000000025671464711036600236500ustar00rootroot00000000000000/* * * 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 main runs an S2Av2 service. package main import ( "flag" "log" "net" "github.com/google/s2a-go/internal/v2/fakes2av2" "google.golang.org/grpc" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) var ( port = flag.String("port", ":8008", "Fake S2Av2 server address port.") ) func runFakeS2Av2Server(listenPort *string) { listener, err := net.Listen("tcp", *port) if err != nil { log.Fatalf("Failed to listen on port %s: %v", listener.Addr().String(), err) } s := grpc.NewServer() log.Printf("Server: started gRPC Fake S2Av2 Server at port: %s", listener.Addr()) s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{}) if err := s.Serve(listener); err != nil { log.Fatalf("Failed to serve: %v", err) } } func main() { runFakeS2Av2Server(port) } s2a-go-0.1.8/internal/v2/remotesigner/000077500000000000000000000000001464711036600174665ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/remotesigner/remotesigner.go000066400000000000000000000156541464711036600225330ustar00rootroot00000000000000/* * * 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") } } s2a-go-0.1.8/internal/v2/remotesigner/remotesigner_test.go000066400000000000000000000431641464711036600235670ustar00rootroot00000000000000/* * * 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 import ( "bytes" "context" "crypto" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/tls" "crypto/x509" "fmt" "log" "net" "strings" "sync" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/s2a-go/internal/v2/fakes2av2" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/testing/protocmp" _ "embed" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( defaultTimeout = 10.0 * time.Second ) func startFakeS2Av2Server(wg *sync.WaitGroup, expToken string) (stop func(), address string, err error) { listener, err := net.Listen("tcp", ":0") if err != nil { log.Fatalf("Failed to listen on address %s: %v", address, err) } address = listener.Addr().String() s := grpc.NewServer() log.Printf("Server: started gRPC fake S2Av2 Server on address: %s", address) s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ExpectedToken: expToken}) go func() { wg.Done() if err := s.Serve(listener); err != nil { log.Printf("Failed to serve: %v", err) } }() return func() { s.Stop() }, address, nil } var ( //go:embed testdata/client_cert.pem clientCertPEM []byte //go:embed testdata/client_cert.der clientCertDER []byte //go:embed testdata/client_key.pem clientKeyPEM []byte //go:embed testdata/server_cert.pem serverCertPEM []byte //go:embed testdata/server_cert.der serverCertDER []byte //go:embed testdata/server_key.pem serverKeyPEM []byte ) func TestSign(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, "TestSign_token") wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } for _, tc := range []struct { description string PEMCert []byte DERCert []byte PEMKey []byte connSide commonpb.ConnectionSide }{ { description: "Sign with client key", PEMCert: clientCertPEM, DERCert: clientCertDER, PEMKey: clientKeyPEM, connSide: commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT, }, { description: "Sign with server key", PEMCert: serverCertPEM, DERCert: serverCertDER, PEMKey: serverKeyPEM, connSide: commonpb.ConnectionSide_CONNECTION_SIDE_SERVER, }, } { t.Run(tc.description, func(t *testing.T) { // Create stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") // Send first SessionReq for TLS Config. Sets isClientSide to ensure correct // private key used to sign transcript. if err := cstream.Send(&s2av2pb.SessionReq{ AuthenticationMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{ Token: "TestSign_token", }, }, }, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: tc.connSide, }, }, }); err != nil { t.Fatalf("Setup failed: failed to send initial SessionReq for TLS config: %v", err) } if _, err := cstream.Recv(); err != nil { t.Fatalf("Setup failed: failed to receive initial SessionResp for TLS config: %v", err) } // Setup data for testing Sign. TLSCert, err := tls.X509KeyPair(tc.PEMCert, tc.PEMKey) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } x509Cert, err := x509.ParseCertificate(tc.DERCert) if err != nil { t.Fatalf("Failed to parse cert: %v", err) } testInBytes := []byte("Test data.") // Hash testInBytes because caller of Sign is expected to do so. hsha256 := sha256.Sum256([]byte(testInBytes)) // Test RSA PKCS1v15 signature algorithm. s := New(x509Cert, cstream) gotSignedBytes, err := s.Sign(rand.Reader, hsha256[:], crypto.SHA256) if err != nil { t.Errorf("Call to remote signer Sign API failed: %v", err) } wantSignedBytes, err := TLSCert.PrivateKey.(crypto.Signer).Sign(rand.Reader, hsha256[:], crypto.SHA256) if err != nil { t.Errorf("Call to Sign API failed: %v", err) } if !bytes.Equal(gotSignedBytes, wantSignedBytes) { t.Errorf("gotSignedBytes = %v, wantSignedBytes = %v", gotSignedBytes, wantSignedBytes) } if err = rsa.VerifyPKCS1v15(x509Cert.PublicKey.(*rsa.PublicKey), crypto.SHA256, hsha256[:], gotSignedBytes); err != nil { t.Errorf("Failed to verify RSA PKCS #1 v1.5 signature: %v", err) } // Test RSA PSS signature algorithm. s = New(x509Cert, cstream) pssSignerOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256} gotSignedBytes, err = s.Sign(rand.Reader, hsha256[:], pssSignerOpts) if err != nil { t.Errorf("Failed to generate gotSignedBytes using RSA PSS: %v", err) } if err = rsa.VerifyPSS(x509Cert.PublicKey.(*rsa.PublicKey), crypto.SHA256, hsha256[:], gotSignedBytes, pssSignerOpts); err != nil { t.Errorf("Failed to verify RSA PSS signature: %v", err) } }) } stop() } // TestNew runs unit test for New. func TestNew(t *testing.T) { // Setup data for testing New. clientx509Cert, err := x509.ParseCertificate(clientCertDER) if err != nil { t.Errorf("Failed to parse cert: %v", err) } var cstream s2av2pb.S2AService_SetUpSessionClient got := New(clientx509Cert, cstream) if v := got.(*remoteSigner).getCert(); v != clientx509Cert { t.Errorf("RemoteSigner leafCert field is incorrect. got: %v, want: %v", v, clientx509Cert) } if v := got.(*remoteSigner).getStream(); v != cstream { t.Errorf("RemoteSigner cstream field is incorrect. got: %v, want: %v", v, cstream) } } // Test GetSignatureAlgorithm runs unit test for getSignatureAlgorithm. func TestGetSignatureAlgorithm(t *testing.T) { for _, tc := range []struct { description string leafCert *x509.Certificate signerOpts crypto.SignerOpts wantSignatureAlgorithm s2av2pb.SignatureAlgorithm wantError error }{ { description: "Leaf certificate is nil", leafCert: nil, signerOpts: crypto.SHA256, wantError: fmt.Errorf("unknown signature algorithm"), }, { description: "Signer options are nil", leafCert: &x509.Certificate{}, signerOpts: nil, wantError: fmt.Errorf("unknown signature algorithm"), }, { description: "RSA PSS SHA256", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256}, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256, }, { description: "RSA PSS SHA384", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA384}, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384, }, { description: "RSA PSS SHA512", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA512}, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512, }, { description: "RSA PSS with unsupported hash", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.MD5}, wantError: fmt.Errorf("unknown signature algorithm"), }, { description: "RSA PKCS1 SHA256", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: crypto.SHA256, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, }, { description: "RSA PKCS1 SHA384", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: crypto.SHA384, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384, }, { description: "RSA PKCS1 SHA512", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: crypto.SHA512, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512, }, { description: "RSA PKCS1 with unsupported hash", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.RSA}, signerOpts: crypto.MD5, wantError: fmt.Errorf("unknown signature algorithm"), }, { description: "ECDSA SHA256", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA}, signerOpts: crypto.SHA256, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256, }, { description: "ECDSA SHA384", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA}, signerOpts: crypto.SHA384, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384, }, { description: "ECDSA SHA512", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA}, signerOpts: crypto.SHA512, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512, }, { description: "ECDSA with unsupported hash", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.ECDSA}, signerOpts: crypto.MD5, wantError: fmt.Errorf("unknown signature algorithm"), }, { description: "ED25519", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.Ed25519}, signerOpts: crypto.SHA256, wantSignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519, }, { description: "DSA", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.DSA}, signerOpts: crypto.SHA256, wantError: fmt.Errorf("unknown signature algorithm: \"DSA\""), }, { description: "Unknown public key algorithm", leafCert: &x509.Certificate{PublicKeyAlgorithm: x509.UnknownPublicKeyAlgorithm}, signerOpts: crypto.SHA256, wantError: fmt.Errorf("unknown signature algorithm: \"0\""), }, { description: "No public key algorithm", leafCert: &x509.Certificate{}, signerOpts: crypto.SHA256, wantError: fmt.Errorf("unknown signature algorithm: \"0\""), }, } { t.Run(tc.description, func(t *testing.T) { algorithm, err := getSignatureAlgorithm(tc.signerOpts, tc.leafCert) if tc.wantError != nil { if got, want := algorithm, s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED; got != want { t.Errorf("Signature algorithm, got: %v, want: %v", got, want) } if !strings.Contains(tc.wantError.Error(), err.Error()) { t.Errorf("Unexpected error, got: %v, want: %v", err, tc.wantError) } } else { if got, want := algorithm, tc.wantSignatureAlgorithm; got != want { t.Errorf("Signature algorithm, got: %v, want: %v", got, want) } if err != nil { t.Errorf("Unexpected error: %v", err) } } }) } } func TestGetSignReq(t *testing.T) { for _, tc := range []struct { description string signatureAlgorithm s2av2pb.SignatureAlgorithm expReq *s2av2pb.OffloadPrivateKeyOperationReq expErr error }{ { description: "Unspecified", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED, expErr: fmt.Errorf("unknown signature algorithm: %v", s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_UNSPECIFIED), }, { description: "RSA PKCS1 SHA256", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA256, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{ Sha256Digest: []byte(""), }, }, }, { description: "RSA PSS SHA256", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA256, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{ Sha256Digest: []byte(""), }, }, }, { description: "ECDSA SHA256", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP256R1_SHA256, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha256Digest{ Sha256Digest: []byte(""), }, }, }, { description: "RSA PKCS1 SHA384", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA384, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{ Sha384Digest: []byte(""), }, }, }, { description: "RSA PSS SHA384", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA384, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{ Sha384Digest: []byte(""), }, }, }, { description: "ECDSA SHA384", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP384R1_SHA384, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha384Digest{ Sha384Digest: []byte(""), }, }, }, { description: "RSA PKCS1 SHA512", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PKCS1_SHA512, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{ Sha512Digest: []byte(""), }, }, }, { description: "RSA PSS SHA512", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_RSA_PSS_RSAE_SHA512, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{ Sha512Digest: []byte(""), }, }, }, { description: "ECDSA SHA512", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ECDSA_SECP521R1_SHA512, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{ Sha512Digest: []byte(""), }, }, }, { description: "ED25519", signatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519, expReq: &s2av2pb.OffloadPrivateKeyOperationReq{ Operation: s2av2pb.OffloadPrivateKeyOperationReq_SIGN, SignatureAlgorithm: s2av2pb.SignatureAlgorithm_S2A_SSL_SIGN_ED25519, InBytes: &s2av2pb.OffloadPrivateKeyOperationReq_Sha512Digest{ Sha512Digest: []byte(""), }, }, }, } { t.Run(tc.description, func(t *testing.T) { gotReq, gotErr := getSignReq(tc.signatureAlgorithm, []byte("")) if gotErr != tc.expErr { if (gotErr == nil) || (tc.expErr == nil) { t.Errorf("gotErr = %v, expErr = %v", gotErr, tc.expErr) } if gotErr.Error() != tc.expErr.Error() { t.Errorf("gotErr = %v, expErr = %v", gotErr, tc.expErr) } } if diff := cmp.Diff(tc.expReq, gotReq, protocmp.Transform()); diff != "" { t.Errorf("getSignReq returned incorrect OffloadPrivateKeyOperationReq, (-want +got):\n%s", diff) } }) } } s2a-go-0.1.8/internal/v2/remotesigner/testdata/000077500000000000000000000000001464711036600212775ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/remotesigner/testdata/client_cert.der000066400000000000000000000017651464711036600242770ustar00rootroot0000000000000000٠)se^G"Od0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220531200315Z 420526200315Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 ㅸ~Fħw@?-nGt"a/}zr߄ C1S/-Mi#GS0Q0U@Sx lLJi%0U#0@Sx lLJi%0U00  *H  O6sC$zr WS}'}"JVeõp=Ւ?X=kIQ+ӜFXL7fLe Hz'Cbg@B'3K.q+p?OP\Pnw )exRPYhL5-@3)DZD>,uÞv\C_m+elFl80~oY}O)Vcݰb7(%W=s2a-go-0.1.8/internal/v2/remotesigner/testdata/client_cert.pem000066400000000000000000000026241464711036600243010ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu 0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 /P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco pKklVz0= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/remotesigner/testdata/client_key.pem000066400000000000000000000032131464711036600241270ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj +Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G 4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh 68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ /+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx 2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm 56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/remotesigner/testdata/server_cert.der000066400000000000000000000017651464711036600243270ustar00rootroot0000000000000000٠(*be{6F"̟0  *H  01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0 220531200825Z 420526200825Z01 0 UUS1 0 U CA10U Sunnyvale10U Company10U Division10U s2a_test_cert10 *H   xyz@xyz.com0"0  *H 0 C76 AcΓL.vy>Z(4jS~_/LKυjNd|X< :TوRvA3TI>D,r<EުȚ\=«ϓ`\*x^d_2&ƫۣ }uS}QR9Ճ)EvG뇬; K.zWHMyE(ٌ'  ŋIdKyԦ\Bx%قuXۨIS0Q0U A iQ +UTTY0U#0 A iQ +UTTY0U00  *H  8hbr{Y3 D%^ +X]#|9뜚YÈ=g*.ϗ<=t!> '}"d+>Y=hD(|{J蒬eVSOXHvK\K ܘΒjUvMw}lPsz& ; %2_E%xju]adJI) ֮='稻P~Di !UAEP7J彇Ϭ& s2a-go-0.1.8/internal/v2/remotesigner/testdata/server_cert.pem000066400000000000000000000026241464711036600243310ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKCoDuLtiZXvhsBY2RoDm0ugizJ8wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwODI1WhcNNDIwNTI2MjAwODI1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKK1++PXQ+M3hjYH/v0K4UEYl5ljzpNM1i52eQM+gFooojT87PDSaphT fs0PXy/PTAjHBEvPhWpOpmQXfJNYzjwcCvg66hbqkv++/VTZiFLAsHagzkEz+FRJ qT5Eq7G5FLyw1izX1uxyPN7tAEWEEg7eqsiaXD3Cq8+TYN9cjirPeF7RZF8yFCYE xqvbo+Yc6RL6xw19iXVTfctRgQe581KQuIY5/LXo3dWDEilFdsADAe8XAEcO64es Ow0g1UvXLnpXSE151kXBFb3sKH/ZjCecDYMCIMEb4sWLSblkSxJ5sNSmXIG4wtr2 Qnii7CXZgnVYraQE/Jyh+NMQANuoSdMCAwEAAaNTMFEwHQYDVR0OBBYEFAyQQQuM ab+YUQqjK8dVVOoHVFmXMB8GA1UdIwQYMBaAFAyQQQuMab+YUQqjK8dVVOoHVFmX MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADj0vQ6ykWhicoqR e6VZMwlEJV7/DSvWWKBd9MUjfKye0A4565ya5lmnzP3DiD3nqGe3miqmLsXKDs+X POqlPXTWIamP7D4MJ32XtSLwZB4ru+I+Ao/P/VngPepoRPQoBnzHe7jww0rokqxl AZERjlbTUwUAy/BPWPSzSJZ2j0tcs6ZLDNyYzpK4ao8R9/1VmQ92Tcp3feJs1QTg odRQc3om/AkWOwsll+oyX0UbJeHkFHiLanUPXbdh+/BkSvZJ8ynL+feSDdaurPe+ PSfnqLtQft9/neecGRdEaQzzzSFVQUVQzTdK1Q7hA7b55b2HvIa3ktDiks+sJsYN Dhm6uZM= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/remotesigner/testdata/server_key.pem000066400000000000000000000032171464711036600241630ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAorX749dD4zeGNgf+/QrhQRiXmWPOk0zWLnZ5Az6AWiiiNPzs 8NJqmFN+zQ9fL89MCMcES8+Fak6mZBd8k1jOPBwK+DrqFuqS/779VNmIUsCwdqDO QTP4VEmpPkSrsbkUvLDWLNfW7HI83u0ARYQSDt6qyJpcPcKrz5Ng31yOKs94XtFk XzIUJgTGq9uj5hzpEvrHDX2JdVN9y1GBB7nzUpC4hjn8tejd1YMSKUV2wAMB7xcA Rw7rh6w7DSDVS9cueldITXnWRcEVvewof9mMJ5wNgwIgwRvixYtJuWRLEnmw1KZc gbjC2vZCeKLsJdmCdVitpAT8nKH40xAA26hJ0wIDAQABAoIBACaNR+lsD8G+XiZf LqN1+HkcAo9tfnyYMAdCOtnx7SdviT9Uzi8hK/B7mAeuJLeHPlS2EuaDfPD7QaFl jza6S+MiIdc+3kgfvESsVAnOoOY6kZUJ9NSuI6CU82y1iJjLaYZrv9NQMLRFPPb0 4KOX709mosB1EnXvshW0rbc+jtDFhrm1SxMt+k9TuzmMxjbOeW4LOLXPgU8X1T3Q Xy0hMZZtcgBs9wFIo8yCtmOixax9pnFE8rRltgDxTodn9LLdz1FieyntNgDksZ0P nt4kV7Mqly7ELaea+Foaj244mKsesic2e3GhAlMRLun/VSunSf7mOCxfpITB8dp1 drDhOYECgYEA19151dVxRcviuovN6Dar+QszMTnU8pDJ8BjLFjXjP/hNBBwMTHDE duMuWk2qnwZqMooI/shxrF/ufmTgS0CFrh2+ANBZu27vWConJNXcyNtdigI4wt50 L0Y2qcZn2mg67qFXHwoR3QNwrwnPwEjRXA09at9CSRZzcwDQ0ETXhYsCgYEAwPaG 06QdK8Zyly7TTzZJwxzv9uGiqzodmGtX6NEKjgij2JaCxHpukqZBJoqa0jKeK1cm eNVkOvT5ff9TMzarSHQLr3pZen2/oVLb5gaFkbcJt/klv9Fd+ZRilHY3i6QwS6pD uMiPOWS4DrLHDRVoVlAZTDjT1RVwwTs+P2NhJdkCgYEAsriXysbxBYyMp05gqEW7 lHIFbFgpSrs9th+Q5U6wW6JEgYaHWDJ1NslY80MiZI93FWjbkbZ7BvBWESeL3EIL a+EMErht0pVCbIhZ6FF4foPAqia0wAJVx14mm+G80kNBp5jE/NnleEsE3KcO7nBb hg8gLn+x7bk81JZ0TDrzBYkCgYEAuQKluv47SeF3tSScTfKLPpvcKCWmxe1uutkQ 7JShPhVioyOMNb39jnYBOWbjkm4d4QgqRuiytSR0oi3QI+Ziy5EYMyNn713qAk9j r2TJZDDPDKnBW+zt4YI4EohWMXk3JRUW4XDKggjjwJQA7bZ812TtHHvP/xoThfG7 eSNb3eECgYBw6ssgCtMrdvQiEmjKVX/9yI38mvC2kSGyzbrQnGUfgqRGomRpeZuD B5E3kysA4td5pT5lvcLgSW0TbOz+YbiriXjwOihPIelCvc9gE2eOUI71/byUWPFz 7u5F/xQ4NaGr5suLF+lBC6h7pSbM4El9lIHQAQadpuEdzHqrw+hs3g== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/s2av2.go000066400000000000000000000306561464711036600162610ustar00rootroot00000000000000/* * * 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 v2 provides the S2Av2 transport credentials used by a gRPC // application. package v2 import ( "context" "crypto/tls" "errors" "net" "os" "time" "github.com/google/s2a-go/fallback" "github.com/google/s2a-go/internal/handshaker/service" "github.com/google/s2a-go/internal/tokenmanager" "github.com/google/s2a-go/internal/v2/tlsconfigstore" "github.com/google/s2a-go/retry" "github.com/google/s2a-go/stream" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" "google.golang.org/protobuf/proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( s2aSecurityProtocol = "tls" defaultS2ATimeout = 6 * time.Second ) // An environment variable, which sets the timeout enforced on the connection to the S2A service for handshake. const s2aTimeoutEnv = "S2A_TIMEOUT" type s2av2TransportCreds struct { info *credentials.ProtocolInfo isClient bool serverName string s2av2Address string transportCreds credentials.TransportCredentials tokenManager *tokenmanager.AccessTokenManager // localIdentity should only be used by the client. localIdentity *commonpb.Identity // localIdentities should only be used by the server. localIdentities []*commonpb.Identity verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode fallbackClientHandshake fallback.ClientHandshake getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error) serverAuthorizationPolicy []byte } // NewClientCreds returns a client-side transport credentials object that uses // the S2Av2 to establish a secure connection with a server. func NewClientCreds(s2av2Address string, transportCreds credentials.TransportCredentials, localIdentity *commonpb.Identity, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, fallbackClientHandshakeFunc fallback.ClientHandshake, getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error), serverAuthorizationPolicy []byte) (credentials.TransportCredentials, error) { // Create an AccessTokenManager instance to use to authenticate to S2Av2. accessTokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() creds := &s2av2TransportCreds{ info: &credentials.ProtocolInfo{ SecurityProtocol: s2aSecurityProtocol, }, isClient: true, serverName: "", s2av2Address: s2av2Address, transportCreds: transportCreds, localIdentity: localIdentity, verificationMode: verificationMode, fallbackClientHandshake: fallbackClientHandshakeFunc, getS2AStream: getS2AStream, serverAuthorizationPolicy: serverAuthorizationPolicy, } if err != nil { creds.tokenManager = nil } else { creds.tokenManager = &accessTokenManager } if grpclog.V(1) { grpclog.Info("Created client S2Av2 transport credentials.") } return creds, nil } // NewServerCreds returns a server-side transport credentials object that uses // the S2Av2 to establish a secure connection with a client. func NewServerCreds(s2av2Address string, transportCreds credentials.TransportCredentials, localIdentities []*commonpb.Identity, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error)) (credentials.TransportCredentials, error) { // Create an AccessTokenManager instance to use to authenticate to S2Av2. accessTokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() creds := &s2av2TransportCreds{ info: &credentials.ProtocolInfo{ SecurityProtocol: s2aSecurityProtocol, }, isClient: false, s2av2Address: s2av2Address, transportCreds: transportCreds, localIdentities: localIdentities, verificationMode: verificationMode, getS2AStream: getS2AStream, } if err != nil { creds.tokenManager = nil } else { creds.tokenManager = &accessTokenManager } if grpclog.V(1) { grpclog.Info("Created server S2Av2 transport credentials.") } return creds, nil } // ClientHandshake performs a client-side mTLS handshake using the S2Av2. func (c *s2av2TransportCreds) ClientHandshake(ctx context.Context, serverAuthority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { if !c.isClient { return nil, nil, errors.New("client handshake called using server transport credentials") } // Remove the port from serverAuthority. serverName := removeServerNamePort(serverAuthority) timeoutCtx, cancel := context.WithTimeout(ctx, GetS2ATimeout()) defer cancel() var s2AStream stream.S2AStream var err error retry.Run(timeoutCtx, func() error { s2AStream, err = createStream(timeoutCtx, c.s2av2Address, c.transportCreds, c.getS2AStream) return err }) if err != nil { grpclog.Infof("Failed to connect to S2Av2: %v", err) if c.fallbackClientHandshake != nil { return c.fallbackClientHandshake(ctx, serverAuthority, rawConn, err) } return nil, nil, err } defer s2AStream.CloseSend() if grpclog.V(1) { grpclog.Infof("Connected to S2Av2.") } var config *tls.Config var tokenManager tokenmanager.AccessTokenManager if c.tokenManager == nil { tokenManager = nil } else { tokenManager = *c.tokenManager } sn := serverName if c.serverName != "" { sn = c.serverName } retry.Run(timeoutCtx, func() error { config, err = tlsconfigstore.GetTLSConfigurationForClient(sn, s2AStream, tokenManager, c.localIdentity, c.verificationMode, c.serverAuthorizationPolicy) return err }) if err != nil { grpclog.Info("Failed to get client TLS config from S2Av2: %v", err) if c.fallbackClientHandshake != nil { return c.fallbackClientHandshake(ctx, serverAuthority, rawConn, err) } return nil, nil, err } if grpclog.V(1) { grpclog.Infof("Got client TLS config from S2Av2.") } creds := credentials.NewTLS(config) conn, authInfo, err := creds.ClientHandshake(timeoutCtx, serverName, rawConn) if err != nil { grpclog.Infof("Failed to do client handshake using S2Av2: %v", err) if c.fallbackClientHandshake != nil { return c.fallbackClientHandshake(ctx, serverAuthority, rawConn, err) } return nil, nil, err } grpclog.Infof("client-side handshake is done using S2Av2 to: %s", serverName) return conn, authInfo, err } // ServerHandshake performs a server-side mTLS handshake using the S2Av2. func (c *s2av2TransportCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { if c.isClient { return nil, nil, errors.New("server handshake called using client transport credentials") } ctx, cancel := context.WithTimeout(context.Background(), GetS2ATimeout()) defer cancel() var s2AStream stream.S2AStream var err error retry.Run(ctx, func() error { s2AStream, err = createStream(ctx, c.s2av2Address, c.transportCreds, c.getS2AStream) return err }) if err != nil { grpclog.Infof("Failed to connect to S2Av2: %v", err) return nil, nil, err } defer s2AStream.CloseSend() if grpclog.V(1) { grpclog.Infof("Connected to S2Av2.") } var tokenManager tokenmanager.AccessTokenManager if c.tokenManager == nil { tokenManager = nil } else { tokenManager = *c.tokenManager } var config *tls.Config retry.Run(ctx, func() error { config, err = tlsconfigstore.GetTLSConfigurationForServer(s2AStream, tokenManager, c.localIdentities, c.verificationMode) return err }) if err != nil { grpclog.Infof("Failed to get server TLS config from S2Av2: %v", err) return nil, nil, err } if grpclog.V(1) { grpclog.Infof("Got server TLS config from S2Av2.") } creds := credentials.NewTLS(config) conn, authInfo, err := creds.ServerHandshake(rawConn) if err != nil { grpclog.Infof("Failed to do server handshake using S2Av2: %v", err) return nil, nil, err } return conn, authInfo, err } // Info returns protocol info of s2av2TransportCreds. func (c *s2av2TransportCreds) Info() credentials.ProtocolInfo { return *c.info } // Clone makes a deep copy of s2av2TransportCreds. func (c *s2av2TransportCreds) Clone() credentials.TransportCredentials { info := *c.info serverName := c.serverName fallbackClientHandshake := c.fallbackClientHandshake s2av2Address := c.s2av2Address var tokenManager tokenmanager.AccessTokenManager if c.tokenManager == nil { tokenManager = nil } else { tokenManager = *c.tokenManager } verificationMode := c.verificationMode var localIdentity *commonpb.Identity if c.localIdentity != nil { localIdentity = proto.Clone(c.localIdentity).(*commonpb.Identity) } var localIdentities []*commonpb.Identity if c.localIdentities != nil { localIdentities = make([]*commonpb.Identity, len(c.localIdentities)) for i, localIdentity := range c.localIdentities { localIdentities[i] = proto.Clone(localIdentity).(*commonpb.Identity) } } creds := &s2av2TransportCreds{ info: &info, isClient: c.isClient, serverName: serverName, fallbackClientHandshake: fallbackClientHandshake, s2av2Address: s2av2Address, localIdentity: localIdentity, localIdentities: localIdentities, verificationMode: verificationMode, } if c.tokenManager == nil { creds.tokenManager = nil } else { creds.tokenManager = &tokenManager } return creds } // NewClientTLSConfig returns a tls.Config instance that uses S2Av2 to establish a TLS connection as // a client. The tls.Config MUST only be used to establish a single TLS connection. func NewClientTLSConfig( ctx context.Context, s2av2Address string, transportCreds credentials.TransportCredentials, tokenManager tokenmanager.AccessTokenManager, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, serverName string, serverAuthorizationPolicy []byte) (*tls.Config, error) { s2AStream, err := createStream(ctx, s2av2Address, transportCreds, nil) if err != nil { grpclog.Infof("Failed to connect to S2Av2: %v", err) return nil, err } return tlsconfigstore.GetTLSConfigurationForClient(removeServerNamePort(serverName), s2AStream, tokenManager, nil, verificationMode, serverAuthorizationPolicy) } // OverrideServerName sets the ServerName in the s2av2TransportCreds protocol // info. The ServerName MUST be a hostname. func (c *s2av2TransportCreds) OverrideServerName(serverNameOverride string) error { serverName := removeServerNamePort(serverNameOverride) c.info.ServerName = serverName c.serverName = serverName return nil } // Remove the trailing port from server name. func removeServerNamePort(serverName string) string { name, _, err := net.SplitHostPort(serverName) if err != nil { name = serverName } return name } type s2AGrpcStream struct { stream s2av2pb.S2AService_SetUpSessionClient } func (x s2AGrpcStream) Send(m *s2av2pb.SessionReq) error { return x.stream.Send(m) } func (x s2AGrpcStream) Recv() (*s2av2pb.SessionResp, error) { return x.stream.Recv() } func (x s2AGrpcStream) CloseSend() error { return x.stream.CloseSend() } func createStream(ctx context.Context, s2av2Address string, transportCreds credentials.TransportCredentials, getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error)) (stream.S2AStream, error) { if getS2AStream != nil { return getS2AStream(ctx, s2av2Address) } // TODO(rmehta19): Consider whether to close the connection to S2Av2. conn, err := service.Dial(ctx, s2av2Address, transportCreds) if err != nil { return nil, err } client := s2av2pb.NewS2AServiceClient(conn) gRPCStream, err := client.SetUpSession(ctx, []grpc.CallOption{}...) if err != nil { return nil, err } return &s2AGrpcStream{ stream: gRPCStream, }, nil } // GetS2ATimeout returns the timeout enforced on the connection to the S2A service for handshake. func GetS2ATimeout() time.Duration { timeout, err := time.ParseDuration(os.Getenv(s2aTimeoutEnv)) if err != nil { return defaultS2ATimeout } return timeout } s2a-go-0.1.8/internal/v2/s2av2_e2e_test.go000066400000000000000000000376671464711036600200640ustar00rootroot00000000000000/* * * 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 v2 import ( "bytes" "context" "crypto/tls" "fmt" "io/ioutil" "net" "os" "path/filepath" "testing" "time" _ "embed" "github.com/google/s2a-go/fallback" "github.com/google/s2a-go/internal/tokenmanager" "github.com/google/s2a-go/internal/v2/fakes2av2" "github.com/google/s2a-go/retry" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" grpc "google.golang.org/grpc" helloworldpb "github.com/google/s2a-go/internal/proto/examples/helloworld_go_proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( accessTokenEnvVariable = "S2A_ACCESS_TOKEN" defaultE2ETimeout = time.Second * 5 clientMessage = "echo" ) var ( //go:embed testdata/client_cert.pem clientCertpem []byte //go:embed testdata/client_key.pem clientKeypem []byte //go:embed testdata/server_cert.pem serverCertpem []byte //go:embed testdata/server_key.pem serverKeypem []byte ) // server implements the helloworld.GreeterServer. type server struct { helloworldpb.UnimplementedGreeterServer } // SayHello implements helloworld.GreeterServer. func (s *server) SayHello(_ context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { return &helloworldpb.HelloReply{Message: "Hello " + in.GetName()}, nil } // startFakeS2A starts up a fake S2A and returns the address that it is // listening on. func startFakeS2A(t *testing.T, expToken string) string { lis, err := net.Listen("tcp", ":") if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } s := grpc.NewServer() s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ExpectedToken: expToken}) go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return lis.Addr().String() } // startFakeS2A starts up a fake S2A on UDS and returns the address that it is // listening on. func startFakeS2AOnUDS(t *testing.T, expToken string) string { dir, err := ioutil.TempDir("/tmp", "socket_dir") if err != nil { t.Errorf("Unable to create temporary directory: %v", err) } udsAddress := filepath.Join(dir, "socket") lis, err := net.Listen("unix", filepath.Join(dir, "socket")) if err != nil { t.Errorf("net.Listen(unix, %s) failed: %v", udsAddress, err) } s := grpc.NewServer() s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ExpectedToken: expToken}) go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return fmt.Sprintf("unix://%s", lis.Addr().String()) } // startServer starts up a server and returns the address that it is listening // on. func startServer(t *testing.T, s2aAddress string, localIdentities []*commonpb.Identity) string { // TODO(rmehta19): Pass verificationMode as a parameter to startServer. creds, err := NewServerCreds(s2aAddress, nil, localIdentities, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil) if err != nil { t.Errorf("NewServerCreds(%s) failed: %v", s2aAddress, err) } lis, err := net.Listen("tcp", ":0") if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } s := grpc.NewServer(grpc.Creds(creds)) helloworldpb.RegisterGreeterServer(s, &server{}) go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return lis.Addr().String() } // startFallbackServer runs a GRPC echo testing server and returns the address. // It's used to test the default fallback logic upon S2A failure. func startFallbackServer(t *testing.T) string { lis, err := net.Listen("tcp", ":0") if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } cert, err := tls.X509KeyPair(serverCertpem, serverKeypem) if err != nil { t.Errorf("failure initializing tls.certificate: %v", err) } // Client certs are not required for the fallback server. creds := credentials.NewTLS(&tls.Config{ MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, Certificates: []tls.Certificate{cert}, }) s := grpc.NewServer(grpc.Creds(creds)) helloworldpb.RegisterGreeterServer(s, &server{}) go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return lis.Addr().String() } // runClient starts up a client and calls the server. func runClient(ctx context.Context, t *testing.T, clientS2AAddress, serverAddr string, localIdentity *commonpb.Identity, fallbackHandshake fallback.ClientHandshake) { creds, err := NewClientCreds(clientS2AAddress, nil, localIdentity, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, fallbackHandshake, nil, nil) if err != nil { t.Errorf("NewClientCreds(%s) failed: %v", clientS2AAddress, err) } dialOptions := []grpc.DialOption{ grpc.WithTransportCredentials(creds), grpc.WithBlock(), } grpclog.Info("Client dialing server at address: %v", serverAddr) // Establish a connection to the server. conn, err := grpc.Dial(serverAddr, dialOptions...) if err != nil { t.Errorf("grpc.Dial(%v, %v) failed: %v", serverAddr, dialOptions, err) } defer conn.Close() // Contact the server. c := helloworldpb.NewGreeterClient(conn) req := &helloworldpb.HelloRequest{Name: clientMessage} grpclog.Infof("Client calling SayHello with request: %v", req) resp, err := c.SayHello(ctx, req, grpc.WaitForReady(true)) if err != nil { t.Errorf("c.SayHello(%v, %v) failed: %v", ctx, req, err) } if got, want := resp.GetMessage(), "Hello "+clientMessage; got != want { t.Errorf("r.GetMessage() = %v, want %v", got, want) } grpclog.Infof("Client received message from server: %s", resp.GetMessage()) } func TestEndToEndUsingFakeS2AOverTCP(t *testing.T) { os.Setenv(accessTokenEnvVariable, "TestE2ETCP_token") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2As for the client and server. serverS2AAddr := startFakeS2A(t, "TestE2ETCP_token") grpclog.Infof("Fake handshaker for server running at address: %v", serverS2AAddr) clientS2AAddr := startFakeS2A(t, "TestE2ETCP_token") grpclog.Infof("Fake handshaker for client running at address: %v", clientS2AAddr) // Start the server. localIdentities := []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_server_identity", }, }, } serverAddr := startServer(t, serverS2AAddr, localIdentities) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() runClient(ctx, t, clientS2AAddr, serverAddr, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, nil) if got, want := testRetryer.Attempts(), 0; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestEndToEndUsingFakeS2AOverTCPEmptyId(t *testing.T) { os.Setenv(accessTokenEnvVariable, "TestE2ETCP_token") // Start the fake S2As for the client and server. serverS2AAddr := startFakeS2A(t, "TestE2ETCP_token") grpclog.Infof("Fake handshaker for server running at address: %v", serverS2AAddr) clientS2AAddr := startFakeS2A(t, "TestE2ETCP_token") grpclog.Infof("Fake handshaker for client running at address: %v", clientS2AAddr) // Start the server. var localIdentities []*commonpb.Identity localIdentities = append(localIdentities, nil) serverAddr := startServer(t, serverS2AAddr, localIdentities) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() runClient(ctx, t, clientS2AAddr, serverAddr, nil, nil) } func TestEndToEndUsingFakeS2AOnUDS(t *testing.T) { os.Setenv(accessTokenEnvVariable, "TestE2EUDS_token") // Start fake S2As for use by the client and server. serverS2AAddr := startFakeS2AOnUDS(t, "TestE2EUDS_token") grpclog.Infof("Fake S2A for server listening on UDS at address: %v", serverS2AAddr) clientS2AAddr := startFakeS2AOnUDS(t, "TestE2EUDS_token") grpclog.Infof("Fake S2A for client listening on UDS at address: %v", clientS2AAddr) // Start the server. localIdentities := []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_server_identity", }, }, } serverAddr := startServer(t, serverS2AAddr, localIdentities) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() runClient(ctx, t, clientS2AAddr, serverAddr, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, nil) } func TestEndToEndUsingFakeS2AOnUDSEmptyId(t *testing.T) { os.Setenv(accessTokenEnvVariable, "TestE2EUDS_token") // Start fake S2As for use by the client and server. serverS2AAddr := startFakeS2AOnUDS(t, "TestE2EUDS_token") grpclog.Infof("Fake S2A for server listening on UDS at address: %v", serverS2AAddr) clientS2AAddr := startFakeS2AOnUDS(t, "TestE2EUDS_token") grpclog.Infof("Fake S2A for client listening on UDS at address: %v", clientS2AAddr) // Start the server. var localIdentities []*commonpb.Identity localIdentities = append(localIdentities, nil) serverAddr := startServer(t, serverS2AAddr, localIdentities) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() runClient(ctx, t, clientS2AAddr, serverAddr, nil, nil) } func TestGRPCFallbackEndToEndUsingFakeS2AOverTCP(t *testing.T) { // Set for testing only. fallback.FallbackTLSConfigGRPC.InsecureSkipVerify = true os.Setenv(accessTokenEnvVariable, "TestE2ETCP_token") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2A for the server. serverS2AAddr := startFakeS2A(t, "TestE2ETCP_token") t.Logf("Fake handshaker for server running at address: %v", serverS2AAddr) // Start the server. localIdentities := []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_server_identity", }, }, } serverAddr := startServer(t, serverS2AAddr, localIdentities) fallbackServerAddr := startFallbackServer(t) t.Logf("server running at address: %v", serverAddr) t.Logf("fallback server running at address: %v", fallbackServerAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() fallbackHandshake, err := fallback.DefaultFallbackClientHandshakeFunc(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback handshake function: %v", err) } fallbackCalled := false fallbackHandshakeWrapper := func(ctx context.Context, targetServer string, conn net.Conn, err error) (net.Conn, credentials.AuthInfo, error) { fallbackCalled = true return fallbackHandshake(ctx, targetServer, conn, err) } // Set wrong S2A address for client to trigger S2A failure and fallback. runClient(ctx, t, "not_exist", serverAddr, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, fallbackHandshakeWrapper) if !fallbackCalled { t.Errorf("fallbackHandshake is not called") } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestGRPCRetryAndFallbackEndToEndUsingFakeS2AOverTCP(t *testing.T) { // Set for testing only. fallback.FallbackTLSConfigGRPC.InsecureSkipVerify = true // Set an invalid token to trigger failures and retries when talking to S2A. os.Setenv(accessTokenEnvVariable, "invalid_token") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } clientS2AAddr := startFakeS2A(t, "TestE2ETCP_token") grpclog.Infof("Fake handshaker for client running at address: %v", clientS2AAddr) serverS2AAddr := startFakeS2A(t, "TestE2ETCP_token") grpclog.Infof("Fake handshaker for server running at address: %v", serverS2AAddr) // Start the server. localIdentities := []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_server_identity", }, }, } serverAddr := startServer(t, serverS2AAddr, localIdentities) fallbackServerAddr := startFallbackServer(t) t.Logf("server running at address: %v", serverAddr) t.Logf("fallback server running at address: %v", fallbackServerAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() fallbackHandshake, err := fallback.DefaultFallbackClientHandshakeFunc(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback handshake function: %v", err) } fallbackCalled := false fallbackHandshakeWrapper := func(ctx context.Context, targetServer string, conn net.Conn, err error) (net.Conn, credentials.AuthInfo, error) { fallbackCalled = true return fallbackHandshake(ctx, targetServer, conn, err) } runClient(ctx, t, clientS2AAddr, serverAddr, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, fallbackHandshakeWrapper) if !fallbackCalled { t.Errorf("fallbackHandshake is not called") } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestNewClientTlsConfigWithTokenManager(t *testing.T) { os.Setenv(accessTokenEnvVariable, "TestNewClientTlsConfig_token") s2AAddr := startFakeS2A(t, "TestNewClientTlsConfig_token") accessTokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() if err != nil { t.Errorf("tokenmanager.NewSingleTokenAccessTokenManager() failed: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() config, err := NewClientTLSConfig(ctx, s2AAddr, nil, accessTokenManager, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, "test_server_name", nil) if err != nil { t.Errorf("NewClientTLSConfig() failed: %v", err) } cert, err := tls.X509KeyPair(clientCertpem, clientKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], cert.Certificate[0]; !bytes.Equal(got, want) { t.Errorf("tls.Config has unexpected certificate: got: %v, want: %v", got, want) } } func TestNewClientTlsConfigWithoutTokenManager(t *testing.T) { os.Unsetenv(accessTokenEnvVariable) s2AAddr := startFakeS2A(t, "ignored-value") var tokenManager tokenmanager.AccessTokenManager ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETimeout) defer cancel() config, err := NewClientTLSConfig(ctx, s2AAddr, nil, tokenManager, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, "test_server_name", nil) if err != nil { t.Errorf("NewClientTLSConfig() failed: %v", err) } cert, err := tls.X509KeyPair(clientCertpem, clientKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], cert.Certificate[0]; !bytes.Equal(got, want) { t.Errorf("tls.Config has unexpected certificate: got: %v, want: %v", got, want) } } s2a-go-0.1.8/internal/v2/s2av2_test.go000066400000000000000000000267331464711036600173210ustar00rootroot00000000000000/* * * 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 v2 import ( "context" "os" "reflect" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/s2a-go/fallback" "github.com/google/s2a-go/internal/tokenmanager" "github.com/google/s2a-go/stream" "google.golang.org/protobuf/testing/protocmp" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) var ( fakes2av2Address = "0.0.0.0:0" ) func TestNewClientCreds(t *testing.T) { os.Setenv("S2A_ACCESS_TOKEN", "TestNewClientCreds_s2a_access_token") for _, tc := range []struct { description string }{ { description: "static", }, } { t.Run(tc.description, func(t *testing.T) { c, err := NewClientCreds(fakes2av2Address, nil, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil, nil, nil) if err != nil { t.Fatalf("NewClientCreds() failed: %v", err) } if got, want := c.Info().SecurityProtocol, s2aSecurityProtocol; got != want { t.Errorf("c.Info().SecurityProtocol = %v, want %v", got, want) } _, ok := c.(*s2av2TransportCreds) if !ok { t.Fatal("The created creds is not of type s2av2TransportCreds") } }) } } func TestNewServerCreds(t *testing.T) { os.Setenv("S2A_ACCESS_TOKEN", "TestNewServerCreds_s2a_access_token") for _, tc := range []struct { description string }{ { description: "static", }, } { t.Run(tc.description, func(t *testing.T) { localIdentities := []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_server_identity", }, }, } c, err := NewServerCreds(fakes2av2Address, nil, localIdentities, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil) if err != nil { t.Fatalf("NewServerCreds() failed: %v", err) } if got, want := c.Info().SecurityProtocol, s2aSecurityProtocol; got != want { t.Errorf("c.Info().SecurityProtocol = %v, want %v", got, want) } _, ok := c.(*s2av2TransportCreds) if !ok { t.Fatal("The created creds is not of type s2av2TransportCreds") } }) } } func TestClientHandshakeFail(t *testing.T) { cc := &s2av2TransportCreds{isClient: false} if _, _, err := cc.ClientHandshake(context.Background(), "", nil); err == nil { t.Errorf("c.ClientHandshake(nil, \"\", nil) should fail with incorrect transport credentials") } } func TestServerHandshakeFail(t *testing.T) { sc := &s2av2TransportCreds{isClient: true} if _, _, err := sc.ServerHandshake(nil); err == nil { t.Errorf("c.ServerHandshake(nil) should fail with incorrect transport credentials") } } func TestInfo(t *testing.T) { os.Setenv("S2A_ACCESS_TOKEN", "TestInfo_s2a_access_token") c, err := NewClientCreds(fakes2av2Address, nil, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil, nil, nil) if err != nil { t.Fatalf("NewClientCreds() failed: %v", err) } info := c.Info() if got, want := info.SecurityProtocol, "tls"; got != want { t.Errorf("info.SecurityProtocol=%v, want %v", got, want) } } func TestCloneClient(t *testing.T) { os.Setenv("S2A_ACCESS_TOKEN", "TestCloneClient_s2a_access_token") fallbackFunc, err := fallback.DefaultFallbackClientHandshakeFunc("example.com") if err != nil { t.Errorf("error creating fallback handshake function: %v", err) } c, err := NewClientCreds(fakes2av2Address, nil, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, fallbackFunc, nil, nil) if err != nil { t.Fatalf("NewClientCreds() failed: %v", err) } cc := c.Clone() s2av2Creds, ok := c.(*s2av2TransportCreds) if !ok { t.Fatal("The created creds is not of type s2av2TransportCreds") } s2av2CloneCreds, ok := cc.(*s2av2TransportCreds) if !ok { t.Fatal("The created clone creds is not of type s2aTransportCreds") } if got, want := cmp.Equal(s2av2Creds, s2av2CloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2av2TransportCreds{}), cmp.Comparer(func(x, y tokenmanager.AccessTokenManager) bool { xToken, err := x.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } yToken, err := y.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } if xToken == yToken { return true } return false }), cmp.Comparer(func(x, y fallback.ClientHandshake) bool { return reflect.ValueOf(x) == reflect.ValueOf(y) })), true; got != want { t.Errorf("cmp.Equal(%+v, %+v) = %v, want %v", s2av2Creds, s2av2CloneCreds, got, want) } // Change the values and verify the creds were deep copied. s2av2CloneCreds.info.SecurityProtocol = "s2a" if got, want := cmp.Equal(s2av2Creds, s2av2CloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2av2TransportCreds{}), cmp.Comparer(func(x, y tokenmanager.AccessTokenManager) bool { xToken, err := x.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } yToken, err := y.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } if xToken == yToken { return true } return false })), false; got != want { t.Errorf("cmp.Equal(%+v, %+v) = %v, want %v", s2av2Creds, s2av2CloneCreds, got, want) } } func TestCloneServer(t *testing.T) { os.Setenv("S2A_ACCESS_TOKEN", "TestCloneServer_s2a_access_token") localIdentities := []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_server_identity", }, }, } c, err := NewServerCreds(fakes2av2Address, nil, localIdentities, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil) if err != nil { t.Fatalf("NewServerCreds() failed: %v", err) } cc := c.Clone() s2av2Creds, ok := c.(*s2av2TransportCreds) if !ok { t.Fatal("The created creds is not of type s2av2TransportCreds") } s2av2CloneCreds, ok := cc.(*s2av2TransportCreds) if !ok { t.Fatal("The created clone creds is not of type s2aTransportCreds") } if got, want := cmp.Equal(s2av2Creds, s2av2CloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2av2TransportCreds{}), cmp.Comparer(func(x, y tokenmanager.AccessTokenManager) bool { xToken, err := x.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } yToken, err := y.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } if xToken == yToken { return true } return false })), true; got != want { t.Errorf("cmp.Equal(%+v, %+v) = %v, want %v", s2av2Creds, s2av2CloneCreds, got, want) } // Change the values and verify the creds were deep copied. s2av2CloneCreds.info.SecurityProtocol = "s2a" if got, want := cmp.Equal(s2av2Creds, s2av2CloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2av2TransportCreds{}), cmp.Comparer(func(x, y tokenmanager.AccessTokenManager) bool { xToken, err := x.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } yToken, err := y.DefaultToken() if err != nil { t.Errorf("Failed to compare cloned creds: %v", err) } if xToken == yToken { return true } return false })), false; got != want { t.Errorf("cmp.Equal(%+v, %+v) = %v, want %v", s2av2Creds, s2av2CloneCreds, got, want) } } func TestOverrideServerName(t *testing.T) { // Setup test. os.Setenv("S2A_ACCESS_TOKEN", "TestOverrideServerName_s2a_access_token") c, err := NewClientCreds(fakes2av2Address, nil, &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "test_rsa_client_identity", }, }, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil, nil, nil) s2av2Creds, ok := c.(*s2av2TransportCreds) if !ok { t.Fatal("The created creds is not of type s2av2TransportCreds") } if err != nil { t.Fatalf("NewClientCreds() failed: %v", err) } if got, want := c.Info().ServerName, ""; got != want { t.Errorf("c.Info().ServerName = %v, want %v", got, want) } if got, want := s2av2Creds.serverName, ""; got != want { t.Errorf("c.serverName = %v, want %v", got, want) } for _, tc := range []struct { description string override string wantServerName string expectError bool }{ { description: "empty string", override: "", wantServerName: "", }, { description: "host only", override: "server.name", wantServerName: "server.name", }, { description: "invalid syntax", override: "server::", wantServerName: "server::", }, { description: "split host port", override: "host:port", wantServerName: "host", }, } { t.Run(tc.description, func(t *testing.T) { c.OverrideServerName(tc.override) if got, want := c.Info().ServerName, tc.wantServerName; got != want { t.Errorf("c.Info().ServerName = %v, want %v", got, want) } if got, want := s2av2Creds.serverName, tc.wantServerName; got != want { t.Errorf("c.serverName = %v, want %v", got, want) } }) } } type s2ATestStream struct { debug string } func (x s2ATestStream) Send(m *s2av2pb.SessionReq) error { return nil } func (x s2ATestStream) Recv() (*s2av2pb.SessionResp, error) { return nil, nil } func (x s2ATestStream) CloseSend() error { return nil } func TestCreateStream(t *testing.T) { for _, tc := range []struct { description string }{ { description: "static", }, } { t.Run(tc.description, func(t *testing.T) { s2AStream, err := createStream(context.TODO(), "fake address", nil, func(ctx context.Context, s2av2Address string) (stream.S2AStream, error) { return s2ATestStream{debug: "test s2a stream"}, nil }) if err != nil { t.Fatalf("New S2AStream failed: %v", err) } testStream, ok := s2AStream.(s2ATestStream) if !ok { t.Fatal("The created stream is not of type s2ATestStream") } if testStream.debug != "test s2a stream" { t.Errorf("The created stream is not the intended stream") } }) } } func TestGetS2ATimeout(t *testing.T) { oldEnvValue := os.Getenv(s2aTimeoutEnv) defer os.Setenv(s2aTimeoutEnv, oldEnvValue) // Unset the environment var os.Unsetenv(s2aTimeoutEnv) if got, want := GetS2ATimeout(), defaultS2ATimeout; got != want { t.Fatalf("GetS2ATimeout should return default if S2A_TIMEOUT is not set") } // Set the environment var to empty string os.Setenv(s2aTimeoutEnv, "") if got, want := GetS2ATimeout(), defaultS2ATimeout; got != want { t.Fatalf("GetS2ATimeout should return default if S2A_TIMEOUT is set to empty string") } // Set a valid duration string os.Setenv(s2aTimeoutEnv, "5s") if got, want := GetS2ATimeout(), 5*time.Second; got != want { t.Fatalf("expected timeout to be 5s") } // Set an invalid duration string os.Setenv(s2aTimeoutEnv, "5abc") if got, want := GetS2ATimeout(), defaultS2ATimeout; got != want { t.Fatalf("expected timeout to be default if the set timeout is invalid") } } s2a-go-0.1.8/internal/v2/testdata/000077500000000000000000000000001464711036600165745ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/testdata/README.md000066400000000000000000000027261464711036600200620ustar00rootroot00000000000000**How example certificates and keys generated in this directory:** To create a self signed cert(and private key), Run the following commands using openssl: ``` openssl req -x509 -sha256 -days 7305 -newkey rsa:2048 -keyout root_key.pem -out root_cert.pem ``` To create a chain of certs: ```leafCert.pem``` < ```intermediateCert.pem``` < ```rootCert.pem``` Run the following commands using openssl: Create a self signed root: ``` openssl req -x509 -sha256 -days 7305 -newkey rsa:2048 -keyout root_key.pem -out root_cert.pem ``` Create a configuration file config.cnf: ``` basicConstraints=CA:TRUE ``` Create the intermediate cert private key: ``` openssl genrsa -out intermediate_key.pem 2048 ``` Create a certificate signing request: ``` openssl req -key intermediate_key.pem -new -out intermediate.csr ``` Sign the CSR with the root: ``` openssl x509 -req -CA root_cert.pem -CAkey root_key.pem -in intermediate.csr -out intermediate_cert.pem -days 7305 -CAcreateserial -extfile config.cnf ``` Create the leaf cert private key: ``` openssl genrsa -out leaf_key.pem 2048 ``` Create a certificate signing request: ``` openssl req -key leaf_key.pem -new -out leaf.csr ``` Sign the CSR with the intermediate ``` openssl x509 -req -CA intermediate_cert.pem -CAkey intermediate_key.pem -in leaf.csr -out leaf_cert.pem -days 7305 -CAcreateserial -extfile config ``` TODO(rmehta19): Perhaps put these commands together into a script to make generation of example certs/keys and cert chains simpler. s2a-go-0.1.8/internal/v2/testdata/client_cert.pem000066400000000000000000000026241464711036600215760ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu 0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 /P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco pKklVz0= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/testdata/client_key.pem000066400000000000000000000032131464711036600214240ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj +Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G 4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh 68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ /+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx 2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm 56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/testdata/server_cert.pem000066400000000000000000000026241464711036600216260ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKCoDuLtiZXvhsBY2RoDm0ugizJ8wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwODI1WhcNNDIwNTI2MjAwODI1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKK1++PXQ+M3hjYH/v0K4UEYl5ljzpNM1i52eQM+gFooojT87PDSaphT fs0PXy/PTAjHBEvPhWpOpmQXfJNYzjwcCvg66hbqkv++/VTZiFLAsHagzkEz+FRJ qT5Eq7G5FLyw1izX1uxyPN7tAEWEEg7eqsiaXD3Cq8+TYN9cjirPeF7RZF8yFCYE xqvbo+Yc6RL6xw19iXVTfctRgQe581KQuIY5/LXo3dWDEilFdsADAe8XAEcO64es Ow0g1UvXLnpXSE151kXBFb3sKH/ZjCecDYMCIMEb4sWLSblkSxJ5sNSmXIG4wtr2 Qnii7CXZgnVYraQE/Jyh+NMQANuoSdMCAwEAAaNTMFEwHQYDVR0OBBYEFAyQQQuM ab+YUQqjK8dVVOoHVFmXMB8GA1UdIwQYMBaAFAyQQQuMab+YUQqjK8dVVOoHVFmX MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADj0vQ6ykWhicoqR e6VZMwlEJV7/DSvWWKBd9MUjfKye0A4565ya5lmnzP3DiD3nqGe3miqmLsXKDs+X POqlPXTWIamP7D4MJ32XtSLwZB4ru+I+Ao/P/VngPepoRPQoBnzHe7jww0rokqxl AZERjlbTUwUAy/BPWPSzSJZ2j0tcs6ZLDNyYzpK4ao8R9/1VmQ92Tcp3feJs1QTg odRQc3om/AkWOwsll+oyX0UbJeHkFHiLanUPXbdh+/BkSvZJ8ynL+feSDdaurPe+ PSfnqLtQft9/neecGRdEaQzzzSFVQUVQzTdK1Q7hA7b55b2HvIa3ktDiks+sJsYN Dhm6uZM= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/testdata/server_key.pem000066400000000000000000000032171464711036600214600ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAorX749dD4zeGNgf+/QrhQRiXmWPOk0zWLnZ5Az6AWiiiNPzs 8NJqmFN+zQ9fL89MCMcES8+Fak6mZBd8k1jOPBwK+DrqFuqS/779VNmIUsCwdqDO QTP4VEmpPkSrsbkUvLDWLNfW7HI83u0ARYQSDt6qyJpcPcKrz5Ng31yOKs94XtFk XzIUJgTGq9uj5hzpEvrHDX2JdVN9y1GBB7nzUpC4hjn8tejd1YMSKUV2wAMB7xcA Rw7rh6w7DSDVS9cueldITXnWRcEVvewof9mMJ5wNgwIgwRvixYtJuWRLEnmw1KZc gbjC2vZCeKLsJdmCdVitpAT8nKH40xAA26hJ0wIDAQABAoIBACaNR+lsD8G+XiZf LqN1+HkcAo9tfnyYMAdCOtnx7SdviT9Uzi8hK/B7mAeuJLeHPlS2EuaDfPD7QaFl jza6S+MiIdc+3kgfvESsVAnOoOY6kZUJ9NSuI6CU82y1iJjLaYZrv9NQMLRFPPb0 4KOX709mosB1EnXvshW0rbc+jtDFhrm1SxMt+k9TuzmMxjbOeW4LOLXPgU8X1T3Q Xy0hMZZtcgBs9wFIo8yCtmOixax9pnFE8rRltgDxTodn9LLdz1FieyntNgDksZ0P nt4kV7Mqly7ELaea+Foaj244mKsesic2e3GhAlMRLun/VSunSf7mOCxfpITB8dp1 drDhOYECgYEA19151dVxRcviuovN6Dar+QszMTnU8pDJ8BjLFjXjP/hNBBwMTHDE duMuWk2qnwZqMooI/shxrF/ufmTgS0CFrh2+ANBZu27vWConJNXcyNtdigI4wt50 L0Y2qcZn2mg67qFXHwoR3QNwrwnPwEjRXA09at9CSRZzcwDQ0ETXhYsCgYEAwPaG 06QdK8Zyly7TTzZJwxzv9uGiqzodmGtX6NEKjgij2JaCxHpukqZBJoqa0jKeK1cm eNVkOvT5ff9TMzarSHQLr3pZen2/oVLb5gaFkbcJt/klv9Fd+ZRilHY3i6QwS6pD uMiPOWS4DrLHDRVoVlAZTDjT1RVwwTs+P2NhJdkCgYEAsriXysbxBYyMp05gqEW7 lHIFbFgpSrs9th+Q5U6wW6JEgYaHWDJ1NslY80MiZI93FWjbkbZ7BvBWESeL3EIL a+EMErht0pVCbIhZ6FF4foPAqia0wAJVx14mm+G80kNBp5jE/NnleEsE3KcO7nBb hg8gLn+x7bk81JZ0TDrzBYkCgYEAuQKluv47SeF3tSScTfKLPpvcKCWmxe1uutkQ 7JShPhVioyOMNb39jnYBOWbjkm4d4QgqRuiytSR0oi3QI+Ziy5EYMyNn713qAk9j r2TJZDDPDKnBW+zt4YI4EohWMXk3JRUW4XDKggjjwJQA7bZ812TtHHvP/xoThfG7 eSNb3eECgYBw6ssgCtMrdvQiEmjKVX/9yI38mvC2kSGyzbrQnGUfgqRGomRpeZuD B5E3kysA4td5pT5lvcLgSW0TbOz+YbiriXjwOihPIelCvc9gE2eOUI71/byUWPFz 7u5F/xQ4NaGr5suLF+lBC6h7pSbM4El9lIHQAQadpuEdzHqrw+hs3g== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/tlsconfigstore/000077500000000000000000000000001464711036600200305ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/tlsconfigstore/testdata/000077500000000000000000000000001464711036600216415ustar00rootroot00000000000000s2a-go-0.1.8/internal/v2/tlsconfigstore/testdata/client_cert.pem000066400000000000000000000026241464711036600246430ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu 0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 /P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco pKklVz0= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/tlsconfigstore/testdata/client_key.pem000066400000000000000000000032131464711036600244710ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj +Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G 4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh 68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ /+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx 2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm 56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/tlsconfigstore/testdata/server_cert.pem000066400000000000000000000026241464711036600246730ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKCoDuLtiZXvhsBY2RoDm0ugizJ8wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwODI1WhcNNDIwNTI2MjAwODI1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKK1++PXQ+M3hjYH/v0K4UEYl5ljzpNM1i52eQM+gFooojT87PDSaphT fs0PXy/PTAjHBEvPhWpOpmQXfJNYzjwcCvg66hbqkv++/VTZiFLAsHagzkEz+FRJ qT5Eq7G5FLyw1izX1uxyPN7tAEWEEg7eqsiaXD3Cq8+TYN9cjirPeF7RZF8yFCYE xqvbo+Yc6RL6xw19iXVTfctRgQe581KQuIY5/LXo3dWDEilFdsADAe8XAEcO64es Ow0g1UvXLnpXSE151kXBFb3sKH/ZjCecDYMCIMEb4sWLSblkSxJ5sNSmXIG4wtr2 Qnii7CXZgnVYraQE/Jyh+NMQANuoSdMCAwEAAaNTMFEwHQYDVR0OBBYEFAyQQQuM ab+YUQqjK8dVVOoHVFmXMB8GA1UdIwQYMBaAFAyQQQuMab+YUQqjK8dVVOoHVFmX MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADj0vQ6ykWhicoqR e6VZMwlEJV7/DSvWWKBd9MUjfKye0A4565ya5lmnzP3DiD3nqGe3miqmLsXKDs+X POqlPXTWIamP7D4MJ32XtSLwZB4ru+I+Ao/P/VngPepoRPQoBnzHe7jww0rokqxl AZERjlbTUwUAy/BPWPSzSJZ2j0tcs6ZLDNyYzpK4ao8R9/1VmQ92Tcp3feJs1QTg odRQc3om/AkWOwsll+oyX0UbJeHkFHiLanUPXbdh+/BkSvZJ8ynL+feSDdaurPe+ PSfnqLtQft9/neecGRdEaQzzzSFVQUVQzTdK1Q7hA7b55b2HvIa3ktDiks+sJsYN Dhm6uZM= -----END CERTIFICATE----- s2a-go-0.1.8/internal/v2/tlsconfigstore/testdata/server_key.pem000066400000000000000000000032171464711036600245250ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAorX749dD4zeGNgf+/QrhQRiXmWPOk0zWLnZ5Az6AWiiiNPzs 8NJqmFN+zQ9fL89MCMcES8+Fak6mZBd8k1jOPBwK+DrqFuqS/779VNmIUsCwdqDO QTP4VEmpPkSrsbkUvLDWLNfW7HI83u0ARYQSDt6qyJpcPcKrz5Ng31yOKs94XtFk XzIUJgTGq9uj5hzpEvrHDX2JdVN9y1GBB7nzUpC4hjn8tejd1YMSKUV2wAMB7xcA Rw7rh6w7DSDVS9cueldITXnWRcEVvewof9mMJ5wNgwIgwRvixYtJuWRLEnmw1KZc gbjC2vZCeKLsJdmCdVitpAT8nKH40xAA26hJ0wIDAQABAoIBACaNR+lsD8G+XiZf LqN1+HkcAo9tfnyYMAdCOtnx7SdviT9Uzi8hK/B7mAeuJLeHPlS2EuaDfPD7QaFl jza6S+MiIdc+3kgfvESsVAnOoOY6kZUJ9NSuI6CU82y1iJjLaYZrv9NQMLRFPPb0 4KOX709mosB1EnXvshW0rbc+jtDFhrm1SxMt+k9TuzmMxjbOeW4LOLXPgU8X1T3Q Xy0hMZZtcgBs9wFIo8yCtmOixax9pnFE8rRltgDxTodn9LLdz1FieyntNgDksZ0P nt4kV7Mqly7ELaea+Foaj244mKsesic2e3GhAlMRLun/VSunSf7mOCxfpITB8dp1 drDhOYECgYEA19151dVxRcviuovN6Dar+QszMTnU8pDJ8BjLFjXjP/hNBBwMTHDE duMuWk2qnwZqMooI/shxrF/ufmTgS0CFrh2+ANBZu27vWConJNXcyNtdigI4wt50 L0Y2qcZn2mg67qFXHwoR3QNwrwnPwEjRXA09at9CSRZzcwDQ0ETXhYsCgYEAwPaG 06QdK8Zyly7TTzZJwxzv9uGiqzodmGtX6NEKjgij2JaCxHpukqZBJoqa0jKeK1cm eNVkOvT5ff9TMzarSHQLr3pZen2/oVLb5gaFkbcJt/klv9Fd+ZRilHY3i6QwS6pD uMiPOWS4DrLHDRVoVlAZTDjT1RVwwTs+P2NhJdkCgYEAsriXysbxBYyMp05gqEW7 lHIFbFgpSrs9th+Q5U6wW6JEgYaHWDJ1NslY80MiZI93FWjbkbZ7BvBWESeL3EIL a+EMErht0pVCbIhZ6FF4foPAqia0wAJVx14mm+G80kNBp5jE/NnleEsE3KcO7nBb hg8gLn+x7bk81JZ0TDrzBYkCgYEAuQKluv47SeF3tSScTfKLPpvcKCWmxe1uutkQ 7JShPhVioyOMNb39jnYBOWbjkm4d4QgqRuiytSR0oi3QI+Ziy5EYMyNn713qAk9j r2TJZDDPDKnBW+zt4YI4EohWMXk3JRUW4XDKggjjwJQA7bZ812TtHHvP/xoThfG7 eSNb3eECgYBw6ssgCtMrdvQiEmjKVX/9yI38mvC2kSGyzbrQnGUfgqRGomRpeZuD B5E3kysA4td5pT5lvcLgSW0TbOz+YbiriXjwOihPIelCvc9gE2eOUI71/byUWPFz 7u5F/xQ4NaGr5suLF+lBC6h7pSbM4El9lIHQAQadpuEdzHqrw+hs3g== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/internal/v2/tlsconfigstore/tlsconfigstore.go000066400000000000000000000352211464711036600234270ustar00rootroot00000000000000/* * * 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 tlsconfigstore offloads operations to S2Av2. package tlsconfigstore import ( "crypto/tls" "crypto/x509" "encoding/pem" "errors" "fmt" "github.com/google/s2a-go/internal/tokenmanager" "github.com/google/s2a-go/internal/v2/certverifier" "github.com/google/s2a-go/internal/v2/remotesigner" "github.com/google/s2a-go/stream" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( // HTTP/2 h2 = "h2" ) // GetTLSConfigurationForClient returns a tls.Config instance for use by a client application. func GetTLSConfigurationForClient(serverHostname string, s2AStream stream.S2AStream, tokenManager tokenmanager.AccessTokenManager, localIdentity *commonpb.Identity, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, serverAuthorizationPolicy []byte) (*tls.Config, error) { authMechanisms := getAuthMechanisms(tokenManager, []*commonpb.Identity{localIdentity}) if grpclog.V(1) { grpclog.Infof("Sending request to S2Av2 for client TLS config.") } // Send request to S2Av2 for config. if err := s2AStream.Send(&s2av2pb.SessionReq{ LocalIdentity: localIdentity, AuthenticationMechanisms: authMechanisms, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_CLIENT, }, }, }); err != nil { grpclog.Infof("Failed to send request to S2Av2 for client TLS config") return nil, err } // Get the response containing config from S2Av2. resp, err := s2AStream.Recv() if err != nil { grpclog.Infof("Failed to receive client TLS config response from S2Av2.") return nil, err } // TODO(rmehta19): Add unit test for this if statement. if (resp.GetStatus() != nil) && (resp.GetStatus().Code != uint32(codes.OK)) { return nil, fmt.Errorf("failed to get TLS configuration from S2A: %d, %v", resp.GetStatus().Code, resp.GetStatus().Details) } // Extract TLS configiguration from SessionResp. tlsConfig := resp.GetGetTlsConfigurationResp().GetClientTlsConfiguration() var cert tls.Certificate for i, v := range tlsConfig.CertificateChain { // Populate Certificates field. block, _ := pem.Decode([]byte(v)) if block == nil { return nil, errors.New("certificate in CertificateChain obtained from S2Av2 is empty") } x509Cert, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, err } cert.Certificate = append(cert.Certificate, x509Cert.Raw) if i == 0 { cert.Leaf = x509Cert } } if len(tlsConfig.CertificateChain) > 0 { cert.PrivateKey = remotesigner.New(cert.Leaf, s2AStream) if cert.PrivateKey == nil { return nil, errors.New("failed to retrieve Private Key from Remote Signer Library") } } minVersion, maxVersion, err := getTLSMinMaxVersionsClient(tlsConfig) if err != nil { return nil, err } // Create mTLS credentials for client. config := &tls.Config{ VerifyPeerCertificate: certverifier.VerifyServerCertificateChain(serverHostname, verificationMode, s2AStream, serverAuthorizationPolicy), ServerName: serverHostname, InsecureSkipVerify: true, // NOLINT ClientSessionCache: nil, SessionTicketsDisabled: true, MinVersion: minVersion, MaxVersion: maxVersion, NextProtos: []string{h2}, } if len(tlsConfig.CertificateChain) > 0 { config.Certificates = []tls.Certificate{cert} } return config, nil } // GetTLSConfigurationForServer returns a tls.Config instance for use by a server application. func GetTLSConfigurationForServer(s2AStream stream.S2AStream, tokenManager tokenmanager.AccessTokenManager, localIdentities []*commonpb.Identity, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode) (*tls.Config, error) { return &tls.Config{ GetConfigForClient: ClientConfig(tokenManager, localIdentities, verificationMode, s2AStream), }, nil } // ClientConfig builds a TLS config for a server to establish a secure // connection with a client, based on SNI communicated during ClientHello. // Ensures that server presents the correct certificate to establish a TLS // connection. func ClientConfig(tokenManager tokenmanager.AccessTokenManager, localIdentities []*commonpb.Identity, verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode, s2AStream stream.S2AStream) func(chi *tls.ClientHelloInfo) (*tls.Config, error) { return func(chi *tls.ClientHelloInfo) (*tls.Config, error) { tlsConfig, err := getServerConfigFromS2Av2(tokenManager, localIdentities, chi.ServerName, s2AStream) if err != nil { return nil, err } var cert tls.Certificate for i, v := range tlsConfig.CertificateChain { // Populate Certificates field. block, _ := pem.Decode([]byte(v)) if block == nil { return nil, errors.New("certificate in CertificateChain obtained from S2Av2 is empty") } x509Cert, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, err } cert.Certificate = append(cert.Certificate, x509Cert.Raw) if i == 0 { cert.Leaf = x509Cert } } cert.PrivateKey = remotesigner.New(cert.Leaf, s2AStream) if cert.PrivateKey == nil { return nil, errors.New("failed to retrieve Private Key from Remote Signer Library") } minVersion, maxVersion, err := getTLSMinMaxVersionsServer(tlsConfig) if err != nil { return nil, err } clientAuth := getTLSClientAuthType(tlsConfig) var cipherSuites []uint16 cipherSuites = getCipherSuites(tlsConfig.Ciphersuites) // Create mTLS credentials for server. return &tls.Config{ Certificates: []tls.Certificate{cert}, VerifyPeerCertificate: certverifier.VerifyClientCertificateChain(verificationMode, s2AStream), ClientAuth: clientAuth, CipherSuites: cipherSuites, SessionTicketsDisabled: true, MinVersion: minVersion, MaxVersion: maxVersion, NextProtos: []string{h2}, }, nil } } func getCipherSuites(tlsConfigCipherSuites []commonpb.Ciphersuite) []uint16 { var tlsGoCipherSuites []uint16 for _, v := range tlsConfigCipherSuites { s := getTLSCipherSuite(v) if s != 0xffff { tlsGoCipherSuites = append(tlsGoCipherSuites, s) } } return tlsGoCipherSuites } func getTLSCipherSuite(tlsCipherSuite commonpb.Ciphersuite) uint16 { switch tlsCipherSuite { case commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: return tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 case commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: return tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 case commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: return tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 case commonpb.Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256: return tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 case commonpb.Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384: return tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 case commonpb.Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: return tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 default: return 0xffff } } func getServerConfigFromS2Av2(tokenManager tokenmanager.AccessTokenManager, localIdentities []*commonpb.Identity, sni string, s2AStream stream.S2AStream) (*s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration, error) { authMechanisms := getAuthMechanisms(tokenManager, localIdentities) var locID *commonpb.Identity if localIdentities != nil { locID = localIdentities[0] } if err := s2AStream.Send(&s2av2pb.SessionReq{ LocalIdentity: locID, AuthenticationMechanisms: authMechanisms, ReqOneof: &s2av2pb.SessionReq_GetTlsConfigurationReq{ GetTlsConfigurationReq: &s2av2pb.GetTlsConfigurationReq{ ConnectionSide: commonpb.ConnectionSide_CONNECTION_SIDE_SERVER, Sni: sni, }, }, }); err != nil { return nil, err } resp, err := s2AStream.Recv() if err != nil { return nil, err } // TODO(rmehta19): Add unit test for this if statement. if (resp.GetStatus() != nil) && (resp.GetStatus().Code != uint32(codes.OK)) { return nil, fmt.Errorf("failed to get TLS configuration from S2A: %d, %v", resp.GetStatus().Code, resp.GetStatus().Details) } return resp.GetGetTlsConfigurationResp().GetServerTlsConfiguration(), nil } func getTLSClientAuthType(tlsConfig *s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration) tls.ClientAuthType { var clientAuth tls.ClientAuthType switch x := tlsConfig.RequestClientCertificate; x { case s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_DONT_REQUEST_CLIENT_CERTIFICATE: clientAuth = tls.NoClientCert case s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: clientAuth = tls.RequestClientCert case s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: // This case actually maps to tls.VerifyClientCertIfGiven. However this // mapping triggers normal verification, followed by custom verification, // specified in VerifyPeerCertificate. To bypass normal verification, and // only do custom verification we set clientAuth to RequireAnyClientCert or // RequestClientCert. See https://github.com/google/s2a-go/pull/43 for full // discussion. clientAuth = tls.RequireAnyClientCert case s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: clientAuth = tls.RequireAnyClientCert case s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: // This case actually maps to tls.RequireAndVerifyClientCert. However this // mapping triggers normal verification, followed by custom verification, // specified in VerifyPeerCertificate. To bypass normal verification, and // only do custom verification we set clientAuth to RequireAnyClientCert or // RequestClientCert. See https://github.com/google/s2a-go/pull/43 for full // discussion. clientAuth = tls.RequireAnyClientCert default: clientAuth = tls.RequireAnyClientCert } return clientAuth } func getAuthMechanisms(tokenManager tokenmanager.AccessTokenManager, localIdentities []*commonpb.Identity) []*s2av2pb.AuthenticationMechanism { if tokenManager == nil { return nil } if len(localIdentities) == 0 { token, err := tokenManager.DefaultToken() if err != nil { grpclog.Infof("Unable to get token for empty local identity: %v", err) return nil } return []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{ Token: token, }, }, } } var authMechanisms []*s2av2pb.AuthenticationMechanism for _, localIdentity := range localIdentities { if localIdentity == nil { token, err := tokenManager.DefaultToken() if err != nil { grpclog.Infof("Unable to get default token for local identity %v: %v", localIdentity, err) continue } authMechanisms = append(authMechanisms, &s2av2pb.AuthenticationMechanism{ Identity: localIdentity, MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{ Token: token, }, }) } else { token, err := tokenManager.Token(localIdentity) if err != nil { grpclog.Infof("Unable to get token for local identity %v: %v", localIdentity, err) continue } authMechanisms = append(authMechanisms, &s2av2pb.AuthenticationMechanism{ Identity: localIdentity, MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{ Token: token, }, }) } } return authMechanisms } // TODO(rmehta19): refactor switch statements into a helper function. func getTLSMinMaxVersionsClient(tlsConfig *s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration) (uint16, uint16, error) { // Map S2Av2 TLSVersion to consts defined in tls package. var minVersion uint16 var maxVersion uint16 switch x := tlsConfig.MinTlsVersion; x { case commonpb.TLSVersion_TLS_VERSION_1_0: minVersion = tls.VersionTLS10 case commonpb.TLSVersion_TLS_VERSION_1_1: minVersion = tls.VersionTLS11 case commonpb.TLSVersion_TLS_VERSION_1_2: minVersion = tls.VersionTLS12 case commonpb.TLSVersion_TLS_VERSION_1_3: minVersion = tls.VersionTLS13 default: return minVersion, maxVersion, fmt.Errorf("S2Av2 provided invalid MinTlsVersion: %v", x) } switch x := tlsConfig.MaxTlsVersion; x { case commonpb.TLSVersion_TLS_VERSION_1_0: maxVersion = tls.VersionTLS10 case commonpb.TLSVersion_TLS_VERSION_1_1: maxVersion = tls.VersionTLS11 case commonpb.TLSVersion_TLS_VERSION_1_2: maxVersion = tls.VersionTLS12 case commonpb.TLSVersion_TLS_VERSION_1_3: maxVersion = tls.VersionTLS13 default: return minVersion, maxVersion, fmt.Errorf("S2Av2 provided invalid MaxTlsVersion: %v", x) } if minVersion > maxVersion { return minVersion, maxVersion, errors.New("S2Av2 provided minVersion > maxVersion") } return minVersion, maxVersion, nil } func getTLSMinMaxVersionsServer(tlsConfig *s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration) (uint16, uint16, error) { // Map S2Av2 TLSVersion to consts defined in tls package. var minVersion uint16 var maxVersion uint16 switch x := tlsConfig.MinTlsVersion; x { case commonpb.TLSVersion_TLS_VERSION_1_0: minVersion = tls.VersionTLS10 case commonpb.TLSVersion_TLS_VERSION_1_1: minVersion = tls.VersionTLS11 case commonpb.TLSVersion_TLS_VERSION_1_2: minVersion = tls.VersionTLS12 case commonpb.TLSVersion_TLS_VERSION_1_3: minVersion = tls.VersionTLS13 default: return minVersion, maxVersion, fmt.Errorf("S2Av2 provided invalid MinTlsVersion: %v", x) } switch x := tlsConfig.MaxTlsVersion; x { case commonpb.TLSVersion_TLS_VERSION_1_0: maxVersion = tls.VersionTLS10 case commonpb.TLSVersion_TLS_VERSION_1_1: maxVersion = tls.VersionTLS11 case commonpb.TLSVersion_TLS_VERSION_1_2: maxVersion = tls.VersionTLS12 case commonpb.TLSVersion_TLS_VERSION_1_3: maxVersion = tls.VersionTLS13 default: return minVersion, maxVersion, fmt.Errorf("S2Av2 provided invalid MaxTlsVersion: %v", x) } if minVersion > maxVersion { return minVersion, maxVersion, errors.New("S2Av2 provided minVersion > maxVersion") } return minVersion, maxVersion, nil } s2a-go-0.1.8/internal/v2/tlsconfigstore/tlsconfigstore_test.go000066400000000000000000001014051464711036600244640ustar00rootroot00000000000000/* * * 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 tlsconfigstore import ( "bytes" "context" "crypto/tls" "errors" "fmt" "log" "net" "sync" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/s2a-go/internal/tokenmanager" "github.com/google/s2a-go/internal/v2/fakes2av2" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/protobuf/testing/protocmp" _ "embed" commonpbv1 "github.com/google/s2a-go/internal/proto/common_go_proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( defaultTimeout = 10.0 * time.Second ) var ( //go:embed testdata/client_cert.pem clientCertpem []byte //go:embed testdata/server_cert.pem serverCertpem []byte //go:embed testdata/client_key.pem clientKeypem []byte //go:embed testdata/server_key.pem serverKeypem []byte ) // fakeAccessTokenManager implements the AccessTokenManager interface. type fakeAccessTokenManager struct { acceptedIdentity *commonpb.Identity accessToken string allowEmptyIdentity bool } // DefaultToken returns the token managed by the fakeAccessTokenManager. func (m *fakeAccessTokenManager) DefaultToken() (string, error) { if !m.allowEmptyIdentity { return "", fmt.Errorf("not allowed to get token for empty identity") } return m.accessToken, nil } // Token returns the token managed by the fakeAccessTokenManager. func (m *fakeAccessTokenManager) Token(identity interface{}) (string, error) { switch v := identity.(type) { case *commonpbv1.Identity: // valid type. case *commonpb.Identity: // valid type. default: return "", fmt.Errorf("Incorrect identity type: %v", v) } if identity == nil || cmp.Equal(identity, &commonpb.Identity{}, protocmp.Transform()) { if !m.allowEmptyIdentity { return "", fmt.Errorf("not allowed to get token for empty identity") } return m.accessToken, nil } if cmp.Equal(identity, m.acceptedIdentity, protocmp.Transform()) { return m.accessToken, nil } return "", fmt.Errorf("unable to get token") } func startFakeS2Av2Server(wg *sync.WaitGroup, expToken string, shouldNotReturnClientCreds bool) (stop func(), address string, err error) { listener, err := net.Listen("tcp", ":0") if err != nil { log.Fatalf("Failed to listen on address %s: %v", address, err) } address = listener.Addr().String() s := grpc.NewServer() log.Printf("Server: started gRPC fake S2Av2 Server on address: %s", address) s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ ExpectedToken: expToken, ShouldNotReturnClientCredentials: shouldNotReturnClientCreds, }) go func() { wg.Done() if err := s.Serve(listener); err != nil { log.Printf("Failed to serve: %v", err) } }() return func() { s.Stop() }, address, nil } // TestTLSConfigStoreClient runs unit tests for GetTLSConfigurationForClient. func TestTLSConfigStoreClient(t *testing.T) { // Setup for static client test. cert, err := tls.X509KeyPair(clientCertpem, clientKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, "TestTlsConfigStoreClient_token", false) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } accessTokenManager := &fakeAccessTokenManager{ allowEmptyIdentity: true, accessToken: "TestTlsConfigStoreClient_token", } for _, tc := range []struct { description string tokenManager tokenmanager.AccessTokenManager Certificates []tls.Certificate ServerName string InsecureSkipVerify bool SessionTicketsDisabled bool ClientSessionCache tls.ClientSessionCache MinVersion uint16 MaxVersion uint16 NextProtos []string }{ { description: "static - nil tokenManager", tokenManager: nil, Certificates: []tls.Certificate{cert}, ServerName: "host", InsecureSkipVerify: true, // NOLINT SessionTicketsDisabled: true, ClientSessionCache: nil, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, NextProtos: []string{"h2"}, }, { description: "static - non-nil tokenManager", tokenManager: accessTokenManager, Certificates: []tls.Certificate{cert}, ServerName: "host", InsecureSkipVerify: true, // NOLINT SessionTicketsDisabled: true, ClientSessionCache: nil, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, NextProtos: []string{"h2"}, }, } { t.Run(tc.description, func(t *testing.T) { // Create stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") config, err := GetTLSConfigurationForClient(tc.ServerName, cstream, tc.tokenManager, nil, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil) if err != nil { t.Errorf("GetTLSConfigurationForClient failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], tc.Certificates[0].Certificate[0]; !bytes.Equal(got, want) { t.Errorf("config.Certificates[0].Certificate[0] = %v, want %v", got, want) } if got, want := config.InsecureSkipVerify, tc.InsecureSkipVerify; got != want { t.Errorf("config.InsecureSkipVerify = %v, want %v", got, want) } if got, want := config.SessionTicketsDisabled, tc.SessionTicketsDisabled; got != want { t.Errorf("config.SessionTicketsDisabled = %v, want %v", got, want) } if got, want := config.ClientSessionCache, tc.ClientSessionCache; got != want { t.Errorf("config.ClientSessionCache = %v, want %v", got, want) } if got, want := config.MinVersion, tc.MinVersion; got != want { t.Errorf("config.MinVersion = %v, want %v", got, want) } if got, want := config.MaxVersion, tc.MaxVersion; got != want { t.Errorf("config.MaxVersion = %v, want %v", got, want) } if !compareNextProtos(config.NextProtos, tc.NextProtos) { t.Errorf("config.NextProtos = %v, want %v", config.NextProtos, tc.NextProtos) } }) } stop() } // TestTLSConfigStoreClientWithoutCredentials runs unit tests for // GetTLSConfigurationForClient, but does not expect the TLS configuration // to contain any client credentials. func TestTLSConfigStoreClientWithoutCredentials(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, "", true) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } // Create stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") config, err := GetTLSConfigurationForClient("hostname", cstream, nil, nil, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, nil) if err != nil { t.Errorf("GetTLSConfigurationForClient failed: %v", err) } if len(config.Certificates) > 0 { t.Errorf("config had unexpected number of certificates") } if got, want := config.InsecureSkipVerify, true; got != want { t.Errorf("config.InsecureSkipVerify = %v, want %v", got, want) } if got, want := config.SessionTicketsDisabled, true; got != want { t.Errorf("config.SessionTicketsDisabled = %v, want %v", got, want) } if config.ClientSessionCache != nil { t.Errorf("config.ClientSessionCache expected to be nil") } if got, want := int(config.MinVersion), tls.VersionTLS13; got != want { t.Errorf("config.MinVersion = %v, want %v", got, want) } if got, want := int(config.MaxVersion), tls.VersionTLS13; got != want { t.Errorf("config.MaxVersion = %v, want %v", got, want) } if !compareNextProtos(config.NextProtos, []string{"h2"}) { t.Errorf("config.NextProtos = %v, want %v", config.NextProtos, []string{"h2"}) } stop() } // TestTLSConfigStoreServer runs unit tests for GetTLSConfigurationForServer. func TestTLSConfigStoreServer(t *testing.T) { // Setup for static server test. cert, err := tls.X509KeyPair(serverCertpem, serverKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, "TestTlsConfigStoreServer_token", false) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } accessTokenManager := &fakeAccessTokenManager{ allowEmptyIdentity: true, accessToken: "TestTlsConfigStoreServer_token", } var identities []*commonpb.Identity identities = append(identities, nil) for _, tc := range []struct { description string tokenManager tokenmanager.AccessTokenManager Certificates []tls.Certificate SessionTicketsDisabled bool ClientAuth tls.ClientAuthType MinVersion uint16 MaxVersion uint16 NextProtos []string }{ { description: "static - nil tokenManager", tokenManager: nil, Certificates: []tls.Certificate{cert}, SessionTicketsDisabled: true, ClientAuth: tls.RequireAnyClientCert, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, NextProtos: []string{"h2"}, }, { description: "static - non-nil tokenManager", tokenManager: accessTokenManager, Certificates: []tls.Certificate{cert}, SessionTicketsDisabled: true, ClientAuth: tls.RequireAnyClientCert, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, NextProtos: []string{"h2"}, }, } { t.Run(tc.description, func(t *testing.T) { // Create stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") config, err := GetTLSConfigurationForServer(cstream, tc.tokenManager, identities, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE) if err != nil { t.Errorf("GetTLSConfigurationForClient failed: %v", err) } clientConfigFunc := config.GetConfigForClient config, err = clientConfigFunc(&tls.ClientHelloInfo{ ServerName: "host_1", }) if err != nil { t.Errorf("ClientConfig failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], tc.Certificates[0].Certificate[0]; !bytes.Equal(got, want) { t.Errorf("config.Certificates[0].Certificate[0] = %v, want %v", got, want) } if got, want := config.SessionTicketsDisabled, tc.SessionTicketsDisabled; got != want { t.Errorf("config.SessionTicketsDisabled = %v, want %v", got, want) } if got, want := config.ClientAuth, tc.ClientAuth; got != want { t.Errorf("config.ClientAuth = %v, want %v", got, want) } if got, want := config.MinVersion, tc.MinVersion; got != want { t.Errorf("config.MinVersion = %v, want %v", got, want) } if got, want := config.MaxVersion, tc.MaxVersion; got != want { t.Errorf("config.MaxVersion = %v, want %v", got, want) } if !compareNextProtos(config.NextProtos, tc.NextProtos) { t.Errorf("config.NextProtos = %v, want %v", config.NextProtos, tc.NextProtos) } }) } stop() } func TestGetTLSMinMaxVersionsClient(t *testing.T) { m := makeMapOfTLSVersions() for min := commonpb.TLSVersion_TLS_VERSION_1_0; min <= commonpb.TLSVersion_TLS_VERSION_1_3; min++ { for max := commonpb.TLSVersion_TLS_VERSION_1_0; max <= commonpb.TLSVersion_TLS_VERSION_1_3; max++ { tlsConfig := &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ MinTlsVersion: min, MaxTlsVersion: max, } tlsMin, tlsMax, err := getTLSMinMaxVersionsServer(tlsConfig) if err != nil { if min <= max { t.Errorf("err = %v, expected err = nil", err) } else { if m[min] != tlsMin { t.Errorf("tlsMin = %v, expected %v", tlsMin, m[min]) } if m[max] != tlsMax { t.Errorf("tlsMax = %v, expected %v", tlsMax, m[max]) } } } else { if min > max { t.Errorf("err = nil, expected err = S2Av2 provided minVersion > maxVersion.") } else { if m[min] != tlsMin { t.Errorf("tlsMin = %v, expected %v", tlsMin, m[min]) } if m[max] != tlsMax { t.Errorf("tlsMax = %v, expected %v", tlsMax, m[max]) } } } } } // Test invalid input. tlsConfig := &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration{ MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_0 - 1, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, } expErr := fmt.Errorf("S2Av2 provided invalid MinTlsVersion: %v", tlsConfig.MinTlsVersion) _, _, err := getTLSMinMaxVersionsClient(tlsConfig) if (err == nil) || (err.Error() != expErr.Error()) { t.Errorf("err = %v, expErr = %v", err, expErr) } tlsConfig = &s2av2pb.GetTlsConfigurationResp_ClientTlsConfiguration{ MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_0, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3 + 1, } expErr = fmt.Errorf("S2Av2 provided invalid MaxTlsVersion: %v", tlsConfig.MaxTlsVersion) _, _, err = getTLSMinMaxVersionsClient(tlsConfig) if (err == nil) || (err.Error() != expErr.Error()) { t.Errorf("err = %v, expErr = %v", err, expErr) } } func TestGetTLSMinMaxVersionsServer(t *testing.T) { m := makeMapOfTLSVersions() for min := commonpb.TLSVersion_TLS_VERSION_1_0; min <= commonpb.TLSVersion_TLS_VERSION_1_3; min++ { for max := commonpb.TLSVersion_TLS_VERSION_1_0; max <= commonpb.TLSVersion_TLS_VERSION_1_3; max++ { tlsConfig := &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ MinTlsVersion: min, MaxTlsVersion: max, } tlsMin, tlsMax, err := getTLSMinMaxVersionsServer(tlsConfig) if err != nil { if min <= max { t.Errorf("err = %v, expected err = nil", err) } else { if m[min] != tlsMin { t.Errorf("tlsMin = %v, expected %v", tlsMin, m[min]) } if m[max] != tlsMax { t.Errorf("tlsMax = %v, expected %v", tlsMax, m[max]) } } } else { if min > max { t.Errorf("err = nil, expected err = S2Av2 provided minVersion > maxVersion.") } else { if m[min] != tlsMin { t.Errorf("tlsMin = %v, expected %v", tlsMin, m[min]) } if m[max] != tlsMax { t.Errorf("tlsMax = %v, expected %v", tlsMax, m[max]) } } } } } // Test invalid input. tlsConfig := &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_0 - 1, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, } expErr := fmt.Errorf("S2Av2 provided invalid MinTlsVersion: %v", tlsConfig.MinTlsVersion) _, _, err := getTLSMinMaxVersionsServer(tlsConfig) if (err == nil) || (err.Error() != expErr.Error()) { t.Errorf("err = %v, expErr = %v", err, expErr) } tlsConfig = &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_0, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3 + 1, } expErr = fmt.Errorf("S2Av2 provided invalid MaxTlsVersion: %v", tlsConfig.MaxTlsVersion) _, _, err = getTLSMinMaxVersionsServer(tlsConfig) if (err == nil) || (err.Error() != expErr.Error()) { t.Errorf("err = %v, expErr = %v", err, expErr) } } func TestGetAuthMechanisms(t *testing.T) { // Setup data for test. sortProtos := cmpopts.SortSlices(func(m1, m2 *s2av2pb.AuthenticationMechanism) bool { return m1.String() < m2.String() }) // TODO(rmehta19): Add additional tests. for _, tc := range []struct { description string tokenManager tokenmanager.AccessTokenManager localIdentities []*commonpb.Identity expectedAuthMechanisms []*s2av2pb.AuthenticationMechanism }{ { description: "fake token manager is nil", tokenManager: nil, expectedAuthMechanisms: nil, }, { description: "fake token manager allows empty identity", tokenManager: &fakeAccessTokenManager{ accessToken: "TestGetAuthMechanisms_s2a_access_token", allowEmptyIdentity: true, }, expectedAuthMechanisms: []*s2av2pb.AuthenticationMechanism{ { MechanismOneof: &s2av2pb.AuthenticationMechanism_Token{ Token: "TestGetAuthMechanisms_s2a_access_token", }, }, }, }, { description: "fake token manager does not allow empty identity", tokenManager: &fakeAccessTokenManager{ allowEmptyIdentity: false, }, expectedAuthMechanisms: nil, }, } { t.Run(tc.description, func(t *testing.T) { authMechanisms := getAuthMechanisms(tc.tokenManager, tc.localIdentities) if got, want := (authMechanisms == nil), (tc.expectedAuthMechanisms == nil); got != want { t.Errorf("authMechanisms == nil: %t, tc.expectedAuthMechanisms == nil: %t", got, want) } if authMechanisms != nil && tc.expectedAuthMechanisms != nil { if diff := cmp.Diff(authMechanisms, tc.expectedAuthMechanisms, protocmp.Transform(), sortProtos); diff != "" { t.Errorf("getAuthMechanisms(%v, %v) returned incorrect slice, (-want +got):\n%s", tc.tokenManager, tc.localIdentities, diff) } } }) } } func TestGetServerConfigFromS2Av2(t *testing.T) { // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, "TestGetServerConfigFromS2Av2_token", false) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } for _, tc := range []struct { description string tokenManager tokenmanager.AccessTokenManager localIdentities []*commonpb.Identity expTLSConfig *s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration expErr error }{ { description: "empty accessToken and empty localIdentities", tokenManager: &fakeAccessTokenManager{ allowEmptyIdentity: true, accessToken: "", }, localIdentities: nil, expErr: errors.New("rpc error: code = Unknown desc = SessionReq has no AuthenticationMechanism with a valid token"), }, { description: "invalid accessToken", tokenManager: &fakeAccessTokenManager{ acceptedIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "server_hostname", }, }, allowEmptyIdentity: true, accessToken: "invalid_access_token", }, localIdentities: []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "server_hostname", }, }, }, expErr: errors.New("rpc error: code = Unknown desc = SessionReq has no AuthenticationMechanism with a valid token"), }, { description: "correct accessToken and non - empty localIdentities", tokenManager: &fakeAccessTokenManager{ acceptedIdentity: &commonpb.Identity{ IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "server_hostname", }, }, allowEmptyIdentity: true, accessToken: "TestGetServerConfigFromS2Av2_token", }, localIdentities: []*commonpb.Identity{ { IdentityOneof: &commonpb.Identity_Hostname{ Hostname: "server_hostname", }, }, }, expTLSConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ CertificateChain: []string{ string(serverCertpem), }, MinTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, MaxTlsVersion: commonpb.TLSVersion_TLS_VERSION_1_3, TlsResumptionEnabled: false, RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, MaxOverheadOfTicketAead: 0, }, expErr: nil, }, } { t.Run(tc.description, func(t *testing.T) { // Create stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") gotTLSConfig, gotErr := getServerConfigFromS2Av2(tc.tokenManager, tc.localIdentities, "test_server_name", cstream) if gotErr != tc.expErr { if (gotErr == nil) || (tc.expErr == nil) { t.Errorf("gotErr = %v, tc.expErr = %v", gotErr, tc.expErr) } else if gotErr.Error() != tc.expErr.Error() { t.Errorf("gotErr = %v, tc.expErr = %v", gotErr, tc.expErr) } } if (gotErr == nil) && (tc.expErr == nil) { if diff := cmp.Diff(gotTLSConfig, tc.expTLSConfig, protocmp.Transform()); diff != "" { t.Errorf("getServerConfigFromS2Av2 returned incorrect GetTlsConfigurationResp_ServerTlsConfiguration, (-want +got):\n%s", diff) } } }) } stop() } func TestGetClientConfig(t *testing.T) { // Setup test. cert, err := tls.X509KeyPair(serverCertpem, serverKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } // Start up fake S2Av2 server. var wg sync.WaitGroup wg.Add(1) stop, address, err := startFakeS2Av2Server(&wg, "TestGetClientConfig_token", false) wg.Wait() if err != nil { t.Fatalf("Error starting fake S2Av2 Server: %v", err) } accessTokenManager := &fakeAccessTokenManager{ accessToken: "TestGetClientConfig_token", allowEmptyIdentity: true, } var identities []*commonpb.Identity identities = append(identities, nil) for _, tc := range []struct { description string Certificates []tls.Certificate SessionTicketsDisabled bool ClientAuth tls.ClientAuthType MinVersion uint16 MaxVersion uint16 NextProtos []string }{ { description: "static", Certificates: []tls.Certificate{cert}, SessionTicketsDisabled: true, ClientAuth: tls.RequireAnyClientCert, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, NextProtos: []string{"h2"}, }, } { t.Run(tc.description, func(t *testing.T) { // Create stream to S2Av2. opts := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithReturnConnectionError(), grpc.WithBlock(), } conn, err := grpc.Dial(address, opts...) if err != nil { t.Fatalf("Client: failed to connect: %v", err) } defer conn.Close() c := s2av2pb.NewS2AServiceClient(conn) log.Printf("Client: connected to: %s", address) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Setup bidrectional streaming session. callOpts := []grpc.CallOption{} cstream, err := c.SetUpSession(ctx, callOpts...) if err != nil { t.Fatalf("Client: failed to setup bidirectional streaming RPC session: %v", err) } log.Printf("Client: set up bidirectional streaming RPC session.") clientConfigFunc := ClientConfig(accessTokenManager, identities, s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, cstream) config, err := clientConfigFunc(&tls.ClientHelloInfo{ ServerName: "host_1", }) if err != nil { t.Errorf("ClientConfig failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], tc.Certificates[0].Certificate[0]; !bytes.Equal(got, want) { t.Errorf("config.Certificates[0].Certificate[0] = %v, want %v", got, want) } if got, want := config.SessionTicketsDisabled, tc.SessionTicketsDisabled; got != want { t.Errorf("config.SessionTicketsDisabled = %v, want %v", got, want) } if got, want := config.ClientAuth, tc.ClientAuth; got != want { t.Errorf("config.ClientAuth = %v, want %v", got, want) } if got, want := config.MinVersion, tc.MinVersion; got != want { t.Errorf("config.MinVersion = %v, want %v", got, want) } if got, want := config.MaxVersion, tc.MaxVersion; got != want { t.Errorf("config.MaxVersion = %v, want %v", got, want) } if !compareNextProtos(config.NextProtos, tc.NextProtos) { t.Errorf("config.NextProtos = %v, want %v", config.NextProtos, tc.NextProtos) } }) } stop() } func TestGetTLSClientAuthType(t *testing.T) { for _, tc := range []struct { description string tlsConfig *s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration expClientAuthType tls.ClientAuthType }{ { description: "Don't request client cert", tlsConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_DONT_REQUEST_CLIENT_CERTIFICATE, }, expClientAuthType: tls.NoClientCert, }, { description: "Request client cert, but don't verify", tlsConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, }, expClientAuthType: tls.RequestClientCert, }, { description: "Request client cert and verify", tlsConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY, }, expClientAuthType: tls.RequireAnyClientCert, }, { description: "Request and Require client cert, but don't verify", tlsConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY, }, expClientAuthType: tls.RequireAnyClientCert, }, { description: "Request and Require client cert and verify", tlsConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY, }, expClientAuthType: tls.RequireAnyClientCert, }, { description: "default case", tlsConfig: &s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration{ RequestClientCertificate: s2av2pb.GetTlsConfigurationResp_ServerTlsConfiguration_UNSPECIFIED, }, expClientAuthType: tls.RequireAnyClientCert, }, } { t.Run(tc.description, func(t *testing.T) { if got, want := getTLSClientAuthType(tc.tlsConfig), tc.expClientAuthType; got != want { t.Errorf("getClientAuthType(%v) returned %v, want = %v", tc.tlsConfig, got, want) } }) } } func TestGetTLSCipherSuite(t *testing.T) { for _, tc := range []struct { description string inp commonpb.Ciphersuite expOut uint16 }{ { description: "ECDSA with AES 128 GCM SHA256", inp: commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, expOut: tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, }, { description: "ECDSA with AES 256 GCM SHA384", inp: commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, expOut: tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, }, { description: "ECDSA with CHACHA20 Poly 1305 SHA256", inp: commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, expOut: tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, }, { description: "RSA with AES 128 GCM SHA256", inp: commonpb.Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_AES_128_GCM_SHA256, expOut: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, }, { description: "RSA with AES 256 GCM SHA384", inp: commonpb.Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_AES_256_GCM_SHA384, expOut: tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, }, { description: "RSA with CHACHA20 Poly1305 SHA256", inp: commonpb.Ciphersuite_CIPHERSUITE_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, expOut: tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, }, { description: "unspecified", inp: commonpb.Ciphersuite_CIPHERSUITE_UNSPECIFIED, expOut: 0xffff, }, } { t.Run(tc.description, func(t *testing.T) { if got, want := getTLSCipherSuite(tc.inp), tc.expOut; got != want { t.Errorf("getTLSCipherSuite(%v) returned %v, want %v", tc.inp, got, want) } }) } } func TestGetCipherSuites(t *testing.T) { for _, tc := range []struct { description string inp []commonpb.Ciphersuite expOut []uint16 }{ { description: "empty input", inp: []commonpb.Ciphersuite{}, expOut: []uint16{}, }, { description: "non - empty input array of size 1", inp: []commonpb.Ciphersuite{commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, expOut: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, }, { description: "non - empty input array of size 2", inp: []commonpb.Ciphersuite{commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, expOut: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, }, { description: "unspecified array of size 1", inp: []commonpb.Ciphersuite{commonpb.Ciphersuite_CIPHERSUITE_UNSPECIFIED}, expOut: []uint16{}, }, { description: "unspecified array of size 2", inp: []commonpb.Ciphersuite{commonpb.Ciphersuite_CIPHERSUITE_UNSPECIFIED, commonpb.Ciphersuite_CIPHERSUITE_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, expOut: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, }, } { t.Run(tc.description, func(t *testing.T) { if got, want := getCipherSuites(tc.inp), tc.expOut; !compareCipherSuites(got, want) { t.Errorf("getCipherSuites(%+v) returned %+v, want %+v", tc.inp, got, want) } }) } } func makeMapOfTLSVersions() map[commonpb.TLSVersion]uint16 { m := make(map[commonpb.TLSVersion]uint16) m[commonpb.TLSVersion_TLS_VERSION_1_0] = tls.VersionTLS10 m[commonpb.TLSVersion_TLS_VERSION_1_1] = tls.VersionTLS11 m[commonpb.TLSVersion_TLS_VERSION_1_2] = tls.VersionTLS12 m[commonpb.TLSVersion_TLS_VERSION_1_3] = tls.VersionTLS13 return m } func compareNextProtos(a, b []string) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } func compareCipherSuites(a, b []uint16) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } s2a-go-0.1.8/kokoro/000077500000000000000000000000001464711036600141245ustar00rootroot00000000000000s2a-go-0.1.8/kokoro/gcp_ubuntu/000077500000000000000000000000001464711036600162775ustar00rootroot00000000000000s2a-go-0.1.8/kokoro/gcp_ubuntu/continuous_gae_test.cfg000066400000000000000000000000711464711036600230370ustar00rootroot00000000000000build_file: "s2a-go/kokoro/gcp_ubuntu/kokoro_gae_test.sh"s2a-go-0.1.8/kokoro/gcp_ubuntu/continuous_golang.cfg000066400000000000000000000000761464711036600225200ustar00rootroot00000000000000build_file: "s2a-go/kokoro/gcp_ubuntu/kokoro_golang_build.sh" s2a-go-0.1.8/kokoro/gcp_ubuntu/continuous_hygiene.cfg000066400000000000000000000000711464711036600226740ustar00rootroot00000000000000build_file: "s2a-go/kokoro/gcp_ubuntu/kokoro_hygiene.sh" s2a-go-0.1.8/kokoro/gcp_ubuntu/kokoro_gae_test.sh000066400000000000000000000014141464711036600220120ustar00rootroot00000000000000# Copyright 2024 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. #!/bin/bash # Fail on any error. set -e # Display commands being run. set -x cd "${KOKORO_ARTIFACTS_DIR}/github/s2a-go" chmod a+rwx tools/internal_ci/run_gae_test.sh ./tools/internal_ci/run_gae_test.shs2a-go-0.1.8/kokoro/gcp_ubuntu/kokoro_golang_build.sh000077500000000000000000000013431464711036600226510ustar00rootroot00000000000000# 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. #!/bin/bash # Fail on any error. set -e # Display commands being run. set -x cd "${KOKORO_ARTIFACTS_DIR}/github/s2a-go" ./tools/internal_ci/run_golang_tests.sh s2a-go-0.1.8/kokoro/gcp_ubuntu/kokoro_hygiene.sh000066400000000000000000000013441464711036600216510ustar00rootroot00000000000000# 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. #!/bin/bash # Fail on any error. set -e # Display commands being run. set -x cd "${KOKORO_ARTIFACTS_DIR}/github/s2a-go" ./tools/internal_ci/run_hygiene_tests.sh s2a-go-0.1.8/kokoro/gcp_ubuntu/presubmit_golang.cfg000066400000000000000000000000761464711036600223240ustar00rootroot00000000000000build_file: "s2a-go/kokoro/gcp_ubuntu/kokoro_golang_build.sh" s2a-go-0.1.8/kokoro/gcp_ubuntu/presubmit_hygiene.cfg000066400000000000000000000000711464711036600225000ustar00rootroot00000000000000build_file: "s2a-go/kokoro/gcp_ubuntu/kokoro_hygiene.sh" s2a-go-0.1.8/kokoro/macos_external/000077500000000000000000000000001464711036600171305ustar00rootroot00000000000000s2a-go-0.1.8/kokoro/macos_external/continuous_golang.cfg000066400000000000000000000001021464711036600233370ustar00rootroot00000000000000build_file: "s2a-go/kokoro/macos_external/kokoro_golang_build.sh" s2a-go-0.1.8/kokoro/macos_external/kokoro_golang_build.sh000066400000000000000000000013431464711036600234770ustar00rootroot00000000000000# 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. #!/bin/bash # Fail on any error. set -e # Display commands being run. set -x cd "${KOKORO_ARTIFACTS_DIR}/github/s2a-go" ./tools/internal_ci/run_golang_tests.sh s2a-go-0.1.8/kokoro/macos_external/presubmit_golang.cfg000066400000000000000000000001021464711036600231430ustar00rootroot00000000000000build_file: "s2a-go/kokoro/macos_external/kokoro_golang_build.sh" s2a-go-0.1.8/retry/000077500000000000000000000000001464711036600137655ustar00rootroot00000000000000s2a-go-0.1.8/retry/retry.go000066400000000000000000000065771464711036600155000ustar00rootroot00000000000000/* * * Copyright 2023 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 retry provides a retry helper for talking to S2A gRPC server. // The implementation is modeled after // https://github.com/googleapis/google-cloud-go/blob/main/compute/metadata/retry.go package retry import ( "context" "math/rand" "time" "google.golang.org/grpc/grpclog" ) const ( maxRetryAttempts = 5 maxRetryForLoops = 10 ) type defaultBackoff struct { max time.Duration mul float64 cur time.Duration } // Pause returns a duration, which is used as the backoff wait time // before the next retry. func (b *defaultBackoff) Pause() time.Duration { d := time.Duration(1 + rand.Int63n(int64(b.cur))) b.cur = time.Duration(float64(b.cur) * b.mul) if b.cur > b.max { b.cur = b.max } return d } // Sleep will wait for the specified duration or return on context // expiration. func Sleep(ctx context.Context, d time.Duration) error { t := time.NewTimer(d) select { case <-ctx.Done(): t.Stop() return ctx.Err() case <-t.C: return nil } } // NewRetryer creates an instance of S2ARetryer using the defaultBackoff // implementation. var NewRetryer = func() *S2ARetryer { return &S2ARetryer{bo: &defaultBackoff{ cur: 100 * time.Millisecond, max: 30 * time.Second, mul: 2, }} } type backoff interface { Pause() time.Duration } // S2ARetryer implements a retry helper for talking to S2A gRPC server. type S2ARetryer struct { bo backoff attempts int } // Attempts return the number of retries attempted. func (r *S2ARetryer) Attempts() int { return r.attempts } // Retry returns a boolean indicating whether retry should be performed // and the backoff duration. func (r *S2ARetryer) Retry(err error) (time.Duration, bool) { if err == nil { return 0, false } if r.attempts >= maxRetryAttempts { return 0, false } r.attempts++ return r.bo.Pause(), true } // Run uses S2ARetryer to execute the function passed in, until success or reaching // max number of retry attempts. func Run(ctx context.Context, f func() error) { retryer := NewRetryer() forLoopCnt := 0 var err error for { err = f() if bo, shouldRetry := retryer.Retry(err); shouldRetry { if grpclog.V(1) { grpclog.Infof("will attempt retry: %v", err) } if ctx.Err() != nil { if grpclog.V(1) { grpclog.Infof("exit retry loop due to context error: %v", ctx.Err()) } break } if errSleep := Sleep(ctx, bo); errSleep != nil { if grpclog.V(1) { grpclog.Infof("exit retry loop due to sleep error: %v", errSleep) } break } // This shouldn't happen, just make sure we are not stuck in the for loops. forLoopCnt++ if forLoopCnt > maxRetryForLoops { if grpclog.V(1) { grpclog.Infof("exit the for loop after too many retries") } break } continue } if grpclog.V(1) { grpclog.Infof("retry conditions not met, exit the loop") } break } } s2a-go-0.1.8/retry/retry_test.go000066400000000000000000000055711464711036600165300ustar00rootroot00000000000000/* * * Copyright 2023 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 retry import ( "context" "errors" "testing" "time" ) var errTest error = errors.New("test error") type constantBackoff struct{} func (b constantBackoff) Pause() time.Duration { return 100 } func TestS2ARetryer(t *testing.T) { tests := []struct { name string err error wantDelay time.Duration wantShouldRetry bool }{ { name: "retry on err", err: errTest, wantDelay: 100, wantShouldRetry: true, }, { name: "don't retry if err is nil", err: nil, wantDelay: 0, wantShouldRetry: false, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { retryer := S2ARetryer{bo: constantBackoff{}} delay, shouldRetry := retryer.Retry(tc.err) if delay != tc.wantDelay { t.Fatalf("retryer.Retry(%v) = %v, want %v", tc.err, delay, tc.wantDelay) } if shouldRetry != tc.wantShouldRetry { t.Fatalf("retryer.Retry(%v) = %v, want %v", tc.err, shouldRetry, tc.wantShouldRetry) } }) } } func TestS2ARetryerAttempts(t *testing.T) { retryer := S2ARetryer{bo: constantBackoff{}} for i := 1; i <= 5; i++ { _, shouldRetry := retryer.Retry(errTest) if !shouldRetry { t.Fatalf("retryer.Retry(errTest) = false, want true") } } _, shouldRetry := retryer.Retry(errTest) if shouldRetry { t.Fatal("an error should only be retried 5 times") } } func TestDefaultBackoff(t *testing.T) { bo := defaultBackoff{ cur: 100 * time.Millisecond, max: 30 * time.Second, mul: 2, } pauseOne := bo.Pause() pauseTwo := bo.Pause() if pauseOne > 100*time.Millisecond { t.Fatal("first backoff should be less than 100 milli seconds") } if pauseTwo > 2*100*time.Millisecond { t.Fatal("second backoff should be less than 200 milli seconds") } } func TestSuccessAfterRetry(t *testing.T) { oldRetry := NewRetryer defer func() { NewRetryer = oldRetry }() testRetryer := NewRetryer() NewRetryer = func() *S2ARetryer { return testRetryer } cnt := 1 f := func() error { if cnt == 1 { cnt++ return errTest } return nil } if testRetryer.Attempts() != 0 { t.Fatal("before execution, retry attempt count should be 0") } Run(context.Background(), f) if testRetryer.Attempts() != 1 { t.Fatal("execution should've succeeded after 1 retry") } } s2a-go-0.1.8/s2a.go000066400000000000000000000364041464711036600136430ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a provides the S2A transport credentials used by a gRPC // application. package s2a import ( "context" "crypto/tls" "errors" "fmt" "net" "sync" "time" "github.com/google/s2a-go/fallback" "github.com/google/s2a-go/internal/handshaker" "github.com/google/s2a-go/internal/handshaker/service" "github.com/google/s2a-go/internal/tokenmanager" "github.com/google/s2a-go/internal/v2" "github.com/google/s2a-go/retry" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" "google.golang.org/protobuf/proto" commonpbv1 "github.com/google/s2a-go/internal/proto/common_go_proto" commonpb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( s2aSecurityProtocol = "tls" // defaultTimeout specifies the default server handshake timeout. defaultTimeout = 30.0 * time.Second ) // s2aTransportCreds are the transport credentials required for establishing // a secure connection using the S2A. They implement the // credentials.TransportCredentials interface. type s2aTransportCreds struct { info *credentials.ProtocolInfo minTLSVersion commonpbv1.TLSVersion maxTLSVersion commonpbv1.TLSVersion // tlsCiphersuites contains the ciphersuites used in the S2A connection. // Note that these are currently unconfigurable. tlsCiphersuites []commonpbv1.Ciphersuite // localIdentity should only be used by the client. localIdentity *commonpbv1.Identity // localIdentities should only be used by the server. localIdentities []*commonpbv1.Identity // targetIdentities should only be used by the client. targetIdentities []*commonpbv1.Identity isClient bool s2aAddr string ensureProcessSessionTickets *sync.WaitGroup } // NewClientCreds returns a client-side transport credentials object that uses // the S2A to establish a secure connection with a server. func NewClientCreds(opts *ClientOptions) (credentials.TransportCredentials, error) { if opts == nil { return nil, errors.New("nil client options") } var targetIdentities []*commonpbv1.Identity for _, targetIdentity := range opts.TargetIdentities { protoTargetIdentity, err := toProtoIdentity(targetIdentity) if err != nil { return nil, err } targetIdentities = append(targetIdentities, protoTargetIdentity) } localIdentity, err := toProtoIdentity(opts.LocalIdentity) if err != nil { return nil, err } if opts.EnableLegacyMode { return &s2aTransportCreds{ info: &credentials.ProtocolInfo{ SecurityProtocol: s2aSecurityProtocol, }, minTLSVersion: commonpbv1.TLSVersion_TLS1_3, maxTLSVersion: commonpbv1.TLSVersion_TLS1_3, tlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, localIdentity: localIdentity, targetIdentities: targetIdentities, isClient: true, s2aAddr: opts.S2AAddress, ensureProcessSessionTickets: opts.EnsureProcessSessionTickets, }, nil } verificationMode := getVerificationMode(opts.VerificationMode) var fallbackFunc fallback.ClientHandshake if opts.FallbackOpts != nil && opts.FallbackOpts.FallbackClientHandshakeFunc != nil { fallbackFunc = opts.FallbackOpts.FallbackClientHandshakeFunc } v2LocalIdentity, err := toV2ProtoIdentity(opts.LocalIdentity) if err != nil { return nil, err } return v2.NewClientCreds(opts.S2AAddress, opts.TransportCreds, v2LocalIdentity, verificationMode, fallbackFunc, opts.getS2AStream, opts.serverAuthorizationPolicy) } // NewServerCreds returns a server-side transport credentials object that uses // the S2A to establish a secure connection with a client. func NewServerCreds(opts *ServerOptions) (credentials.TransportCredentials, error) { if opts == nil { return nil, errors.New("nil server options") } var localIdentities []*commonpbv1.Identity for _, localIdentity := range opts.LocalIdentities { protoLocalIdentity, err := toProtoIdentity(localIdentity) if err != nil { return nil, err } localIdentities = append(localIdentities, protoLocalIdentity) } if opts.EnableLegacyMode { return &s2aTransportCreds{ info: &credentials.ProtocolInfo{ SecurityProtocol: s2aSecurityProtocol, }, minTLSVersion: commonpbv1.TLSVersion_TLS1_3, maxTLSVersion: commonpbv1.TLSVersion_TLS1_3, tlsCiphersuites: []commonpbv1.Ciphersuite{ commonpbv1.Ciphersuite_AES_128_GCM_SHA256, commonpbv1.Ciphersuite_AES_256_GCM_SHA384, commonpbv1.Ciphersuite_CHACHA20_POLY1305_SHA256, }, localIdentities: localIdentities, isClient: false, s2aAddr: opts.S2AAddress, }, nil } verificationMode := getVerificationMode(opts.VerificationMode) var v2LocalIdentities []*commonpb.Identity for _, localIdentity := range opts.LocalIdentities { protoLocalIdentity, err := toV2ProtoIdentity(localIdentity) if err != nil { return nil, err } v2LocalIdentities = append(v2LocalIdentities, protoLocalIdentity) } return v2.NewServerCreds(opts.S2AAddress, opts.TransportCreds, v2LocalIdentities, verificationMode, opts.getS2AStream) } // ClientHandshake initiates a client-side TLS handshake using the S2A. func (c *s2aTransportCreds) ClientHandshake(ctx context.Context, serverAuthority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { if !c.isClient { return nil, nil, errors.New("client handshake called using server transport credentials") } var cancel context.CancelFunc ctx, cancel = context.WithCancel(ctx) defer cancel() // Connect to the S2A. hsConn, err := service.Dial(ctx, c.s2aAddr, nil) if err != nil { grpclog.Infof("Failed to connect to S2A: %v", err) return nil, nil, err } opts := &handshaker.ClientHandshakerOptions{ MinTLSVersion: c.minTLSVersion, MaxTLSVersion: c.maxTLSVersion, TLSCiphersuites: c.tlsCiphersuites, TargetIdentities: c.targetIdentities, LocalIdentity: c.localIdentity, TargetName: serverAuthority, EnsureProcessSessionTickets: c.ensureProcessSessionTickets, } chs, err := handshaker.NewClientHandshaker(ctx, hsConn, rawConn, c.s2aAddr, opts) if err != nil { grpclog.Infof("Call to handshaker.NewClientHandshaker failed: %v", err) return nil, nil, err } defer func() { if err != nil { if closeErr := chs.Close(); closeErr != nil { grpclog.Infof("Close failed unexpectedly: %v", err) err = fmt.Errorf("%v: close unexpectedly failed: %v", err, closeErr) } } }() secConn, authInfo, err := chs.ClientHandshake(context.Background()) if err != nil { grpclog.Infof("Handshake failed: %v", err) return nil, nil, err } return secConn, authInfo, nil } // ServerHandshake initiates a server-side TLS handshake using the S2A. func (c *s2aTransportCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { if c.isClient { return nil, nil, errors.New("server handshake called using client transport credentials") } ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) defer cancel() // Connect to the S2A. hsConn, err := service.Dial(ctx, c.s2aAddr, nil) if err != nil { grpclog.Infof("Failed to connect to S2A: %v", err) return nil, nil, err } opts := &handshaker.ServerHandshakerOptions{ MinTLSVersion: c.minTLSVersion, MaxTLSVersion: c.maxTLSVersion, TLSCiphersuites: c.tlsCiphersuites, LocalIdentities: c.localIdentities, } shs, err := handshaker.NewServerHandshaker(ctx, hsConn, rawConn, c.s2aAddr, opts) if err != nil { grpclog.Infof("Call to handshaker.NewServerHandshaker failed: %v", err) return nil, nil, err } defer func() { if err != nil { if closeErr := shs.Close(); closeErr != nil { grpclog.Infof("Close failed unexpectedly: %v", err) err = fmt.Errorf("%v: close unexpectedly failed: %v", err, closeErr) } } }() secConn, authInfo, err := shs.ServerHandshake(context.Background()) if err != nil { grpclog.Infof("Handshake failed: %v", err) return nil, nil, err } return secConn, authInfo, nil } func (c *s2aTransportCreds) Info() credentials.ProtocolInfo { return *c.info } func (c *s2aTransportCreds) Clone() credentials.TransportCredentials { info := *c.info var localIdentity *commonpbv1.Identity if c.localIdentity != nil { localIdentity = proto.Clone(c.localIdentity).(*commonpbv1.Identity) } var localIdentities []*commonpbv1.Identity if c.localIdentities != nil { localIdentities = make([]*commonpbv1.Identity, len(c.localIdentities)) for i, localIdentity := range c.localIdentities { localIdentities[i] = proto.Clone(localIdentity).(*commonpbv1.Identity) } } var targetIdentities []*commonpbv1.Identity if c.targetIdentities != nil { targetIdentities = make([]*commonpbv1.Identity, len(c.targetIdentities)) for i, targetIdentity := range c.targetIdentities { targetIdentities[i] = proto.Clone(targetIdentity).(*commonpbv1.Identity) } } return &s2aTransportCreds{ info: &info, minTLSVersion: c.minTLSVersion, maxTLSVersion: c.maxTLSVersion, tlsCiphersuites: c.tlsCiphersuites, localIdentity: localIdentity, localIdentities: localIdentities, targetIdentities: targetIdentities, isClient: c.isClient, s2aAddr: c.s2aAddr, } } func (c *s2aTransportCreds) OverrideServerName(serverNameOverride string) error { c.info.ServerName = serverNameOverride return nil } // TLSClientConfigOptions specifies parameters for creating client TLS config. type TLSClientConfigOptions struct { // ServerName is required by s2a as the expected name when verifying the hostname found in server's certificate. // tlsConfig, _ := factory.Build(ctx, &s2a.TLSClientConfigOptions{ // ServerName: "example.com", // }) ServerName string } // TLSClientConfigFactory defines the interface for a client TLS config factory. type TLSClientConfigFactory interface { Build(ctx context.Context, opts *TLSClientConfigOptions) (*tls.Config, error) } // NewTLSClientConfigFactory returns an instance of s2aTLSClientConfigFactory. func NewTLSClientConfigFactory(opts *ClientOptions) (TLSClientConfigFactory, error) { if opts == nil { return nil, fmt.Errorf("opts must be non-nil") } if opts.EnableLegacyMode { return nil, fmt.Errorf("NewTLSClientConfigFactory only supports S2Av2") } tokenManager, err := tokenmanager.NewSingleTokenAccessTokenManager() if err != nil { // The only possible error is: access token not set in the environment, // which is okay in environments other than serverless. grpclog.Infof("Access token manager not initialized: %v", err) return &s2aTLSClientConfigFactory{ s2av2Address: opts.S2AAddress, transportCreds: opts.TransportCreds, tokenManager: nil, verificationMode: getVerificationMode(opts.VerificationMode), serverAuthorizationPolicy: opts.serverAuthorizationPolicy, }, nil } return &s2aTLSClientConfigFactory{ s2av2Address: opts.S2AAddress, transportCreds: opts.TransportCreds, tokenManager: tokenManager, verificationMode: getVerificationMode(opts.VerificationMode), serverAuthorizationPolicy: opts.serverAuthorizationPolicy, }, nil } type s2aTLSClientConfigFactory struct { s2av2Address string transportCreds credentials.TransportCredentials tokenManager tokenmanager.AccessTokenManager verificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode serverAuthorizationPolicy []byte } func (f *s2aTLSClientConfigFactory) Build( ctx context.Context, opts *TLSClientConfigOptions) (*tls.Config, error) { serverName := "" if opts != nil && opts.ServerName != "" { serverName = opts.ServerName } return v2.NewClientTLSConfig(ctx, f.s2av2Address, f.transportCreds, f.tokenManager, f.verificationMode, serverName, f.serverAuthorizationPolicy) } func getVerificationMode(verificationMode VerificationModeType) s2av2pb.ValidatePeerCertificateChainReq_VerificationMode { switch verificationMode { case ConnectToGoogle: return s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE case Spiffe: return s2av2pb.ValidatePeerCertificateChainReq_SPIFFE case ReservedCustomVerificationMode3: return s2av2pb.ValidatePeerCertificateChainReq_RESERVED_CUSTOM_VERIFICATION_MODE_3 case ReservedCustomVerificationMode4: return s2av2pb.ValidatePeerCertificateChainReq_RESERVED_CUSTOM_VERIFICATION_MODE_4 case ReservedCustomVerificationMode5: return s2av2pb.ValidatePeerCertificateChainReq_RESERVED_CUSTOM_VERIFICATION_MODE_5 default: return s2av2pb.ValidatePeerCertificateChainReq_UNSPECIFIED } } // NewS2ADialTLSContextFunc returns a dialer which establishes an MTLS connection using S2A. // Example use with http.RoundTripper: // // dialTLSContext := s2a.NewS2aDialTLSContextFunc(&s2a.ClientOptions{ // S2AAddress: s2aAddress, // required // }) // transport := http.DefaultTransport // transport.DialTLSContext = dialTLSContext func NewS2ADialTLSContextFunc(opts *ClientOptions) func(ctx context.Context, network, addr string) (net.Conn, error) { return func(ctx context.Context, network, addr string) (net.Conn, error) { fallback := func(err error) (net.Conn, error) { if opts.FallbackOpts != nil && opts.FallbackOpts.FallbackDialer != nil && opts.FallbackOpts.FallbackDialer.Dialer != nil && opts.FallbackOpts.FallbackDialer.ServerAddr != "" { fbDialer := opts.FallbackOpts.FallbackDialer grpclog.Infof("fall back to dial: %s", fbDialer.ServerAddr) fbConn, fbErr := fbDialer.Dialer.DialContext(ctx, network, fbDialer.ServerAddr) if fbErr != nil { return nil, fmt.Errorf("error fallback to %s: %v; S2A error: %w", fbDialer.ServerAddr, fbErr, err) } return fbConn, nil } return nil, err } factory, err := NewTLSClientConfigFactory(opts) if err != nil { grpclog.Infof("error creating S2A client config factory: %v", err) return fallback(err) } serverName, _, err := net.SplitHostPort(addr) if err != nil { serverName = addr } timeoutCtx, cancel := context.WithTimeout(ctx, v2.GetS2ATimeout()) defer cancel() var s2aTLSConfig *tls.Config var c net.Conn retry.Run(timeoutCtx, func() error { s2aTLSConfig, err = factory.Build(timeoutCtx, &TLSClientConfigOptions{ ServerName: serverName, }) if err != nil { grpclog.Infof("error building S2A TLS config: %v", err) return err } s2aDialer := &tls.Dialer{ Config: s2aTLSConfig, } c, err = s2aDialer.DialContext(timeoutCtx, network, addr) return err }) if err != nil { grpclog.Infof("error dialing with S2A to %s: %v", addr, err) return fallback(err) } grpclog.Infof("success dialing MTLS to %s with S2A", addr) return c, nil } } s2a-go-0.1.8/s2a_e2e_test.go000066400000000000000000001017471464711036600154400ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a import ( "bytes" "context" "crypto/tls" "crypto/x509" "fmt" "io" "io/ioutil" "net" "net/http" "os" "path/filepath" "testing" "time" _ "embed" "github.com/google/s2a-go/fallback" "github.com/google/s2a-go/internal/fakehandshaker/service" "github.com/google/s2a-go/internal/v2/fakes2av2" "github.com/google/s2a-go/retry" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/peer" grpc "google.golang.org/grpc" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" helloworldpb "github.com/google/s2a-go/internal/proto/examples/helloworld_go_proto" s2apb "github.com/google/s2a-go/internal/proto/s2a_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) const ( accessTokenEnvVariable = "S2A_ACCESS_TOKEN" testAccessToken = "test_access_token" testV2AccessToken = "valid_token" applicationProtocol = "grpc" authType = "s2a" clientHostname = "test_client_hostname" serverSpiffeID = "test_server_spiffe_id" clientMessage = "echo" defaultE2ETestTimeout = time.Second * 5 ) var ( //go:embed testdata/client_cert.pem clientCertpem []byte //go:embed testdata/client_key.pem clientKeypem []byte //go:embed testdata/server_cert.pem serverCertpem []byte //go:embed testdata/server_key.pem serverKeypem []byte //go:embed testdata/mds_root_cert.pem mdsRootCertPem []byte //go:embed testdata/mds_server_cert.pem mdsServerCertPem []byte //go:embed testdata/mds_server_key.pem mdsServerKeyPem []byte //go:embed testdata/mds_client_cert.pem mdsClientCertPem []byte //go:embed testdata/mds_client_key.pem mdsClientKeyPem []byte //go:embed testdata/self_signed_cert.pem selfSignedCertPem []byte //go:embed testdata/self_signed_key.pem selfSignedKeyPem []byte ) // server is used to implement helloworld.GreeterServer. type server struct { helloworldpb.UnimplementedGreeterServer } // SayHello implements helloworld.GreeterServer. func (s *server) SayHello(_ context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { return &helloworldpb.HelloReply{Message: "Hello " + in.GetName()}, nil } // startFakeS2A starts up a fake S2A and returns the address that it is // listening on. func startFakeS2A(t *testing.T, enableLegacyMode bool, expToken string, serverTransportCreds credentials.TransportCredentials) string { lis, err := net.Listen("tcp", ":") if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } var s *grpc.Server if serverTransportCreds != nil { s = grpc.NewServer(grpc.Creds(serverTransportCreds)) } else { s = grpc.NewServer() } if enableLegacyMode { s2apb.RegisterS2AServiceServer(s, &service.FakeHandshakerService{}) } else { s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ExpectedToken: expToken}) } go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return lis.Addr().String() } // startFakeS2AOnUDS starts up a fake S2A on UDS and returns the address that // it is listening on. func startFakeS2AOnUDS(t *testing.T, enableLegacyMode bool, expToken string) string { dir, err := ioutil.TempDir("/tmp", "socket_dir") if err != nil { t.Errorf("Unable to create temporary directory: %v", err) } udsAddress := filepath.Join(dir, "socket") lis, err := net.Listen("unix", filepath.Join(dir, "socket")) if err != nil { t.Errorf("net.Listen(unix, %s) failed: %v", udsAddress, err) } s := grpc.NewServer() if enableLegacyMode { s2apb.RegisterS2AServiceServer(s, &service.FakeHandshakerService{}) } else { s2av2pb.RegisterS2AServiceServer(s, &fakes2av2.Server{ExpectedToken: expToken}) } go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return fmt.Sprintf("unix://%s", lis.Addr().String()) } // startServer starts up a server and returns the address that it is listening // on. func startServer(t *testing.T, s2aAddress string, transportCreds credentials.TransportCredentials, enableLegacyMode bool) string { serverOpts := &ServerOptions{ LocalIdentities: []Identity{NewSpiffeID(serverSpiffeID)}, S2AAddress: s2aAddress, TransportCreds: transportCreds, EnableLegacyMode: enableLegacyMode, } creds, err := NewServerCreds(serverOpts) if err != nil { t.Errorf("NewServerCreds(%v) failed: %v", serverOpts, err) } lis, err := net.Listen("tcp", ":0") if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } s := grpc.NewServer(grpc.Creds(creds)) helloworldpb.RegisterGreeterServer(s, &server{}) go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return lis.Addr().String() } // runClient starts up a client and calls the server. func runClient(ctx context.Context, t *testing.T, clientS2AAddress string, transportCreds credentials.TransportCredentials, serverAddr string, enableLegacyMode bool, fallbackHandshake fallback.ClientHandshake) { clientOpts := &ClientOptions{ TargetIdentities: []Identity{NewSpiffeID(serverSpiffeID)}, LocalIdentity: NewHostname(clientHostname), S2AAddress: clientS2AAddress, TransportCreds: transportCreds, EnableLegacyMode: enableLegacyMode, FallbackOpts: &FallbackOptions{ FallbackClientHandshakeFunc: fallbackHandshake, }, } creds, err := NewClientCreds(clientOpts) if err != nil { t.Errorf("NewClientCreds(%v) failed: %v", clientOpts, err) } dialOptions := []grpc.DialOption{ grpc.WithTransportCredentials(creds), grpc.WithBlock(), } grpclog.Info("Client dialing server at address: %v", serverAddr) // Establish a connection to the server. conn, err := grpc.Dial(serverAddr, dialOptions...) if err != nil { t.Errorf("grpc.Dial(%v, %v) failed: %v", serverAddr, dialOptions, err) } defer conn.Close() // Contact the server. peer := new(peer.Peer) c := helloworldpb.NewGreeterClient(conn) req := &helloworldpb.HelloRequest{Name: clientMessage} grpclog.Infof("Client calling SayHello with request: %v", req) resp, err := c.SayHello(ctx, req, grpc.Peer(peer), grpc.WaitForReady(true)) if err != nil { t.Errorf("c.SayHello(%v, %v) failed: %v", ctx, req, err) } if got, want := resp.GetMessage(), "Hello "+clientMessage; got != want { t.Errorf("r.GetMessage() = %v, want %v", got, want) } grpclog.Infof("Client received message from server: %s", resp.GetMessage()) if enableLegacyMode { // Check the auth info. authInfo, err := AuthInfoFromPeer(peer) if err != nil { t.Errorf("AuthInfoFromContext(peer) failed: %v", err) } s2aAuthInfo, ok := authInfo.(AuthInfo) if !ok { t.Errorf("authInfo is not an s2a.AuthInfo") } if got, want := s2aAuthInfo.AuthType(), authType; got != want { t.Errorf("s2aAuthInfo.AuthType() = %v, want %v", got, want) } if got, want := s2aAuthInfo.ApplicationProtocol(), applicationProtocol; got != want { t.Errorf("s2aAuthInfo.ApplicationProtocol() = %v, want %v", got, want) } if got, want := s2aAuthInfo.TLSVersion(), commonpb.TLSVersion_TLS1_3; got != want { t.Errorf("s2aAuthInfo.TLSVersion() = %v, want %v", got, want) } if got, want := s2aAuthInfo.IsHandshakeResumed(), false; got != want { t.Errorf("s2aAuthInfo.IsHandshakeResumed() = %v, want %v", got, want) } if got, want := s2aAuthInfo.SecurityLevel(), credentials.PrivacyAndIntegrity; got != want { t.Errorf("s2aAuthInfo.SecurityLevel() = %v, want %v", got, want) } } } func TestV1EndToEndUsingFakeS2AOverTCP(t *testing.T) { os.Setenv(accessTokenEnvVariable, "") // Start the fake S2As for the client and server. serverHandshakerAddr := startFakeS2A(t, true, "", nil) grpclog.Infof("Fake handshaker for server running at address: %v", serverHandshakerAddr) clientHandshakerAddr := startFakeS2A(t, true, "", nil) grpclog.Infof("Fake handshaker for client running at address: %v", clientHandshakerAddr) // Start the server. serverAddr := startServer(t, serverHandshakerAddr, nil, true) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientHandshakerAddr, nil, serverAddr, true, nil) } func TestV2EndToEndUsingFakeS2AOverTCP(t *testing.T) { os.Setenv(accessTokenEnvVariable, testV2AccessToken) oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2As for the client and server. serverHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake handshaker for server running at address: %v", serverHandshakerAddr) clientHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake handshaker for client running at address: %v", clientHandshakerAddr) // Start the server. serverAddr := startServer(t, serverHandshakerAddr, nil, false) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientHandshakerAddr, nil, serverAddr, false, nil) if got, want := testRetryer.Attempts(), 0; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestV2EndToEndUsingFakeMTLSS2AOverTCP(t *testing.T) { os.Setenv(accessTokenEnvVariable, "") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } serverTransportCreds := loadServerTransportCreds(t, mdsServerCertPem, mdsServerKeyPem) // Start the fake S2As for the client and server. serverHandshakerAddr := startFakeS2A(t, false, "", serverTransportCreds) grpclog.Infof("Fake handshaker for server running at address: %v", serverHandshakerAddr) clientHandshakerAddr := startFakeS2A(t, false, "", serverTransportCreds) grpclog.Infof("Fake handshaker for client running at address: %v", clientHandshakerAddr) clientTransportCreds := loadClientTransportCreds(t, mdsClientCertPem, mdsClientKeyPem) // Start the server. serverAddr := startServer(t, serverHandshakerAddr, clientTransportCreds, false) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientHandshakerAddr, clientTransportCreds, serverAddr, false, nil) if got, want := testRetryer.Attempts(), 0; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestV2EndToEndUsingFakeMTLSS2AOverTCP_SelfSignedClientTransportCreds(t *testing.T) { os.Setenv(accessTokenEnvVariable, "") fallback.FallbackTLSConfigGRPC.InsecureSkipVerify = true oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } serverTransportCreds := loadServerTransportCreds(t, mdsServerCertPem, mdsServerKeyPem) // Start the fake S2As for the client and server. serverHandshakerAddr := startFakeS2A(t, false, "", serverTransportCreds) grpclog.Infof("Fake handshaker for server running at address: %v", serverHandshakerAddr) clientHandshakerAddr := startFakeS2A(t, false, "", serverTransportCreds) grpclog.Infof("Fake handshaker for client running at address: %v", clientHandshakerAddr) clientTransportCreds := loadClientTransportCreds(t, mdsClientCertPem, mdsClientKeyPem) // Load self-signed client credentials. selfSignedClientTransportCreds := loadClientTransportCreds(t, selfSignedCertPem, selfSignedKeyPem) // Start the server. serverAddr := startServer(t, serverHandshakerAddr, clientTransportCreds, false) fallbackServerAddr := startFallbackServer(t) t.Logf("server running at address: %v", serverAddr) t.Logf("fallback server running at address: %v", fallbackServerAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() fallbackHandshake, err := fallback.DefaultFallbackClientHandshakeFunc(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback handshake function: %v", err) } fallbackCalled := false fallbackHandshakeWrapper := func(ctx context.Context, targetServer string, conn net.Conn, err error) (net.Conn, credentials.AuthInfo, error) { fallbackCalled = true return fallbackHandshake(ctx, targetServer, conn, err) } // Use self-signed cert to trigger handshake failure when connecting to MTLS-S2A gRPC server. // This should cause retries and eventually fallback. runClient(ctx, t, clientHandshakerAddr, selfSignedClientTransportCreds, serverAddr, false, fallbackHandshakeWrapper) if !fallbackCalled { t.Errorf("fallbackHandshake is not called") } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func loadServerTransportCreds(t *testing.T, cert, key []byte) credentials.TransportCredentials { certificate, err := tls.X509KeyPair(cert, key) if err != nil { t.Errorf("failed to load S2A server cert/key: %v", err) } caPool := x509.NewCertPool() if !caPool.AppendCertsFromPEM(mdsRootCertPem) { t.Errorf("failed to add ca cert") } tlsConfig := &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, Certificates: []tls.Certificate{certificate}, ClientCAs: caPool, } return credentials.NewTLS(tlsConfig) } func loadClientTransportCreds(t *testing.T, cert, key []byte) credentials.TransportCredentials { certificate, err := tls.X509KeyPair(cert, key) if err != nil { t.Errorf("failed to load S2A client cert/key: %v", err) } caPool := x509.NewCertPool() if !caPool.AppendCertsFromPEM(mdsRootCertPem) { t.Errorf("failed to add ca cert") } tlsConfig := &tls.Config{ Certificates: []tls.Certificate{certificate}, RootCAs: caPool, } return credentials.NewTLS(tlsConfig) } // startFallbackServer runs a GRPC echo testing server and returns the address. // It's used to test the default fallback logic upon S2A failure. func startFallbackServer(t *testing.T) string { lis, err := net.Listen("tcp", ":0") if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } cert, err := tls.X509KeyPair(serverCertpem, serverKeypem) if err != nil { t.Errorf("failure initializing tls.certificate: %v", err) } // Client certs are not required for the fallback server. creds := credentials.NewTLS(&tls.Config{ MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, Certificates: []tls.Certificate{cert}, }) s := grpc.NewServer(grpc.Creds(creds)) helloworldpb.RegisterGreeterServer(s, &server{}) go func() { if err := s.Serve(lis); err != nil { t.Errorf("s.Serve(%v) failed: %v", lis, err) } }() return lis.Addr().String() } func TestV2GRPCFallbackEndToEndUsingFakeS2AOverTCP(t *testing.T) { // Set for testing only. fallback.FallbackTLSConfigGRPC.InsecureSkipVerify = true os.Setenv(accessTokenEnvVariable, testV2AccessToken) oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2A for the server. serverHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("fake handshaker for server running at address: %v", serverHandshakerAddr) // Start the server. serverAddr := startServer(t, serverHandshakerAddr, nil, false) fallbackServerAddr := startFallbackServer(t) t.Logf("server running at address: %v", serverAddr) t.Logf("fallback server running at address: %v", fallbackServerAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() fallbackHandshake, err := fallback.DefaultFallbackClientHandshakeFunc(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback handshake function: %v", err) } fallbackCalled := false fallbackHandshakeWrapper := func(ctx context.Context, targetServer string, conn net.Conn, err error) (net.Conn, credentials.AuthInfo, error) { fallbackCalled = true return fallbackHandshake(ctx, targetServer, conn, err) } runClient(ctx, t, "not_exist", nil, serverAddr, false, fallbackHandshakeWrapper) if !fallbackCalled { t.Errorf("fallbackHandshake is not called") } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestV2GRPCRetryAndFallbackEndToEndUsingFakeS2AOverTCP(t *testing.T) { // Set for testing only. fallback.FallbackTLSConfigGRPC.InsecureSkipVerify = true // Set an invalid token to trigger failures and retries when talking to S2A. os.Setenv(accessTokenEnvVariable, "invalid_token") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2A for the server and client. serverHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("fake handshaker for server running at address: %v", serverHandshakerAddr) clientHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake handshaker for client running at address: %v", clientHandshakerAddr) // Start the server. serverAddr := startServer(t, serverHandshakerAddr, nil, false) fallbackServerAddr := startFallbackServer(t) t.Logf("server running at address: %v", serverAddr) t.Logf("fallback server running at address: %v", fallbackServerAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() fallbackHandshake, err := fallback.DefaultFallbackClientHandshakeFunc(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback handshake function: %v", err) } fallbackCalled := false fallbackHandshakeWrapper := func(ctx context.Context, targetServer string, conn net.Conn, err error) (net.Conn, credentials.AuthInfo, error) { fallbackCalled = true return fallbackHandshake(ctx, targetServer, conn, err) } runClient(ctx, t, clientHandshakerAddr, nil, serverAddr, false, fallbackHandshakeWrapper) if !fallbackCalled { t.Errorf("fallbackHandshake is not called") } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestV1EndToEndUsingTokens(t *testing.T) { os.Setenv(accessTokenEnvVariable, testAccessToken) // Start the handshaker servers for the client and server. serverS2AAddress := startFakeS2A(t, true, "", nil) grpclog.Infof("Fake S2A for server running at address: %v", serverS2AAddress) clientS2AAddress := startFakeS2A(t, true, "", nil) grpclog.Infof("Fake S2A for client running at address: %v", clientS2AAddress) // Start the server. serverAddr := startServer(t, serverS2AAddress, nil, true) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientS2AAddress, nil, serverAddr, true, nil) } func TestV2EndToEndUsingTokens(t *testing.T) { os.Setenv(accessTokenEnvVariable, testV2AccessToken) // Start the handshaker servers for the client and server. serverS2AAddress := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake S2A for server running at address: %v", serverS2AAddress) clientS2AAddress := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake S2A for client running at address: %v", clientS2AAddress) // Start the server. serverAddr := startServer(t, serverS2AAddress, nil, false) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientS2AAddress, nil, serverAddr, false, nil) } func TestV2EndToEndEmptyToken(t *testing.T) { os.Unsetenv(accessTokenEnvVariable) // Start the handshaker servers for the client and server. serverS2AAddress := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake S2A for server running at address: %v", serverS2AAddress) clientS2AAddress := startFakeS2A(t, false, testV2AccessToken, nil) grpclog.Infof("Fake S2A for client running at address: %v", clientS2AAddress) // Start the server. serverAddr := startServer(t, serverS2AAddress, nil, false) grpclog.Infof("Server running at address: %v", serverAddr) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientS2AAddress, nil, serverAddr, false, nil) } func TestV1EndToEndUsingFakeS2AOnUDS(t *testing.T) { os.Setenv(accessTokenEnvVariable, "") // Start fake S2As for use by the client and server. serverS2AAddress := startFakeS2AOnUDS(t, true, "") grpclog.Infof("Fake S2A for server listening on UDS at address: %v", serverS2AAddress) clientS2AAddress := startFakeS2AOnUDS(t, true, "") grpclog.Infof("Fake S2A for client listening on UDS at address: %v", clientS2AAddress) // Start the server. serverAddress := startServer(t, serverS2AAddress, nil, true) grpclog.Infof("Server running at address: %v", serverS2AAddress) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientS2AAddress, nil, serverAddress, true, nil) } func TestV2EndToEndUsingFakeS2AOnUDS(t *testing.T) { os.Setenv(accessTokenEnvVariable, testV2AccessToken) // Start fake S2As for use by the client and server. serverS2AAddress := startFakeS2AOnUDS(t, false, testV2AccessToken) grpclog.Infof("Fake S2A for server listening on UDS at address: %v", serverS2AAddress) clientS2AAddress := startFakeS2AOnUDS(t, false, testV2AccessToken) grpclog.Infof("Fake S2A for client listening on UDS at address: %v", clientS2AAddress) // Start the server. serverAddress := startServer(t, serverS2AAddress, nil, false) grpclog.Infof("Server running at address: %v", serverS2AAddress) // Finally, start up the client. ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() runClient(ctx, t, clientS2AAddress, nil, serverAddress, false, nil) } func TestNewTLSClientConfigFactoryWithTokenManager(t *testing.T) { os.Setenv(accessTokenEnvVariable, "TestNewTLSClientConfigFactory_token") s2AAddr := startFakeS2A(t, false, "TestNewTLSClientConfigFactory_token", nil) ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() factory, err := NewTLSClientConfigFactory(&ClientOptions{ S2AAddress: s2AAddr, }) if err != nil { t.Errorf("NewTLSClientConfigFactory() failed: %v", err) } config, err := factory.Build(ctx, nil) if err != nil { t.Errorf("Build tls config failed: %v", err) } cert, err := tls.X509KeyPair(clientCertpem, clientKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], cert.Certificate[0]; !bytes.Equal(got, want) { t.Errorf("tls.Config has unexpected certificate: got: %v, want: %v", got, want) } } func TestNewTLSClientConfigFactoryWithoutTokenManager(t *testing.T) { os.Unsetenv(accessTokenEnvVariable) s2AAddr := startFakeS2A(t, false, "ignored-value", nil) ctx, cancel := context.WithTimeout(context.Background(), defaultE2ETestTimeout) defer cancel() factory, err := NewTLSClientConfigFactory(&ClientOptions{ S2AAddress: s2AAddr, }) if err != nil { t.Errorf("NewTLSClientConfigFactory() failed: %v", err) } config, err := factory.Build(ctx, nil) if err != nil { t.Errorf("Build tls config failed: %v", err) } cert, err := tls.X509KeyPair(clientCertpem, clientKeypem) if err != nil { t.Fatalf("tls.X509KeyPair failed: %v", err) } if got, want := config.Certificates[0].Certificate[0], cert.Certificate[0]; !bytes.Equal(got, want) { t.Errorf("tls.Config has unexpected certificate: got: %v, want: %v", got, want) } } // startHTTPServer runs an HTTP server on a random local port and serves a /hello endpoint. // The response of the /hello endpoint should be passed in via the `resp` parameter. // It returns the address of the server. func startHTTPServer(t *testing.T, resp string) string { cert, _ := tls.X509KeyPair(serverCertpem, serverKeypem) tlsConfig := tls.Config{ MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13, Certificates: []tls.Certificate{cert}, } s := http.NewServeMux() s.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, resp) }) lis, err := tls.Listen("tcp", ":0", &tlsConfig) if err != nil { t.Errorf("net.Listen(tcp, :0) failed: %v", err) } go func() { http.Serve(lis, s) }() return lis.Addr().String() } // runHTTPClient starts an HTTP client and talks to an HTTP server using S2A. // It returns the response from the /hello endpoint. func runHTTPClient(t *testing.T, clientS2AAddress string, transportCreds credentials.TransportCredentials, serverAddr string, fallbackOpts *FallbackOptions) string { dialTLSContext := NewS2ADialTLSContextFunc(&ClientOptions{ S2AAddress: clientS2AAddress, TransportCreds: transportCreds, FallbackOpts: fallbackOpts, }) tr := http.Transport{ DialTLSContext: dialTLSContext, } client := &http.Client{Transport: &tr} reqURL := fmt.Sprintf("https://%s/hello", serverAddr) t.Logf("reqURL is set to: %v", reqURL) req, err := http.NewRequest(http.MethodGet, reqURL, nil) if err != nil { t.Errorf("error creating new HTTP request: %v", err) } resp, err := client.Do(req) if err != nil { t.Errorf("error making client HTTP request: %v", err) } respBody, err := io.ReadAll(resp.Body) if err != nil { t.Errorf("error reading HTTP response: %v", err) } return string(respBody) } func TestHTTPEndToEndUsingFakeS2AOverTCP(t *testing.T) { os.Setenv(accessTokenEnvVariable, testV2AccessToken) oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2As for the client. clientHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) t.Logf("fake handshaker for client running at address: %v", clientHandshakerAddr) // Start the server. serverAddr := startHTTPServer(t, "hello") t.Logf("HTTP server running at address: %v", serverAddr) // Finally, start up the client. resp := runHTTPClient(t, clientHandshakerAddr, nil, serverAddr, nil) if got, want := resp, "hello"; got != want { t.Errorf("expecting HTTP response:[%s], got [%s]", want, got) } if got, want := testRetryer.Attempts(), 0; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestHTTPEndToEndSUsingFakeMTLSS2AOverTCP(t *testing.T) { os.Setenv(accessTokenEnvVariable, "") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2As for the client. serverTransportCreds := loadServerTransportCreds(t, mdsServerCertPem, mdsServerKeyPem) clientHandshakerAddr := startFakeS2A(t, false, "", serverTransportCreds) t.Logf("fake handshaker for client running at address: %v", clientHandshakerAddr) // Start the server. serverAddr := startHTTPServer(t, "hello") t.Logf("HTTP server running at address: %v", serverAddr) // Finally, start up the client. clientTransportCreds := loadClientTransportCreds(t, mdsClientCertPem, mdsClientKeyPem) resp := runHTTPClient(t, clientHandshakerAddr, clientTransportCreds, serverAddr, nil) if got, want := resp, "hello"; got != want { t.Errorf("expecting HTTP response:[%s], got [%s]", want, got) } if got, want := testRetryer.Attempts(), 0; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestHTTPEndToEndSUsingFakeMTLSS2AOverTCP_SelfSignedClientTransportCreds(t *testing.T) { fallback.FallbackTLSConfigHTTP.InsecureSkipVerify = true os.Setenv(accessTokenEnvVariable, "") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2As for the client. serverTransportCreds := loadServerTransportCreds(t, mdsServerCertPem, mdsServerKeyPem) clientHandshakerAddr := startFakeS2A(t, false, "", serverTransportCreds) t.Logf("fake handshaker for client running at address: %v", clientHandshakerAddr) serverAddr := startHTTPServer(t, "hello") t.Logf("HTTP server running at address: %v", serverAddr) fallbackServerAddr := startHTTPServer(t, "hello fallback") t.Logf("fallback HTTP server running at address: %v", fallbackServerAddr) // Configure fallback options. fbDialer, fbAddr, err := fallback.DefaultFallbackDialerAndAddress(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback dialer: %v", err) } fallbackOpts := &FallbackOptions{ FallbackDialer: &FallbackDialer{ Dialer: fbDialer, ServerAddr: fbAddr, }, } // Load self-signed client credentials. selfSignedClientTransportCreds := loadClientTransportCreds(t, selfSignedCertPem, selfSignedKeyPem) // Use self-signed cert to trigger handshake failure when connecting to MTLS-S2A gRPC server. // This should cause retries and eventually fallback. resp := runHTTPClient(t, clientHandshakerAddr, selfSignedClientTransportCreds, serverAddr, fallbackOpts) if got, want := resp, "hello fallback"; got != want { t.Errorf("expecting HTTP response:[%s], got [%s]", want, got) } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestHTTPFallbackEndToEndUsingFakeS2AOverTCP(t *testing.T) { fallback.FallbackTLSConfigHTTP.InsecureSkipVerify = true os.Setenv(accessTokenEnvVariable, testV2AccessToken) oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the server. serverAddr := startHTTPServer(t, "hello") t.Logf("HTTP server running at address: %v", serverAddr) fallbackServerAddr := startHTTPServer(t, "hello fallback") t.Logf("fallback HTTP server running at address: %v", fallbackServerAddr) // Configure fallback options. fbDialer, fbAddr, err := fallback.DefaultFallbackDialerAndAddress(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback dialer: %v", err) } fallbackOpts := &FallbackOptions{ FallbackDialer: &FallbackDialer{ Dialer: fbDialer, ServerAddr: fbAddr, }, } // Set wrong client S2A address to trigger S2A failure and fallback. resp := runHTTPClient(t, "not_exist", nil, serverAddr, fallbackOpts) if got, want := resp, "hello fallback"; got != want { t.Errorf("expecting HTTP response:[%s], got [%s]", want, got) } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } func TestHTTPRetryAndFallbackEndToEndUsingFakeS2AOverTCP(t *testing.T) { fallback.FallbackTLSConfigHTTP.InsecureSkipVerify = true // Set an invalid token to trigger failures and retries when talking to S2A. os.Setenv(accessTokenEnvVariable, "invalid_token") oldRetry := retry.NewRetryer defer func() { retry.NewRetryer = oldRetry }() testRetryer := retry.NewRetryer() retry.NewRetryer = func() *retry.S2ARetryer { return testRetryer } // Start the fake S2As for the client. clientHandshakerAddr := startFakeS2A(t, false, testV2AccessToken, nil) t.Logf("fake handshaker for client running at address: %v", clientHandshakerAddr) serverAddr := startHTTPServer(t, "hello") t.Logf("HTTP server running at address: %v", serverAddr) fallbackServerAddr := startHTTPServer(t, "hello fallback") t.Logf("fallback HTTP server running at address: %v", fallbackServerAddr) // Configure fallback options. fbDialer, fbAddr, err := fallback.DefaultFallbackDialerAndAddress(fallbackServerAddr) if err != nil { t.Errorf("error creating fallback dialer: %v", err) } fallbackOpts := &FallbackOptions{ FallbackDialer: &FallbackDialer{ Dialer: fbDialer, ServerAddr: fbAddr, }, } resp := runHTTPClient(t, clientHandshakerAddr, nil, serverAddr, fallbackOpts) if got, want := resp, "hello fallback"; got != want { t.Errorf("expecting HTTP response:[%s], got [%s]", want, got) } if got, want := testRetryer.Attempts(), 5; got != want { t.Errorf("expecting retryer attempts count:[%v], got [%v]", want, got) } } s2a-go-0.1.8/s2a_options.go000066400000000000000000000174031464711036600154140ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a import ( "context" "crypto/tls" "errors" "sync" "github.com/google/s2a-go/fallback" "github.com/google/s2a-go/stream" "google.golang.org/grpc/credentials" s2apbv1 "github.com/google/s2a-go/internal/proto/common_go_proto" s2apb "github.com/google/s2a-go/internal/proto/v2/common_go_proto" ) // Identity is the interface for S2A identities. type Identity interface { // Name returns the name of the identity. Name() string } type spiffeID struct { spiffeID string } func (s *spiffeID) Name() string { return s.spiffeID } // NewSpiffeID creates a SPIFFE ID from id. func NewSpiffeID(id string) Identity { return &spiffeID{spiffeID: id} } type hostname struct { hostname string } func (h *hostname) Name() string { return h.hostname } // NewHostname creates a hostname from name. func NewHostname(name string) Identity { return &hostname{hostname: name} } type uid struct { uid string } func (h *uid) Name() string { return h.uid } // NewUID creates a UID from name. func NewUID(name string) Identity { return &uid{uid: name} } // VerificationModeType specifies the mode that S2A must use to verify the peer // certificate chain. type VerificationModeType int // Three types of verification modes. const ( Unspecified VerificationModeType = iota Spiffe ConnectToGoogle ReservedCustomVerificationMode3 ReservedCustomVerificationMode4 ReservedCustomVerificationMode5 ) // ClientOptions contains the client-side options used to establish a secure // channel using the S2A handshaker service. type ClientOptions struct { // TargetIdentities contains a list of allowed server identities. One of the // target identities should match the peer identity in the handshake // result; otherwise, the handshake fails. TargetIdentities []Identity // LocalIdentity is the local identity of the client application. If none is // provided, then the S2A will choose the default identity, if one exists. LocalIdentity Identity // S2AAddress is the address of the S2A. S2AAddress string // Optional transport credentials. // If set, this will be used for the gRPC connection to the S2A server. TransportCreds credentials.TransportCredentials // EnsureProcessSessionTickets waits for all session tickets to be sent to // S2A before a process completes. // // This functionality is crucial for processes that complete very soon after // using S2A to establish a TLS connection, but it can be ignored for longer // lived processes. // // Usage example: // func main() { // var ensureProcessSessionTickets sync.WaitGroup // clientOpts := &s2a.ClientOptions{ // EnsureProcessSessionTickets: &ensureProcessSessionTickets, // // Set other members. // } // creds, _ := s2a.NewClientCreds(clientOpts) // conn, _ := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds)) // defer conn.Close() // // // Make RPC call. // // // The process terminates right after the RPC call ends. // // ensureProcessSessionTickets can be used to ensure resumption // // tickets are fully processed. If the process is long-lived, using // // ensureProcessSessionTickets is not necessary. // ensureProcessSessionTickets.Wait() // } EnsureProcessSessionTickets *sync.WaitGroup // If true, enables the use of legacy S2Av1. EnableLegacyMode bool // VerificationMode specifies the mode that S2A must use to verify the // peer certificate chain. VerificationMode VerificationModeType // Optional fallback after dialing with S2A fails. FallbackOpts *FallbackOptions // Generates an S2AStream interface for talking to the S2A server. getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error) // Serialized user specified policy for server authorization. serverAuthorizationPolicy []byte } // FallbackOptions prescribes the fallback logic that should be taken if the application fails to connect with S2A. type FallbackOptions struct { // FallbackClientHandshakeFunc is used to specify fallback behavior when calling s2a.NewClientCreds(). // It will be called by ClientHandshake function, after handshake with S2A fails. // s2a.NewClientCreds() ignores the other FallbackDialer field. FallbackClientHandshakeFunc fallback.ClientHandshake // FallbackDialer is used to specify fallback behavior when calling s2a.NewS2aDialTLSContextFunc(). // It passes in a custom fallback dialer and server address to use after dialing with S2A fails. // s2a.NewS2aDialTLSContextFunc() ignores the other FallbackClientHandshakeFunc field. FallbackDialer *FallbackDialer } // FallbackDialer contains a fallback tls.Dialer and a server address to connect to. type FallbackDialer struct { // Dialer specifies a fallback tls.Dialer. Dialer *tls.Dialer // ServerAddr is used by Dialer to establish fallback connection. ServerAddr string } // DefaultClientOptions returns the default client options. func DefaultClientOptions(s2aAddress string) *ClientOptions { return &ClientOptions{ S2AAddress: s2aAddress, VerificationMode: ConnectToGoogle, } } // ServerOptions contains the server-side options used to establish a secure // channel using the S2A handshaker service. type ServerOptions struct { // LocalIdentities is the list of local identities that may be assumed by // the server. If no local identity is specified, then the S2A chooses a // default local identity, if one exists. LocalIdentities []Identity // S2AAddress is the address of the S2A. S2AAddress string // Optional transport credentials. // If set, this will be used for the gRPC connection to the S2A server. TransportCreds credentials.TransportCredentials // If true, enables the use of legacy S2Av1. EnableLegacyMode bool // VerificationMode specifies the mode that S2A must use to verify the // peer certificate chain. VerificationMode VerificationModeType // Generates an S2AStream interface for talking to the S2A server. getS2AStream func(ctx context.Context, s2av2Address string) (stream.S2AStream, error) } // DefaultServerOptions returns the default server options. func DefaultServerOptions(s2aAddress string) *ServerOptions { return &ServerOptions{ S2AAddress: s2aAddress, VerificationMode: ConnectToGoogle, } } func toProtoIdentity(identity Identity) (*s2apbv1.Identity, error) { if identity == nil { return nil, nil } switch id := identity.(type) { case *spiffeID: return &s2apbv1.Identity{IdentityOneof: &s2apbv1.Identity_SpiffeId{SpiffeId: id.Name()}}, nil case *hostname: return &s2apbv1.Identity{IdentityOneof: &s2apbv1.Identity_Hostname{Hostname: id.Name()}}, nil case *uid: return &s2apbv1.Identity{IdentityOneof: &s2apbv1.Identity_Uid{Uid: id.Name()}}, nil default: return nil, errors.New("unrecognized identity type") } } func toV2ProtoIdentity(identity Identity) (*s2apb.Identity, error) { if identity == nil { return nil, nil } switch id := identity.(type) { case *spiffeID: return &s2apb.Identity{IdentityOneof: &s2apb.Identity_SpiffeId{SpiffeId: id.Name()}}, nil case *hostname: return &s2apb.Identity{IdentityOneof: &s2apb.Identity_Hostname{Hostname: id.Name()}}, nil case *uid: return &s2apb.Identity{IdentityOneof: &s2apb.Identity_Uid{Uid: id.Name()}}, nil default: return nil, errors.New("unrecognized identity type") } } s2a-go-0.1.8/s2a_options_test.go000066400000000000000000000034331464711036600164510ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a import ( "testing" "github.com/google/go-cmp/cmp" s2apb "github.com/google/s2a-go/internal/proto/common_go_proto" "google.golang.org/protobuf/testing/protocmp" ) func TestToProtoIdentity(t *testing.T) { for _, tc := range []struct { identity Identity outIdentity *s2apb.Identity }{ { identity: NewSpiffeID("test_spiffe_id"), outIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_SpiffeId{SpiffeId: "test_spiffe_id"}, }, }, { identity: NewHostname("test_hostname"), outIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_Hostname{Hostname: "test_hostname"}, }, }, { identity: NewUID("test_uid"), outIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_Uid{Uid: "test_uid"}, }, }, { identity: nil, outIdentity: nil, }, } { t.Run(tc.outIdentity.String(), func(t *testing.T) { protoSpiffeID, err := toProtoIdentity(tc.identity) if err != nil { t.Errorf("toProtoIdentity(%v) failed: %v", tc.identity, err) } if got, want := protoSpiffeID, tc.outIdentity; !cmp.Equal(got, want, protocmp.Transform()) { t.Errorf("toProtoIdentity(%v) = %v, want %v", tc.outIdentity, got, want) } }) } } s2a-go-0.1.8/s2a_test.go000066400000000000000000000374451464711036600147100ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a import ( "context" "testing" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/testing/protocmp" s2apb "github.com/google/s2a-go/internal/proto/common_go_proto" s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) func TestNewClientCreds(t *testing.T) { for _, tc := range []struct { desc string opts *ClientOptions outMinTLSVersion s2apb.TLSVersion outMaxTLSVersion s2apb.TLSVersion outTLSCiphersuites []s2apb.Ciphersuite outLocalIdentity *s2apb.Identity outTargetIdentities []*s2apb.Identity outS2AAddress string }{ { desc: "only hostnames", opts: &ClientOptions{ TargetIdentities: []Identity{ &hostname{"test_server_hostname"}, }, LocalIdentity: &hostname{"test_client_hostname"}, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outTargetIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_Hostname{ Hostname: "test_server_hostname", }, }, }, outLocalIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_Hostname{ Hostname: "test_client_hostname", }, }, outS2AAddress: "test_s2a_address", }, { desc: "only spiffe IDs", opts: &ClientOptions{ TargetIdentities: []Identity{ &spiffeID{"test_server_spiffe_id"}, }, LocalIdentity: &spiffeID{"test_client_spiffe_id"}, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outTargetIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "test_server_spiffe_id", }, }, }, outLocalIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "test_client_spiffe_id", }, }, outS2AAddress: "test_s2a_address", }, { desc: "only UIDs", opts: &ClientOptions{ TargetIdentities: []Identity{ &uid{"test_server_uid"}, }, LocalIdentity: &uid{"test_client_uid"}, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outTargetIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_Uid{ Uid: "test_server_uid", }, }, }, outLocalIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_Uid{ Uid: "test_client_uid", }, }, outS2AAddress: "test_s2a_address", }, { desc: "mixed identities", opts: &ClientOptions{ TargetIdentities: []Identity{ &spiffeID{"test_server_spiffe_id"}, &hostname{"test_server_hostname"}, &uid{"test_server_uid"}, }, LocalIdentity: &spiffeID{"test_client_spiffe_id"}, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outTargetIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "test_server_spiffe_id", }, }, { IdentityOneof: &s2apb.Identity_Hostname{ Hostname: "test_server_hostname", }, }, { IdentityOneof: &s2apb.Identity_Uid{ Uid: "test_server_uid", }, }, }, outLocalIdentity: &s2apb.Identity{ IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "test_client_spiffe_id", }, }, outS2AAddress: "test_s2a_address", }, } { t.Run(tc.desc, func(t *testing.T) { c, err := NewClientCreds(tc.opts) if err != nil { t.Fatalf("NewClientCreds(_) failed: %v", err) } if got, want := c.Info().SecurityProtocol, s2aSecurityProtocol; got != want { t.Errorf("c.Info().SecurityProtocol = %v, want %v", got, want) } s2aCreds, ok := c.(*s2aTransportCreds) if !ok { t.Fatal("The created creds is not of type s2aTransportCreds") } if got, want := s2aCreds.minTLSVersion, tc.outMinTLSVersion; got != want { t.Errorf("s2aCreds.minTLSVersion = %v, want %v", got, want) } if got, want := s2aCreds.maxTLSVersion, tc.outMaxTLSVersion; got != want { t.Errorf("s2aCreds.maxTLSVersion = %v, want %v", got, want) } if got, want := s2aCreds.tlsCiphersuites, tc.outTLSCiphersuites; !cmp.Equal(got, want) { t.Errorf("s2aCreds.tlsCiphersuites = %v, want %v", got, want) } if got, want := s2aCreds.targetIdentities, tc.outTargetIdentities; !cmp.Equal(got, want, protocmp.Transform()) { t.Errorf("s2aCreds.targetIdentities = %v, want %v", got, want) } if got, want := s2aCreds.localIdentity, tc.outLocalIdentity; !cmp.Equal(got, want, protocmp.Transform()) { t.Errorf("s2aCreds.localIdentity = %v, want %v", got, want) } if got, want := s2aCreds.s2aAddr, tc.outS2AAddress; got != want { t.Errorf("s2aCreds.s2aAddr = %v, want %v", got, want) } }) } } func TestNewServerCreds(t *testing.T) { for _, tc := range []struct { desc string opts *ServerOptions outMinTLSVersion s2apb.TLSVersion outMaxTLSVersion s2apb.TLSVersion outTLSCiphersuites []s2apb.Ciphersuite outLocalIdentities []*s2apb.Identity outS2AAddress string }{ { desc: "only hostnames", opts: &ServerOptions{ LocalIdentities: []Identity{ &hostname{"test_server_hostname"}, }, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outLocalIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_Hostname{ Hostname: "test_server_hostname", }, }, }, outS2AAddress: "test_s2a_address", }, { desc: "only spiffe IDs", opts: &ServerOptions{ LocalIdentities: []Identity{ &spiffeID{"test_server_spiffe_id"}, }, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outLocalIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "test_server_spiffe_id", }, }, }, outS2AAddress: "test_s2a_address", }, { desc: "only UIDs", opts: &ServerOptions{ LocalIdentities: []Identity{ &uid{"test_server_uid"}, }, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outLocalIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_Uid{ Uid: "test_server_uid", }, }, }, outS2AAddress: "test_s2a_address", }, { desc: "mixed identities", opts: &ServerOptions{ LocalIdentities: []Identity{ &spiffeID{"test_server_spiffe_id"}, &hostname{"test_server_hostname"}, &uid{"test_server_uid"}, }, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }, outMinTLSVersion: s2apb.TLSVersion_TLS1_3, outMaxTLSVersion: s2apb.TLSVersion_TLS1_3, outTLSCiphersuites: []s2apb.Ciphersuite{ s2apb.Ciphersuite_AES_128_GCM_SHA256, s2apb.Ciphersuite_AES_256_GCM_SHA384, s2apb.Ciphersuite_CHACHA20_POLY1305_SHA256}, outLocalIdentities: []*s2apb.Identity{ { IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "test_server_spiffe_id", }, }, { IdentityOneof: &s2apb.Identity_Hostname{ Hostname: "test_server_hostname", }, }, { IdentityOneof: &s2apb.Identity_Uid{ Uid: "test_server_uid", }, }, }, outS2AAddress: "test_s2a_address", }, } { t.Run(tc.desc, func(t *testing.T) { c, err := NewServerCreds(tc.opts) if err != nil { t.Fatalf("NewServerCreds(_) failed: %v", err) } if got, want := c.Info().SecurityProtocol, s2aSecurityProtocol; got != want { t.Errorf("c.Info().SecurityProtocol = %v, want %v", got, want) } s2aCreds, ok := c.(*s2aTransportCreds) if !ok { t.Fatal("The created creds is not of type s2aTransportCreds") } if got, want := s2aCreds.minTLSVersion, tc.outMinTLSVersion; got != want { t.Errorf("s2aCreds.minTLSVersion = %v, want %v", got, want) } if got, want := s2aCreds.maxTLSVersion, tc.outMaxTLSVersion; got != want { t.Errorf("s2aCreds.maxTLSVersion = %v, want %v", got, want) } if got, want := s2aCreds.tlsCiphersuites, tc.outTLSCiphersuites; !cmp.Equal(got, want) { t.Errorf("s2aCreds.tlsCiphersuites = %v, want %v", got, want) } if got, want := s2aCreds.localIdentities, tc.outLocalIdentities; !cmp.Equal(got, want, protocmp.Transform()) { t.Errorf("s2aCreds.localIdentities = %v, want %v", got, want) } if got, want := s2aCreds.s2aAddr, tc.outS2AAddress; got != want { t.Errorf("s2aCreds.s2aAddr = %v, want %v", got, want) } }) } } func TestHandshakeFail(t *testing.T) { cc := &s2aTransportCreds{isClient: false} if _, _, err := cc.ClientHandshake(context.Background(), "", nil); err == nil { t.Errorf("c.ClientHandshake(nil, \"\", nil) should fail with incorrect transport credentials") } sc := &s2aTransportCreds{isClient: true} if _, _, err := sc.ServerHandshake(nil); err == nil { t.Errorf("c.ServerHandshake(nil) should fail with incorrect transport credentials") } } func TestInfo(t *testing.T) { // This is not testing any handshaker functionality, so it's fine to only // use NewServerCreds and not NewClientCreds. c, err := NewServerCreds(&ServerOptions{}) if err != nil { t.Fatalf("NewServerCreds(&ServerOptions{}) failed: %v", err) } info := c.Info() if got, want := info.ProtocolVersion, ""; got != want { t.Errorf("info.ProtocolVersion=%v, want %v", got, want) } if got, want := info.SecurityProtocol, "tls"; got != want { t.Errorf("info.SecurityProtocol=%v, want %v", got, want) } if got, want := info.ServerName, ""; got != want { t.Errorf("info.ServerName=%v, want %v", got, want) } } func TestCloneClient(t *testing.T) { opt := &ClientOptions{ TargetIdentities: []Identity{ &spiffeID{"test_server_spiffe_id"}, &hostname{"test_server_hostname"}, }, LocalIdentity: &hostname{"test_client_hostname"}, S2AAddress: "test_s2a_address", EnableLegacyMode: true, } c, err := NewClientCreds(opt) if err != nil { t.Fatalf("NewClientCreds(%v) failed: %v", opt, err) } cc := c.Clone() s2aCreds, ok := c.(*s2aTransportCreds) if !ok { t.Fatal("The created creds is not of type s2aTransportCreds") } s2aCloneCreds, ok := cc.(*s2aTransportCreds) if !ok { t.Fatal("The created cloned creds is not of type s2aTransportCreds") } if got, want := cmp.Equal(s2aCreds, s2aCloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2aTransportCreds{})), true; got != want { t.Errorf("cmp.Equal(%v, %v) = %v, want %v", s2aCreds, s2aCloneCreds, got, want) } // Change the values and verify that the creds were deep copied. s2aCloneCreds.targetIdentities[0] = &s2apb.Identity{ IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "new_spiffe_id", }, } if got, want := cmp.Equal(s2aCreds, s2aCloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2aTransportCreds{})), false; got != want { t.Errorf("cmp.Equal(%v, %v) = %v, want %v", s2aCreds, s2aCloneCreds, got, want) } } func TestCloneServer(t *testing.T) { c, err := NewServerCreds(&ServerOptions{ LocalIdentities: []Identity{ &spiffeID{"test_server_spiffe_id"}, &hostname{"test_server_hostname"}, }, S2AAddress: "test_s2a_address", EnableLegacyMode: true, }) if err != nil { t.Fatalf("NewServerCreds(&ServerOptions{}) failed: %v", err) } cc := c.Clone() s2aCreds, ok := c.(*s2aTransportCreds) if !ok { t.Fatal("The created creds is not of type s2aTransportCreds") } s2aCloneCreds, ok := cc.(*s2aTransportCreds) if !ok { t.Fatal("The created cloned creds is not of type s2aTransportCreds") } if got, want := cmp.Equal(s2aCreds, s2aCloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2aTransportCreds{})), true; got != want { t.Errorf("cmp.Equal(%v, %v) = %v, want %v", s2aCreds, s2aCloneCreds, got, want) } // Change the values and verify that the creds were deep copied. s2aCloneCreds.localIdentities[0] = &s2apb.Identity{ IdentityOneof: &s2apb.Identity_SpiffeId{ SpiffeId: "new_spiffe_id", }, } if got, want := cmp.Equal(s2aCreds, s2aCloneCreds, protocmp.Transform(), cmp.AllowUnexported(s2aTransportCreds{})), false; got != want { t.Errorf("cmp.Equal(%v, %v) = %v, want %v", s2aCreds, s2aCloneCreds, got, want) } } func TestOverrideServerName(t *testing.T) { wantServerName := "server.name" // This is not testing any handshaker functionality, so it's fine to only // use NewServerCreds and not NewClientCreds. c, err := NewServerCreds(&ServerOptions{}) if err != nil { t.Fatalf("NewServerCreds(&ServerOptions{}) failed: %v", err) } if got, want := c.Info().ServerName, ""; got != want { t.Errorf("c.Info().ServerName = %v, want %v", got, want) } if err := c.OverrideServerName(wantServerName); err != nil { t.Fatalf("c.OverrideServerName(%v) failed: %v", wantServerName, err) } if got, want := c.Info().ServerName, wantServerName; got != want { t.Errorf("c.Info().ServerName = %v, want %v", got, want) } } func TestGetVerificationMode(t *testing.T) { for _, tc := range []struct { description string verificationMode VerificationModeType expVerificationMode s2av2pb.ValidatePeerCertificateChainReq_VerificationMode }{ { description: "connect to google", verificationMode: ConnectToGoogle, expVerificationMode: s2av2pb.ValidatePeerCertificateChainReq_CONNECT_TO_GOOGLE, }, { description: "spiffe", verificationMode: Spiffe, expVerificationMode: s2av2pb.ValidatePeerCertificateChainReq_SPIFFE, }, { description: "unspecified", verificationMode: Unspecified, expVerificationMode: s2av2pb.ValidatePeerCertificateChainReq_UNSPECIFIED, }, } { t.Run(tc.description, func(t *testing.T) { if got, want := getVerificationMode(tc.verificationMode), tc.expVerificationMode; got != want { t.Errorf("got = %v, want = %v", got, want) } }) } } s2a-go-0.1.8/s2a_utils.go000066400000000000000000000054761464711036600150700ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a import ( "context" "errors" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" ) // AuthInfo exposes security information from the S2A to the application. type AuthInfo interface { // AuthType returns the authentication type. AuthType() string // ApplicationProtocol returns the application protocol, e.g. "grpc". ApplicationProtocol() string // TLSVersion returns the TLS version negotiated during the handshake. TLSVersion() commonpb.TLSVersion // Ciphersuite returns the ciphersuite negotiated during the handshake. Ciphersuite() commonpb.Ciphersuite // PeerIdentity returns the authenticated identity of the peer. PeerIdentity() *commonpb.Identity // LocalIdentity returns the local identity of the application used during // session setup. LocalIdentity() *commonpb.Identity // PeerCertFingerprint returns the SHA256 hash of the peer certificate used in // the S2A handshake. PeerCertFingerprint() []byte // LocalCertFingerprint returns the SHA256 hash of the local certificate used // in the S2A handshake. LocalCertFingerprint() []byte // IsHandshakeResumed returns true if a cached session was used to resume // the handshake. IsHandshakeResumed() bool // SecurityLevel returns the security level of the connection. SecurityLevel() credentials.SecurityLevel } // AuthInfoFromPeer extracts the authinfo.S2AAuthInfo object from the given // peer, if it exists. This API should be used by gRPC clients after // obtaining a peer object using the grpc.Peer() CallOption. func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) { s2aAuthInfo, ok := p.AuthInfo.(AuthInfo) if !ok { return nil, errors.New("no S2AAuthInfo found in Peer") } return s2aAuthInfo, nil } // AuthInfoFromContext extracts the authinfo.S2AAuthInfo object from the given // context, if it exists. This API should be used by gRPC server RPC handlers // to get information about the peer. On the client-side, use the grpc.Peer() // CallOption and the AuthInfoFromPeer function. func AuthInfoFromContext(ctx context.Context) (AuthInfo, error) { p, ok := peer.FromContext(ctx) if !ok { return nil, errors.New("no Peer found in Context") } return AuthInfoFromPeer(p) } s2a-go-0.1.8/s2a_utils_test.go000066400000000000000000000056201464711036600161160ustar00rootroot00000000000000/* * * Copyright 2021 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 s2a import ( "context" "testing" commonpb "github.com/google/s2a-go/internal/proto/common_go_proto" "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" ) func TestAuthInfoFromContext(t *testing.T) { ctx := context.Background() s2aAuthInfo := &fakeS2AAuthInfo{} p := &peer.Peer{ AuthInfo: s2aAuthInfo, } for _, tc := range []struct { desc string ctx context.Context success bool out AuthInfo }{ { "working case", peer.NewContext(ctx, p), true, s2aAuthInfo, }, } { authInfo, err := AuthInfoFromContext(tc.ctx) if got, want := (err == nil), tc.success; got != want { t.Errorf("%v: AuthInfoFromContext(_)=(err=nil)=%v, want %v", tc.desc, got, want) } if got, want := authInfo, tc.out; got != want { t.Errorf("%v:, AuthInfoFromContext(_)=(%v, _), want (%v, _)", tc.desc, got, want) } } } func TestAuthInfoFromPeer(t *testing.T) { s2aAuthInfo := &fakeS2AAuthInfo{} p := &peer.Peer{ AuthInfo: s2aAuthInfo, } for _, tc := range []struct { desc string p *peer.Peer success bool out AuthInfo }{ { "working case", p, true, s2aAuthInfo, }, } { authInfo, err := AuthInfoFromPeer(tc.p) if got, want := (err == nil), tc.success; got != want { t.Errorf("%v: AuthInfoFromPeer(_)=(err=nil)=%v, want %v", tc.desc, got, want) } if got, want := authInfo, tc.out; got != want { t.Errorf("%v:, AuthInfoFromPeer(_)=(%v, _), want (%v, _)", tc.desc, got, want) } } } type fakeS2AAuthInfo struct{} func (*fakeS2AAuthInfo) AuthType() string { return "" } func (*fakeS2AAuthInfo) ApplicationProtocol() string { return "" } func (*fakeS2AAuthInfo) TLSVersion() commonpb.TLSVersion { return commonpb.TLSVersion_TLS1_3 } func (*fakeS2AAuthInfo) Ciphersuite() commonpb.Ciphersuite { return commonpb.Ciphersuite_AES_128_GCM_SHA256 } func (*fakeS2AAuthInfo) PeerIdentity() *commonpb.Identity { return nil } func (*fakeS2AAuthInfo) LocalIdentity() *commonpb.Identity { return nil } func (*fakeS2AAuthInfo) PeerCertFingerprint() []byte { return nil } func (*fakeS2AAuthInfo) LocalCertFingerprint() []byte { return nil } func (*fakeS2AAuthInfo) IsHandshakeResumed() bool { return false } func (*fakeS2AAuthInfo) SecurityLevel() credentials.SecurityLevel { return credentials.PrivacyAndIntegrity } s2a-go-0.1.8/stream/000077500000000000000000000000001464711036600141135ustar00rootroot00000000000000s2a-go-0.1.8/stream/s2a_stream.go000066400000000000000000000021701464711036600165020ustar00rootroot00000000000000/* * * Copyright 2023 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 stream provides an interface for bidirectional streaming to the S2A server. package stream import ( s2av2pb "github.com/google/s2a-go/internal/proto/v2/s2a_go_proto" ) // S2AStream defines the operation for communicating with the S2A server over a bidirectional stream. type S2AStream interface { // Send sends the message to the S2A server. Send(*s2av2pb.SessionReq) error // Recv receives the message from the S2A server. Recv() (*s2av2pb.SessionResp, error) // Closes the channel to the S2A server. CloseSend() error } s2a-go-0.1.8/testdata/000077500000000000000000000000001464711036600144315ustar00rootroot00000000000000s2a-go-0.1.8/testdata/README.md000066400000000000000000000027761464711036600157240ustar00rootroot00000000000000**Generating certificates and keys for testing mTLS-S2A** Create root CA ``` openssl req -x509 -sha256 -days 7305 -newkey rsa:2048 -keyout mds_root_key.pem -out mds_root_cert.pem ``` Generate private keys for server and client ``` openssl genrsa -out mds_server_key.pem 2048 openssl genrsa -out mds_client_key.pem 2048 ``` Generate CSRs for server and client ``` openssl req -key mds_server_key.pem -new -out mds_server.csr -config config.cnf openssl req -key mds_client_key.pem -new -out mds_client.csr -config config.cnf ``` Look at CSR ``` openssl req -noout -text -in mds_server.csr openssl req -noout -text -in mds_client.csr ``` Sign CSRs for server and client ``` openssl x509 -req -CA mds_root_cert.pem -CAkey mds_root_key.pem -in mds_server.csr -out mds_server_cert.pem -days 7305 -extfile config.cnf -extensions req_ext openssl x509 -req -CA mds_root_cert.pem -CAkey mds_root_key.pem -in mds_client.csr -out mds_client_cert.pem -days 7305 ``` Look at signed certs ``` openssl x509 -in mds_server_cert.pem -noout -text openssl x509 -in mds_client_cert.pem -noout -text ``` Verify server and client certs using root CA ``` openssl verify -CAfile mds_root_cert.pem mds_server_cert.pem openssl verify -CAfile mds_root_cert.pem mds_client_cert.pem ``` Create self-signed key/cert to test failure case ``` openssl genrsa -out self_signed_key.pem 2048 openssl req -new -key self_signed_key.pem -out self_signed.csr openssl x509 -req -in self_signed.csr -signkey self_signed_key.pem -out self_signed_cert.pem -days 7305 ``` s2a-go-0.1.8/testdata/client_cert.pem000066400000000000000000000026241464711036600174330ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu 0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 /P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco pKklVz0= -----END CERTIFICATE----- s2a-go-0.1.8/testdata/client_key.pem000066400000000000000000000032131464711036600172610ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj +Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G 4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh 68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ /+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx 2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm 56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= -----END RSA PRIVATE KEY----- s2a-go-0.1.8/testdata/config.cnf000066400000000000000000000010641464711036600163670ustar00rootroot00000000000000[req] distinguished_name = req_distinguished_name req_extensions = req_ext [req_distinguished_name] countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (eg, city) organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, your name or your server\'s hostname) emailAddress = Email Address [req_ext] subjectAltName = @alt_names [alt_names] IP.1 = :: s2a-go-0.1.8/testdata/mds_client.csr000066400000000000000000000017551464711036600172730ustar00rootroot00000000000000-----BEGIN CERTIFICATE REQUEST----- MIICrDCCAZQCAQAwOTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMR0wGwYDVQQD DBR0ZXN0LXMyYS1tdGxzLWNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKq0EDMsTbZnQgfrmN7M4EbHz6ygvk1fRbrJ3fD32glbhkxnEgSjNNfJ 1dkw59yGBUNR4C6RsBsDhQwW98tKPYtv5dlSckq4l9RkjV+pw5lWrEJTtcLjiwj+ /y0Zju2+iorHuVtCBYWGqbSslp3pJ9qUtLQI4pqqX59sNFOhQxrUFKoP7a0EJhrU 0iR42wPjhXdBBQtfChj/EPozjGjJCUZqXhIgD8hzw6DIakDU9ukQKb/Y9lM6OErl 8xx+k3AHZtfsxvhF2P1GSl/aA5Em8CCbzfoApjcjkS2pSddoLBmDgozHfCtJpVwa q5pmzlR1W1JvdOtpYRO8efQAPAyuA6ECAwEAAaAuMCwGCSqGSIb3DQEJDjEfMB0w GwYDVR0RBBQwEocQAAAAAAAAAAAAAAAAAAAAADANBgkqhkiG9w0BAQsFAAOCAQEA i3A/Evfcv87UG1Egp9IDvhYZ6ieWsbxzmcgAWJmYT7jWpxA7tO6UsS2i7ZZHHMK/ 6hROqLRSWgK/Br5LVw83WT40CdC0A5sQRm2LhYisZfMWX3wZ7NjIH+AuK/4s517b V46WQ/WcIks1Wd6IKRJec7R0C3RPWMfS8Ucu8xWHWkup0qP2OHX5k47pxpl8xCoS YNeeVyX2D6pOV/sEP0HKBQZ9VsufoN+hojfQDn5fH31rutV3yK5LeVRXZFQLAW8I 1Ep7+t6Y1NTjnfUr9ennf4JeQWdloDOF4OLoyWIX6zSNEPZV6eaWQpur+qkmZo19 8xeGpL7742J/sx0JREXTMg== -----END CERTIFICATE REQUEST----- s2a-go-0.1.8/testdata/mds_client_cert.pem000066400000000000000000000021271464711036600202740ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDCDCCAfACFFlYsYCFit01ZpYmfjxpo7/6wMEbMA0GCSqGSIb3DQEBCwUAMEgx CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEPMA0GA1UECgwGR29vZ2xlMRswGQYD VQQDDBJ0ZXN0LXMyYS1tdGxzLXJvb3QwHhcNMjMwODIyMTY0NTE4WhcNNDMwODIy MTY0NTE4WjA5MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExHTAbBgNVBAMMFHRl c3QtczJhLW10bHMtY2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAqrQQMyxNtmdCB+uY3szgRsfPrKC+TV9Fusnd8PfaCVuGTGcSBKM018nV2TDn 3IYFQ1HgLpGwGwOFDBb3y0o9i2/l2VJySriX1GSNX6nDmVasQlO1wuOLCP7/LRmO 7b6Kise5W0IFhYaptKyWnekn2pS0tAjimqpfn2w0U6FDGtQUqg/trQQmGtTSJHjb A+OFd0EFC18KGP8Q+jOMaMkJRmpeEiAPyHPDoMhqQNT26RApv9j2Uzo4SuXzHH6T cAdm1+zG+EXY/UZKX9oDkSbwIJvN+gCmNyORLalJ12gsGYOCjMd8K0mlXBqrmmbO VHVbUm9062lhE7x59AA8DK4DoQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCPOvtL dq2hxFHlIy0YUK8jp/DtwJZPwzx1id5FtWwd0CxBS1StIgmkHMxtkJGz1iyQLplI je+Msd4sTsb5zZi/8kGKehi8Wj4lghp4oP30cpob41OvM68M9RC/wSOVk9igSww+ l3zof6wKRIswsi5VHrL16ruIVVoDlyFbKr8yk+cp9OPOV8hNNN7ewY9xC8OgnTt8 YtdaLe6uTplKBLW+j3GtshigRhyfkGJyPFYL4LAeDJCHlC1qmBnkyP0ijMp6vneM E8TLavnMTMcpihWTWpyKeRkO6HDRsP4AofQAp7VAiAdSOplga+w2qgrVICV+m8MK BTq2PBvc59T6OFLq -----END CERTIFICATE----- s2a-go-0.1.8/testdata/mds_client_key.pem000066400000000000000000000032501464711036600201250ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqtBAzLE22Z0IH 65jezOBGx8+soL5NX0W6yd3w99oJW4ZMZxIEozTXydXZMOfchgVDUeAukbAbA4UM FvfLSj2Lb+XZUnJKuJfUZI1fqcOZVqxCU7XC44sI/v8tGY7tvoqKx7lbQgWFhqm0 rJad6SfalLS0COKaql+fbDRToUMa1BSqD+2tBCYa1NIkeNsD44V3QQULXwoY/xD6 M4xoyQlGal4SIA/Ic8OgyGpA1PbpECm/2PZTOjhK5fMcfpNwB2bX7Mb4Rdj9Rkpf 2gORJvAgm836AKY3I5EtqUnXaCwZg4KMx3wrSaVcGquaZs5UdVtSb3TraWETvHn0 ADwMrgOhAgMBAAECggEAUccupZ1ZY4OHTi0PkNk8rpwFwTFGyeFVEf2ofkr24RnA NnUAXEllxOUUNlcoFOz9s3kTeavg3qgqgpa0QmdAIb9LMXg+ec6CKkW7trMpGho8 LxBUWNfSoU4sKEqAvyPT0lWJVo9D/up6/avbAi6TIbOw+Djzel4ZrlHTpabxc3WT EilXzn4q54b3MzxCQeQjcnzTieW4Q5semG2kLiXFToHIY2di01P/O8awUjgrD+uW /Cb6H49MnHm9VPkqea1iwZeMQd6Gh5FrC7RezsBjdB1JBcfsv6PFt2ySInjB8SF+ XR5Gr3Cc5sh9s0LfprZ9Dq0rlSWmwasPMI1COK6SswKBgQDczgeWd3erQ1JX9LEI wollawqC9y7uJhEsw1hrPqA3uqZYiLUc7Nmi4laZ12mcGoXNDS3R3XmD58qGmGaU lxEVTb8KDVWBgw450VoBKzSMQnCP6zn4nZxTYxeqMKjDGf6TRB6TZc843qsG3eRC k91yxrCQ/0HV6PT48C+lieDzLwKBgQDF6aNKiyrswr457undBnM1H8q/Y6xC5ZlK UtiQdhuyBnicvz0U8WPxBY/8gha0OXWuSnBqq/z77iFVNv/zT6p9K7kM7nBGd8cB 8KO6FNbyaHWFrhCI5zNzRTH4oha0hfvUOoti09vqavCtWD4L+D/63ba1wNLKPO9o 4gWbCnUCLwKBgQC/vus372csgrnvR761LLrEJ8BpGt7WUJh5luoht7DKtHvgRleB Vu1oVcV+s2Iy/ZVUDC3OIdZ0hcWKPK5YOxfKuEk+IXYvke+4peTTPwHTC59UW6Fs FPK8N0FFuhvT0a8RlAY5WiAp8rPysp6WcnHMSl7qi8BQUozp4Sp/RsziYQKBgBXv r4mzoy5a53rEYGd/L4XT4EUWZyGDEVqLlDVu4eL5lKTLDZokp08vrqXuRVX0iHap CYzJQ2EpI8iuL/BoBB2bmwcz5n3pCMXORld5t9lmeqA2it6hwbIlGUTVsm6P6zm6 w3hQwy9YaxTLkxUAjxbfPEEo/jQsTNzzMGve3NlBAoGAbgJExpDyMDnaD2Vi5eyr 63b54BsqeLHqxJmADifyRCj7G1SJMm3zMKkNNOS0vsXgoiId973STFf1XQiojiv8 Slbxyv5rczcY0n3LOuQYcM5OzsjzpNFZsT2dDnMfNRUF3rx3Geu/FuJ9scF1b00r fVMrcL3jSf/W1Xh4TgtyoU8= -----END PRIVATE KEY----- s2a-go-0.1.8/testdata/mds_root_cert.pem000066400000000000000000000023451464711036600200030ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDcTCCAlmgAwIBAgIUDUkgI+2FZtuUHyUUi0ZBH7JvN00wDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQKDAZHb29nbGUx GzAZBgNVBAMMEnRlc3QtczJhLW10bHMtcm9vdDAeFw0yMzA4MjEyMTI5MTVaFw00 MzA4MjEyMTI5MTVaMEgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEPMA0GA1UE CgwGR29vZ2xlMRswGQYDVQQDDBJ0ZXN0LXMyYS1tdGxzLXJvb3QwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbFEQfpvla27bATedrN4BAWsI9GSwSnJLW QWzXcnAk6cKxQBAhnaKHRxHY8ttLhNTtxQeub894CLzJvHE/0xDhuMzjtCCCZ7i2 r08tKZ1KcEzPJCPNlxlzAXPA45XU3LRlbGvju/PBPhm6n1hCEKTNI/KETJ5DEaYg Cf2LcXVsl/zW20MwDZ+e2w/9a2a6n6DdpW1ekOR550hXAUOIxvmXRBeYeGLFvp1n rQgZBhRaxP03UB+PQD2oMi/4mfsS96uGCXdzzX8qV46O8m132HUbnA/wagIwboEe d7Bx237dERDyHw5GFnll7orgA0FOtoEufXdeQxWVvTjO0+PVPgsvAgMBAAGjUzBR MB0GA1UdDgQWBBRyMtg/yutV8hw8vOq0i8x0eBQi7DAfBgNVHSMEGDAWgBRyMtg/ yutV8hw8vOq0i8x0eBQi7DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA A4IBAQArN/gdqWMxd5Rvq2eJMTp6I4RepJOT7Go4sMsRsy1caJqqcoS2EvREDZMN XNEBcyQBB5kYd6TCcZGoLnEtWYXQ4jjEiXG1g7/+rWxyqw0ZYuP7FWzuHg3Uor/x fApbEKwptP5ywVc+33h4qreGcqXkVCCn+sAcstGgrqubdGZW2T5gazUMyammOOuN 9IWL1PbvXmgEKD+80NUIrk09zanYyrElGdU/zw/kUbZ3Jf6WUBtJGhTzRQ1qZeKa VnpCbLoG3vObEB8mxDUAlIzwAtfvw4U32BVIZA8xrocz6OOoAnSW1bTlo3EOIo/G MTV7jmY9TBPtfhRuO/cG650+F+cw -----END CERTIFICATE----- s2a-go-0.1.8/testdata/mds_root_key.pem000066400000000000000000000034761464711036600176440ustar00rootroot00000000000000-----BEGIN ENCRYPTED PRIVATE KEY----- MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIIxtHqH4HVrACAggA MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECFjU1fjS/n59BIIEyNzJwdg/x5JP dZFh+k6NWaaomXf9yurqA9fZtw8LrjMWiFdL/FjpWUVoxk+75BZdtwXGOnGHV1Ks nPj+1dcc3Vlnli2LhtJVtZbjHWwJUtSMXT4s1aBS9r1gUHA9toxsWBqnRKcjJpFd rnt12WdrEmPPJdz1pZyi3TM7q0XWS75OvFW9WdA+FJwyidlG4Y/doGmRYb7ObqHv PLadtlC7WtZOuNswDxZAyMgGAS10Kk3pohMZ1RCaa/7J625zlmx3Ps1U3PzchvPI MEv+Y8g5hkEbRP8tIpcuOrzwNsmQ5VkNeQmD6CAgKAyqwwmJAlKzCvJnXLJa+nsD iSMXPk7tJasLLHFYO4InZO1zuk8WL+AajnYYaipiC1sOxOfegaxjMAjV2qiqrDrE TwIEk/SbDOFd80dEQgVz++5BYhxdCiplL2aO5s8Cw9slhfEXb/XohIbEKvO5oeFD fqdQLkEZ0IEEg/0d5jO4bdNiXIsGTV6WlVbQXmihqpDiP8GHabGBDWI1Ov1fj4e6 Vx22bQucRM/IdkSebNZguL4PFBVBKZAC+uM1sxO8h5HRfquI5TjuAnbvp7PQ1a94 un5LCWN3ydMrzC9jdm3pzVb+Rt+J2JzhOJfJSHuAFhUnSWsCrNS/+QFH+/QffQ0r Ki6XBydmhKelJo0m+T5RbodKDlEVRbExDdQe6k7SZiYhyF/FEB1NjVwLHFUr02cj URilU5WEoJF85T07zh1hzZHP+grsKgmVE8b7qsA51OVyac0TW58qWXdm5UaYvGqJ gRYA7EuvFHlfqgxRsupNlCO95vk8Dz2LbHwgt/Q0rXcDXLwC10ycbo0JIRF2zMW5 2DuCEYweByFv8x8FwIYj/ForlCWXLQjXkiB/nkyjzGOiNG3PQzy61BceYfhkAs49 ZYt/BseXwNOgizgXKY7jyWU7g6R29isq90sg3sYp/y2MHh/OsHHWC3nSSHoBRa23 FUkB0hogd7RJCXrNo/s9QfEuRZlQLfj1iogGuOK4vrne15WMU3Yu7Bi5is/KuzIj xm/mjq3GMaENk2Mz4FyCy77H2w/coQuki5FjiYwXFRHyhpkYl7ePyfLT19t7b4Mt 3w1cfq1hrY37UbFGJM5mzKzcjFGSzcIxyGhHNGqrYKJSKfSOJAroD8v4l0cJLQ2M alEPpDvT5/Nkvzvwd3tH6Rqli6AHlYy4OxJXTr567bpjclZHGOq+7wWjPRalRDiY Gqj1ARE8+Qa/WLVAZM2GRZ2uZ/eQ12rS28gofSUr8Ur4ELdiFKHw+b9Nz9bIGquM M8EW0GutSJvqJ+q9Xn722C5SkQp/oMSImL2lmHWZeHr5mgoNH5AqwBm1r01GRnVt jNO8Poi+ncPSRP0Peq/qQ5kXEx5phCPNm6ZFcCrEipv798xm7eebUM474RICMRFC +XKVLlT8er4jZ1HSncvvtTx17OiyYh2PaPRH8GQW8t0nfs/YclH+qcQCAmIsEBCo 391KjCKYXeKR9bigZWErphjxDFK+m0vXUtW2jGAVj05XLddTc0oeCH2gyzRZx1gy iHzL0mRJXFaBAcoOb78L/0mWwfn7CP4klYenhingE7lQXB30Rzr/rr54I4+sofnF T6/FrKRlfUmczNYDQIixHw== -----END ENCRYPTED PRIVATE KEY----- s2a-go-0.1.8/testdata/mds_server.csr000066400000000000000000000017551464711036600173230ustar00rootroot00000000000000-----BEGIN CERTIFICATE REQUEST----- MIICrDCCAZQCAQAwOTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMR0wGwYDVQQD DBR0ZXN0LXMyYS1tdGxzLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAIwTPJuwY+p+H3YYvDLjea3yRAMXfO2vzLTpHBTWFWdjtCpgrihum+Ee QlWdPP2DA0EXefmdRqWpHNpy2V/Y8LJ032hJg0I7yy9Waju/DUKV4oAoUCJXlCcf vpCWoPXmgmt6HudIzxHiqPkq6Qge+3Rw3SAPoIlDMhREO2wonCRbfJCNjJP8UAoZ i0WsHpu4OfcSDcezDrPu6PsLMsGxKXsEgatAgtulsj2cU1PetRNSFdkpj/dS0kA5 vroCNOYxsPXpEZhlHgmw/HoKy2F6J8nphIjv2vkqAPfvNfSMxcVaKa9vZKZmYV4u iiG0Lwru5PKOb91E7Hqcdd0O3lNBhccCAwEAAaAuMCwGCSqGSIb3DQEJDjEfMB0w GwYDVR0RBBQwEocQAAAAAAAAAAAAAAAAAAAAADANBgkqhkiG9w0BAQsFAAOCAQEA glGG7pd5jffzc7qJfSl5WlglTFkBSVYNz/6nZ33GfAfm2O/SZYYW4+XbGZUsLkzm ifeNB3i/C9yu4C8EMmU3o2nlAVGhoKnwqC5PO/vnnvo8EKtNiqg5eJMnMulZgpc9 QmL+gQ0715UnVhAIhivftpFqaDhAwyubicQ7AC4W/x2KXaJ36UU4ehXI1xr33m1+ 48p+lVyR8UUuCVKVoqndAaebE4c9lqhTfM6cL8Pruve1/IJ/xdxcAW+KKIr4uzcp 30Pd/Ts6XEeVY9i++yMypl7BNemw4mQQ1i3bpvzN+tgb5AtmbyD72bC2nJn0HlLd umOUQ3HqOVMYgx+3jJTO5g== -----END CERTIFICATE REQUEST----- s2a-go-0.1.8/testdata/mds_server_cert.pem000066400000000000000000000023411464711036600203220ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDbjCCAlagAwIBAgIUbexZ5sZl86Al9dsI2PkOgtqKnkgwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQKDAZHb29nbGUx GzAZBgNVBAMMEnRlc3QtczJhLW10bHMtcm9vdDAeFw0yMzA4MjIwMDMyMDRaFw00 MzA4MjIwMDMyMDRaMDkxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEdMBsGA1UE AwwUdGVzdC1zMmEtbXRscy1zZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCMEzybsGPqfh92GLwy43mt8kQDF3ztr8y06RwU1hVnY7QqYK4obpvh HkJVnTz9gwNBF3n5nUalqRzactlf2PCydN9oSYNCO8svVmo7vw1CleKAKFAiV5Qn H76QlqD15oJreh7nSM8R4qj5KukIHvt0cN0gD6CJQzIURDtsKJwkW3yQjYyT/FAK GYtFrB6buDn3Eg3Hsw6z7uj7CzLBsSl7BIGrQILbpbI9nFNT3rUTUhXZKY/3UtJA Ob66AjTmMbD16RGYZR4JsPx6CstheifJ6YSI79r5KgD37zX0jMXFWimvb2SmZmFe LoohtC8K7uTyjm/dROx6nHXdDt5TQYXHAgMBAAGjXzBdMBsGA1UdEQQUMBKHEAAA AAAAAAAAAAAAAAAAAAAwHQYDVR0OBBYEFI3i2+tIk6YYn0MIxC0q93jk1VsUMB8G A1UdIwQYMBaAFHIy2D/K61XyHDy86rSLzHR4FCLsMA0GCSqGSIb3DQEBCwUAA4IB AQAUhk+s/lrIAULBbU7E22C8f93AzTxE1mhyHGNlfPPJP3t1Dl+h4X4WkFpkz5gT EcNXB//Vvoq99HbEK5/92sxsIPexKdJBdcggeHXIgLDkOrEZEb0Nnh9eaAuU2QDn JW44hMB+aF6mEaJvOHE6DRkQw3hwFYFisFKKHtlQ3TyOhw5CHGzSExPZusdSFNIe 2E7V/0QzGPJEFnEFUNe9N8nTH2P385Paoi+5+Iizlp/nztVXfzv0Cj/i+qGgtDUs HB+gBU2wxMw8eYyuNzACH70wqGR1Parj8/JoyYhx0S4+Gjzy3JH3CcAMaxyfH/dI 4Wcvfz/isxgmH1UqIt3oc6ad -----END CERTIFICATE----- s2a-go-0.1.8/testdata/mds_server_key.pem000066400000000000000000000032501464711036600201550ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCMEzybsGPqfh92 GLwy43mt8kQDF3ztr8y06RwU1hVnY7QqYK4obpvhHkJVnTz9gwNBF3n5nUalqRza ctlf2PCydN9oSYNCO8svVmo7vw1CleKAKFAiV5QnH76QlqD15oJreh7nSM8R4qj5 KukIHvt0cN0gD6CJQzIURDtsKJwkW3yQjYyT/FAKGYtFrB6buDn3Eg3Hsw6z7uj7 CzLBsSl7BIGrQILbpbI9nFNT3rUTUhXZKY/3UtJAOb66AjTmMbD16RGYZR4JsPx6 CstheifJ6YSI79r5KgD37zX0jMXFWimvb2SmZmFeLoohtC8K7uTyjm/dROx6nHXd Dt5TQYXHAgMBAAECggEAIB5zGdIG/yh/Z1GBqfuOFaxFGx5iJ5BVlLAVH9P9IXFz yPnVRXEjbinFlSMSbqEBeIX9EpcVMXxHIPIP1RIGEy2IYr3kiqXyT771ahDDZh6/ Spqz0UQatSPqyvW3H9uE0Uc12dvQm23JSCUmPRX5m7gbhDQBIChXzdzdcU4Yi59V 4xmJUvbsAcLw5CBM6kwV+1NGVH9+3mUdhrr9M6B6+sVB/xnaqMGEDfQGiwL8U7EY QOuc46KXu3Pd/qCdVLn60IrdjSzDJKeC5UZZ+ejNAo+DfbtOovBj3qu3OCUg4XVy 0CDBJ1sTdLvUfF4Gb+crjPsd+qBbXcjVfqdadwhsoQKBgQDBF1Pys/NitW8okJwp 2fiDIASP3TiI+MthWHGyuoZGPvmXQ3H6iuLSm8c/iYI2WPTf53Xff1VcFm1GmQms GCsYM8Ax94zCeO6Ei1sYYxwcBloEZfOeV37MPA4pjJF4Lt+n5nveNxP+lrsjksJz wToSEgWPDT1b/xcdt4/5j9J85wKBgQC5tiLx+33mwH4DoaFRmSl0+VuSNYFw6DTQ SQ+kWqWGH4NENc9wf4Dj2VUZQhpXNhXVSxj+aP2d/ck1NrTJAWqYEXCDtFQOGSa2 cGPRr+Fhy5NIEaEvR7IXcMBZzx3koYmWVBHricyrXs5FvHrT3N14mGDUG8n24U3f R799bau0IQKBgQC97UM+lHCPJCWNggiJRgSifcje9VtZp1btjoBvq/bNe74nYkjn htsrC91Fiu1Qpdlfr50K1IXSyaB886VG6JLjAGxI+dUzqJ38M9LLvxj0G+9JKjsi AbAQFfZcOg8QZxLJZPVsE0MQhZTXndC06VhEVAOxvPUg214Sde8hK61/+wKBgCRw O10VhnePT2pw/VEgZ0T/ZFtEylgYB7zSiRIrgwzVBBGPKVueePC8BPmGwdpYz2Hh cU8B1Ll6QU+Co2hJMdwSl+wPpup5PuJPHRbYlrV0lzpt0x2OyL/WrLcyb2Ab3f40 EqwPhqwdVwXR3JvTW1U9OMqFhVQ+kuP7lPQMX8NhAoGBAJOgZ7Tokipc4Mi68Olw SCaOPvjjy4sW2rTRuKyjc1wTAzy7SJ3vXHfGkkN99nTLJFwAyJhWUpnRdwAXGi+x gyOa95ImsEfRSwEjbluWfF8/P0IU8GR+ZTqT4NnNCOsi8T/xst4Szd1ECJNnnZDe 1ChfPP1AH+/75MJCvu6wQBQv -----END PRIVATE KEY----- s2a-go-0.1.8/testdata/self_signed.csr000066400000000000000000000017101464711036600174230ustar00rootroot00000000000000-----BEGIN CERTIFICATE REQUEST----- MIICkjCCAXoCAQAwTTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ0wCwYDVQQK DARUZXN0MSIwIAYDVQQDDBl0ZXN0LXMyYS1tdGxzLXNlbGYtc2lnbmVkMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoUU+xhqwpl4IUsReXdGkT9k5cV7a WG60hqVKlm8Kayj6ZAahnhwcrsC36QOMGLkKudeRhzDuq5ACEeBTR+uFZ2Pu2xYd RS2rtPx5oZYoGdUP1+X4yO0CXUGaFfBX2pEFuPgR6xIoYNIakp/rp063PDzclsFx TteU8AfVzXOjYZcLWGKZxn5JUYdWs6Ofg2Z4WzyD3j8OR7x1aQfC/lhMxW6AUrjk rEqBI4qSviRrs8IHODEKdbjBhJk1EdzGuqSICs7YcBCrQAKvu759UNgf//2Y/ZkA Oj/NyHs7nKGSI1uNckhGum0NYS5VgxGWhgOFPvveHttX9DRajQ1Aa1qwnwIDAQAB oAAwDQYJKoZIhvcNAQELBQADggEBAHKusdAj6/hNNSZIPQhUpm+eMYWZrLLQMSGq bXzh4uibrqMcQIPTopf4HrMt5mKrBqssUf4siWionE0FySHxqIWs6nBx+L+3Zpz6 5c5bGILLI5o4j9v9XXFBPk+M0dmlzs33Fm/qJleeu57zZnjRp5D00gfDr2wNfOFU pjJIlws73riz7zP474411u0J9Hx0sph3PNfjvD+tWW2Ver4gLdgH9fHQlWh7JZPw iW7qYFYbh6bvq6Q8Y8Nbub+vYDCRT87qqd0EAnf9nepaiUennnqzH7jVmdLrcyHg 7X5AORVWOEOzutLftJ4QTROOyte4OIuEdB5P5G+BNBseGon2OeY= -----END CERTIFICATE REQUEST----- s2a-go-0.1.8/testdata/self_signed_cert.pem000066400000000000000000000021731464711036600204360ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDITCCAgkCFBS8mLoytMpMWBwpAtnRaq3eIKnsMA0GCSqGSIb3DQEBCwUAME0x CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTENMAsGA1UECgwEVGVzdDEiMCAGA1UE AwwZdGVzdC1zMmEtbXRscy1zZWxmLXNpZ25lZDAeFw0yMzA4MjIyMTE2MDFaFw00 MzA4MjIyMTE2MDFaME0xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTENMAsGA1UE CgwEVGVzdDEiMCAGA1UEAwwZdGVzdC1zMmEtbXRscy1zZWxmLXNpZ25lZDCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKFFPsYasKZeCFLEXl3RpE/ZOXFe 2lhutIalSpZvCmso+mQGoZ4cHK7At+kDjBi5CrnXkYcw7quQAhHgU0frhWdj7tsW HUUtq7T8eaGWKBnVD9fl+MjtAl1BmhXwV9qRBbj4EesSKGDSGpKf66dOtzw83JbB cU7XlPAH1c1zo2GXC1himcZ+SVGHVrOjn4NmeFs8g94/Dke8dWkHwv5YTMVugFK4 5KxKgSOKkr4ka7PCBzgxCnW4wYSZNRHcxrqkiArO2HAQq0ACr7u+fVDYH//9mP2Z ADo/zch7O5yhkiNbjXJIRrptDWEuVYMRloYDhT773h7bV/Q0Wo0NQGtasJ8CAwEA ATANBgkqhkiG9w0BAQsFAAOCAQEAPjbH0TMyegF/MDvglkc0sXr6DqlmTxDCZZmG lYPZ5Xy062+rxIHghMARbvO4BxepiG37KsP2agvOldm4TtU8nQ8LyswmSIFm4BQ+ XQWwdsWyYyd8l0d5sXAdaN6AXwy50fvqCepmEqyreMY6dtLzlwo9gVCBFB7QuAPt Nc14phpEUZt/KPNuY6cUlB7bz3tmnFbwxUrWj1p0KBEYsr7+KEVZxR+z0wtlU7S9 ZBrmUvx0fq5Ef7JWtHW0w4ofg1op742sdYl+53C26GZ76ts4MmqVz2/94DScgRaU gT0GLVuuCZXRDVeTXqTb4mditRCfzFPe9cCegYhGhSqBs8yh5A== -----END CERTIFICATE----- s2a-go-0.1.8/testdata/self_signed_key.pem000066400000000000000000000032501464711036600202660ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChRT7GGrCmXghS xF5d0aRP2TlxXtpYbrSGpUqWbwprKPpkBqGeHByuwLfpA4wYuQq515GHMO6rkAIR 4FNH64VnY+7bFh1FLau0/HmhligZ1Q/X5fjI7QJdQZoV8FfakQW4+BHrEihg0hqS n+unTrc8PNyWwXFO15TwB9XNc6NhlwtYYpnGfklRh1azo5+DZnhbPIPePw5HvHVp B8L+WEzFboBSuOSsSoEjipK+JGuzwgc4MQp1uMGEmTUR3Ma6pIgKzthwEKtAAq+7 vn1Q2B///Zj9mQA6P83IezucoZIjW41ySEa6bQ1hLlWDEZaGA4U++94e21f0NFqN DUBrWrCfAgMBAAECggEAR8e8YwyqJ8KezcgdgIC5M9kp2i4v3UCZFX0or8CI0J2S pUbWVLuKgLXCpfIwPyjNf15Vpei/spkMcsx4BQDthdFTFSzIpmvni0z9DlD5VFYj ESOJElV7wepbHPy2/c+izmuL/ic81aturGiFyRgeMq+cN3WuaztFTXkPTrzzsZGF p/Mx3gqm7Hoc3d2xlv+8L5GjCtEJPlQgZJV+s3ennBjOAd8CC7d9qJetE3Er46pn r5jedV3bQRZYBzmooYNHjbAs26++wYac/jTE0/U6nKS17eWq4BQZUtlMXUw5N81B 7LKn7C03rj2KCn+Nf5uin9ALmoy888LXCDdvL/NZkQKBgQDduv1Heu+tOZuNYUdQ Hswmd8sVNAAWGZxdxixHMv58zrgbLFXSX6K89X2l5Sj9XON8TH46MuSFdjSwwWw5 fBrhVEhA5srcqpvVWIBE05yqPpt0s1NQktMWJKELWlG8jOhVKwM5OYDpdxtwehpz 1g70XJz+nF/LTV8RdTK+OWDDpQKBgQC6MhdbGHUz/56dY3gZpE5TXnN2hkNbZCgk emr6z85VHhQflZbedhCzB9PUnZnCKWOGQHQdxRTtRfd46LVboZqCdYO1ZNQv6toP ysS7dTpZZFy7CpQaW0Y6/jS65jW6xIDKR1W40vgltZ3sfpG37JaowpzWdw2WuOnw Bg0rcJAf8wKBgQCqE+p/z97UwuF8eufWnyj9QNo382E1koOMspv4KTdnyLETtthF vDH6O1wbykG8xmmASLRyM+NyNA+KnXNETNvZh2q8zctBpGRQK8iIAsGjHM7ln0AD B/x+ea5GJQuZU4RK/+lDFca6TjBwAFkWDVX/PqL18kDQkxKfM4SuwRhmOQKBgDGh eoJIsa0LnP787Z2AI3Srf4F/ZmLs/ppCm1OBotEjdF+64v0nYWonUvqgi8SqfaHi elEZIGvis4ViGj1zhRjzNAlc+AZRxpBhDzGcnNIJI4Kj3jhsTfsZmXqcNIQ1LtM8 Uogyi/yZPaA1WKg7Aym2vlGYaGHdplXZdxc2KOSrAoGABRkD9l2OVcwK7RyNgFxo mjxx0tfUdDBhHIi2igih1FiHpeP9E+4/kE/K7PnU9DoDrL1jW1MTpXaYV4seOylk k9z/9QfcRa9ePD2N4FqbHWSYp5n3aLoIcGq/9jyjTwayZbbIhWO+vNuHE9wIvecZ 8x3gNkxJRb4NaLIoNzAhCoo= -----END PRIVATE KEY----- s2a-go-0.1.8/testdata/server_cert.pem000066400000000000000000000026241464711036600174630ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIUKCoDuLtiZXvhsBY2RoDm0ugizJ8wDQYJKoZIhvcNAQEL BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN MjIwNTMxMjAwODI1WhcNNDIwNTI2MjAwODI1WjCBhzELMAkGA1UEBhMCVVMxCzAJ BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKK1++PXQ+M3hjYH/v0K4UEYl5ljzpNM1i52eQM+gFooojT87PDSaphT fs0PXy/PTAjHBEvPhWpOpmQXfJNYzjwcCvg66hbqkv++/VTZiFLAsHagzkEz+FRJ qT5Eq7G5FLyw1izX1uxyPN7tAEWEEg7eqsiaXD3Cq8+TYN9cjirPeF7RZF8yFCYE xqvbo+Yc6RL6xw19iXVTfctRgQe581KQuIY5/LXo3dWDEilFdsADAe8XAEcO64es Ow0g1UvXLnpXSE151kXBFb3sKH/ZjCecDYMCIMEb4sWLSblkSxJ5sNSmXIG4wtr2 Qnii7CXZgnVYraQE/Jyh+NMQANuoSdMCAwEAAaNTMFEwHQYDVR0OBBYEFAyQQQuM ab+YUQqjK8dVVOoHVFmXMB8GA1UdIwQYMBaAFAyQQQuMab+YUQqjK8dVVOoHVFmX MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADj0vQ6ykWhicoqR e6VZMwlEJV7/DSvWWKBd9MUjfKye0A4565ya5lmnzP3DiD3nqGe3miqmLsXKDs+X POqlPXTWIamP7D4MJ32XtSLwZB4ru+I+Ao/P/VngPepoRPQoBnzHe7jww0rokqxl AZERjlbTUwUAy/BPWPSzSJZ2j0tcs6ZLDNyYzpK4ao8R9/1VmQ92Tcp3feJs1QTg odRQc3om/AkWOwsll+oyX0UbJeHkFHiLanUPXbdh+/BkSvZJ8ynL+feSDdaurPe+ PSfnqLtQft9/neecGRdEaQzzzSFVQUVQzTdK1Q7hA7b55b2HvIa3ktDiks+sJsYN Dhm6uZM= -----END CERTIFICATE----- s2a-go-0.1.8/testdata/server_key.pem000066400000000000000000000032171464711036600173150ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAorX749dD4zeGNgf+/QrhQRiXmWPOk0zWLnZ5Az6AWiiiNPzs 8NJqmFN+zQ9fL89MCMcES8+Fak6mZBd8k1jOPBwK+DrqFuqS/779VNmIUsCwdqDO QTP4VEmpPkSrsbkUvLDWLNfW7HI83u0ARYQSDt6qyJpcPcKrz5Ng31yOKs94XtFk XzIUJgTGq9uj5hzpEvrHDX2JdVN9y1GBB7nzUpC4hjn8tejd1YMSKUV2wAMB7xcA Rw7rh6w7DSDVS9cueldITXnWRcEVvewof9mMJ5wNgwIgwRvixYtJuWRLEnmw1KZc gbjC2vZCeKLsJdmCdVitpAT8nKH40xAA26hJ0wIDAQABAoIBACaNR+lsD8G+XiZf LqN1+HkcAo9tfnyYMAdCOtnx7SdviT9Uzi8hK/B7mAeuJLeHPlS2EuaDfPD7QaFl jza6S+MiIdc+3kgfvESsVAnOoOY6kZUJ9NSuI6CU82y1iJjLaYZrv9NQMLRFPPb0 4KOX709mosB1EnXvshW0rbc+jtDFhrm1SxMt+k9TuzmMxjbOeW4LOLXPgU8X1T3Q Xy0hMZZtcgBs9wFIo8yCtmOixax9pnFE8rRltgDxTodn9LLdz1FieyntNgDksZ0P nt4kV7Mqly7ELaea+Foaj244mKsesic2e3GhAlMRLun/VSunSf7mOCxfpITB8dp1 drDhOYECgYEA19151dVxRcviuovN6Dar+QszMTnU8pDJ8BjLFjXjP/hNBBwMTHDE duMuWk2qnwZqMooI/shxrF/ufmTgS0CFrh2+ANBZu27vWConJNXcyNtdigI4wt50 L0Y2qcZn2mg67qFXHwoR3QNwrwnPwEjRXA09at9CSRZzcwDQ0ETXhYsCgYEAwPaG 06QdK8Zyly7TTzZJwxzv9uGiqzodmGtX6NEKjgij2JaCxHpukqZBJoqa0jKeK1cm eNVkOvT5ff9TMzarSHQLr3pZen2/oVLb5gaFkbcJt/klv9Fd+ZRilHY3i6QwS6pD uMiPOWS4DrLHDRVoVlAZTDjT1RVwwTs+P2NhJdkCgYEAsriXysbxBYyMp05gqEW7 lHIFbFgpSrs9th+Q5U6wW6JEgYaHWDJ1NslY80MiZI93FWjbkbZ7BvBWESeL3EIL a+EMErht0pVCbIhZ6FF4foPAqia0wAJVx14mm+G80kNBp5jE/NnleEsE3KcO7nBb hg8gLn+x7bk81JZ0TDrzBYkCgYEAuQKluv47SeF3tSScTfKLPpvcKCWmxe1uutkQ 7JShPhVioyOMNb39jnYBOWbjkm4d4QgqRuiytSR0oi3QI+Ziy5EYMyNn713qAk9j r2TJZDDPDKnBW+zt4YI4EohWMXk3JRUW4XDKggjjwJQA7bZ812TtHHvP/xoThfG7 eSNb3eECgYBw6ssgCtMrdvQiEmjKVX/9yI38mvC2kSGyzbrQnGUfgqRGomRpeZuD B5E3kysA4td5pT5lvcLgSW0TbOz+YbiriXjwOihPIelCvc9gE2eOUI71/byUWPFz 7u5F/xQ4NaGr5suLF+lBC6h7pSbM4El9lIHQAQadpuEdzHqrw+hs3g== -----END RSA PRIVATE KEY----- s2a-go-0.1.8/tools/000077500000000000000000000000001464711036600137605ustar00rootroot00000000000000s2a-go-0.1.8/tools/internal_ci/000077500000000000000000000000001464711036600162475ustar00rootroot00000000000000s2a-go-0.1.8/tools/internal_ci/run_gae_test.sh000066400000000000000000000024101464711036600212570ustar00rootroot00000000000000# Copyright 2024 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. #!/bin/bash # inspired by https://github.com/grpc/grpc-java/blob/master/buildscripts/kokoro/gae-interop.sh # Fail on any error. set -e # Display commands being run. set -x KOKORO_GAE_DEFAULT_APP_VERSION="default" PROJECT_ID=$(curl "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google") # Setup app. cd "tools/internal_ci/test_gae" go mod edit -go=1.22 export CLOUDSDK_CORE_DISABLE_PROMPTS=1 # Deploy the app. gcloud app deploy --version=$KOKORO_GAE_DEFAULT_APP_VERSION APP_URL=$(gcloud app browse --no-launch-browser --version="$KOKORO_GAE_DEFAULT_APP_VERSION" --project="$PROJECT_ID") if curl -s $APP_URL | grep "success" then exit 0 else exit 1 fi s2a-go-0.1.8/tools/internal_ci/run_golang_tests.sh000077500000000000000000000032261464711036600221660ustar00rootroot00000000000000# 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. #!/bin/bash # Fail on any error. set -e # Display commands being run. set -x readonly PLATFORM="$(uname | tr '[:upper:]' '[:lower:]')" fail_with_debug_output() { ls -l df -h / exit 1 } run_tests() { time go build -buildvcs=false ./... || fail_with_debug_output time go test -buildvcs=false ./... || fail_with_debug_output } main() { # Install a newer Golang version on GCP Ubuntu VMs. which go sudo rm -rf /usr/local/go case "${PLATFORM}" in 'linux') sudo rm -rf /usr/local/go curl -O https://dl.google.com/go/go1.21.12.linux-amd64.tar.gz tar -xvf go1.21.12.linux-amd64.tar.gz sudo mv go /usr/local export GOROOT=/usr/local/go export PATH=$PATH:$GOROOT/bin ;; 'darwin') sudo rm -rf /usr/local/go curl -O https://dl.google.com/go/go1.21.12.darwin-amd64.tar.gz tar -xvf go1.21.12.darwin-amd64.tar.gz sudo mv go /usr/local export GOROOT=/usr/local/go export PATH="${GOROOT}/bin:${PATH}" ;; *) echo "Using existing Go installation." ;; esac go version run_tests } main "$@" s2a-go-0.1.8/tools/internal_ci/run_hygiene_tests.sh000077500000000000000000000030511464711036600223430ustar00rootroot00000000000000# 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. #!/bin/bash set -ex set -o pipefail readonly PLATFORM="$(uname | tr '[:upper:]' '[:lower:]')" not() { ! "$@" } fail_on_output() { tee /dev/stderr | not read } which go sudo rm -rf /usr/local/go case "${PLATFORM}" in 'linux') sudo rm -rf /usr/local/go curl -O https://dl.google.com/go/go1.21.12.linux-amd64.tar.gz tar -xvf go1.21.12.linux-amd64.tar.gz sudo mv go /usr/local export GOROOT=/usr/local/go export PATH=$PATH:$GOROOT/bin ;; 'darwin') sudo rm -rf /usr/local/go curl -O https://dl.google.com/go/go1.21.12.darwin-amd64.tar.gz tar -xvf go1.21.12.darwin-amd64.tar.gz sudo mv go /usr/local export GOROOT=/usr/local/go export PATH="${GOROOT}/bin:${PATH}" ;; *) echo "Using existing Go installation." ;; esac go version # TODO(mattstev): Install goimports and run: # goimports -l . 2>&1 | not grep -vE "\.pb\.go" go vet -all ./... | fail_on_output gofmt -s -d -l . 2>&1 | fail_on_output go mod tidy echo SUCCESS s2a-go-0.1.8/tools/internal_ci/test_gae/000077500000000000000000000000001464711036600200425ustar00rootroot00000000000000s2a-go-0.1.8/tools/internal_ci/test_gae/app.yaml000066400000000000000000000000441464711036600215040ustar00rootroot00000000000000runtime: go122 app_engine_apis: trues2a-go-0.1.8/tools/internal_ci/test_gae/main.go000066400000000000000000000050421464711036600213160ustar00rootroot00000000000000package main import ( "fmt" "log" "net/http" "os" "github.com/google/s2a-go" "google.golang.org/api/option" "google.golang.org/appengine" "google.golang.org/grpc" "google.golang.org/grpc/credentials/oauth" translate "cloud.google.com/go/translate/apiv3" translatepb "cloud.google.com/go/translate/apiv3/translatepb" ) const serverAddr = "translate.mtls.googleapis.com:443" func indexHandler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } ctx := appengine.NewContext(r) creds, err := s2a.NewClientCreds(&s2a.ClientOptions{S2AAddress: "metadata.google.internal:80"}) if err != nil { errorMessage := "Failed to create S2A client credentials: %v" + err.Error() log.Fatalf("%v", errorMessage) http.Error(w, errorMessage, http.StatusBadRequest) return } perRPCCreds, err := oauth.NewApplicationDefault(ctx, "https://www.googleapis.com/auth/cloud-platform") if err != nil { errorMessage := "Failed to get per-RPC credentials: %v" + err.Error() log.Fatalf("%v", errorMessage) http.Error(w, errorMessage, http.StatusBadRequest) return } opts := []grpc.DialOption{ grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(perRPCCreds), grpc.WithBlock(), grpc.WithReturnConnectionError(), } conn, err := grpc.DialContext(ctx, serverAddr, opts...) if err != nil { errorMessage := "Client: failed to connect: %v" + err.Error() log.Fatalf("%v", errorMessage) http.Error(w, errorMessage, http.StatusBadRequest) return } defer conn.Close() cliOpts := []option.ClientOption{option.WithGRPCConn(conn)} client, err := translate.NewTranslationClient(ctx, cliOpts...) if err != nil { errorMessage := "Failed to create client: %v" + err.Error() log.Fatalf("%v", errorMessage) http.Error(w, errorMessage, http.StatusBadRequest) } req := &translatepb.TranslateTextRequest{ Contents: []string{"Hello World!"}, SourceLanguageCode: "en", TargetLanguageCode: "es", Parent: fmt.Sprintf("projects/%s", os.Getenv("GOOGLE_CLOUD_PROJECT")), } _, err = client.TranslateText(ctx, req) if err != nil { errorMessage := "Failed to translate: %v" + err.Error() log.Fatalf("%v", errorMessage) http.Error(w, errorMessage, http.StatusBadRequest) } fmt.Fprintf(w, "success") } func main() { http.HandleFunc("/", indexHandler) port := os.Getenv("PORT") if port == "" { port = "8080" log.Printf("Defaulting to port %s", port) } log.Printf("Listening on port %s", port) if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatal(err) } } s2a-go-0.1.8/tools/proto/000077500000000000000000000000001464711036600151235ustar00rootroot00000000000000s2a-go-0.1.8/tools/proto/regenerate_proto.sh000077500000000000000000000104761464711036600210360ustar00rootroot00000000000000# 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. #!/bin/bash go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest export PATH="$PATH:$(go env GOPATH)/bin" # Regenerate the S2A protos. protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ internal/proto/common/common.proto internal/proto/s2a/s2a.proto internal/proto/s2a_context/s2a_context.proto mkdir -p internal/proto/common_go_proto mv internal/proto/common/common.pb.go internal/proto/common_go_proto/common.pb.go mkdir -p internal/proto/s2a_go_proto mv internal/proto/s2a/s2a.pb.go internal/proto/s2a_go_proto/s2a.pb.go mv internal/proto/s2a/s2a_grpc.pb.go internal/proto/s2a_go_proto/s2a_grpc.pb.go sed -i 's/common_go_proto \"github.com\/google\/s2a\/internal\/proto\/common_go_proto\"/common_go_proto \"github.com\/google\/s2a-go\/internal\/proto\/common_go_proto\"/g' internal/proto/s2a_go_proto/s2a.pb.go mkdir -p internal/proto/s2a_context_go_proto mv internal/proto/s2a_context/s2a_context.pb.go internal/proto/s2a_context_go_proto/s2a_context.pb.go sed -i 's/common_go_proto \"github.com\/google\/s2a\/internal\/proto\/common_go_proto\"/common_go_proto \"github.com\/google\/s2a-go\/internal\/proto\/common_go_proto\"/g' internal/proto/s2a_context_go_proto/s2a_context.pb.go # Regenerate the S2Av2 protos. protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ internal/proto/v2/common/common.proto internal/proto/v2/s2a_context/s2a_context.proto internal/proto/v2/s2a/s2a.proto mkdir -p internal/proto/v2/common_go_proto mv internal/proto/v2/common/common.pb.go internal/proto/v2/common_go_proto/common.pb.go mkdir -p internal/proto/v2/s2a_go_proto mv internal/proto/v2/s2a/s2a.pb.go internal/proto/v2/s2a_go_proto/s2a.pb.go mv internal/proto/v2/s2a/s2a_grpc.pb.go internal/proto/v2/s2a_go_proto/s2a_grpc.pb.go sed -i 's/common_go_proto1 \"github.com\/google\/s2a\/internal\/proto\/common_go_proto\"/common_go_proto1 \"github.com\/google\/s2a-go\/internal\/proto\/common_go_proto\"/g' internal/proto/v2/s2a_go_proto/s2a.pb.go sed -i 's/common_go_proto \"github.com\/google\/s2a\/internal\/proto\/v2\/common_go_proto\"/common_go_proto \"github.com\/google\/s2a-go\/internal\/proto\/v2\/common_go_proto\"/g' internal/proto/v2/s2a_go_proto/s2a.pb.go sed -i 's/s2a_context_go_proto \"github.com\/google\/s2a\/internal\/proto\/v2\/s2a_context_go_proto\"/s2a_context_go_proto \"github.com\/google\/s2a-go\/internal\/proto\/v2\/s2a_context_go_proto\"/g' internal/proto/v2/s2a_go_proto/s2a.pb.go mkdir -p internal/proto/v2/s2a_context_go_proto mv internal/proto/v2/s2a_context/s2a_context.pb.go internal/proto/v2/s2a_context_go_proto/s2a_context.pb.go sed -i 's/common_go_proto \"github.com\/google\/s2a\/internal\/proto\/v2\/common_go_proto\"/common_go_proto \"github.com\/google\/s2a-go\/internal\/proto\/v2\/common_go_proto\"/g' internal/proto/v2/s2a_context_go_proto/s2a_context.pb.go # Regenerate the example protos. protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ internal/proto/examples/helloworld.proto mkdir -p internal/proto/examples/helloworld_go_proto mv internal/proto/examples/helloworld.pb.go internal/proto/examples/helloworld_go_proto/helloworld.pb.go mv internal/proto/examples/helloworld_grpc.pb.go internal/proto/examples/helloworld_go_proto/helloworld_grpc.pb.go # Regenerate the echo example protos. protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ example/proto/echo.proto mkdir -p example/proto/echo_go_proto mv example/proto/echo.pb.go example/proto/echo_go_proto/echo.pb.go mv example/proto/echo_grpc.pb.go example/proto/echo_go_proto/echo_grpc.pb.go