• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 #include <grpc/support/port_platform.h>
19 
20 #include "absl/log/check.h"
21 #include "src/core/tsi/ssl/session_cache/ssl_session.h"
22 #include "src/core/util/crash.h"
23 
24 #ifndef OPENSSL_IS_BORINGSSL
25 
26 #include "absl/memory/memory.h"
27 #include "src/core/lib/slice/slice.h"
28 
29 // OpenSSL invalidates SSL_SESSION on SSL destruction making it pointless
30 // to cache sessions. The workaround is to serialize (relatively expensive)
31 // session into binary blob and re-create it from blob on every handshake.
32 // Note that it's safe to keep serialized session outside of SSL lifetime
33 // as openssl performs all necessary validation while attempting to use a
34 // session and creates a new one if something is wrong (e.g. server changed
35 // set of allowed codecs).
36 
37 namespace tsi {
38 namespace {
39 
40 class OpenSslCachedSession : public SslCachedSession {
41  public:
OpenSslCachedSession(SslSessionPtr session)42   OpenSslCachedSession(SslSessionPtr session) {
43     int size = i2d_SSL_SESSION(session.get(), nullptr);
44     CHECK_GT(size, 0);
45     grpc_slice slice = grpc_slice_malloc(size_t(size));
46     unsigned char* start = GRPC_SLICE_START_PTR(slice);
47     int second_size = i2d_SSL_SESSION(session.get(), &start);
48     CHECK(size == second_size);
49     serialized_session_ = slice;
50   }
51 
~OpenSslCachedSession()52   virtual ~OpenSslCachedSession() {
53     grpc_core::CSliceUnref(serialized_session_);
54   }
55 
CopySession() const56   SslSessionPtr CopySession() const override {
57     const unsigned char* data = GRPC_SLICE_START_PTR(serialized_session_);
58     size_t length = GRPC_SLICE_LENGTH(serialized_session_);
59     SSL_SESSION* session = d2i_SSL_SESSION(nullptr, &data, length);
60     if (session == nullptr) {
61       return SslSessionPtr();
62     }
63     return SslSessionPtr(session);
64   }
65 
66  private:
67   grpc_slice serialized_session_;
68 };
69 
70 }  // namespace
71 
Create(SslSessionPtr session)72 std::unique_ptr<SslCachedSession> SslCachedSession::Create(
73     SslSessionPtr session) {
74   return std::make_unique<OpenSslCachedSession>(std::move(session));
75 }
76 
77 }  // namespace tsi
78 
79 #endif  // OPENSSL_IS_BORINGSSL
80