15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Avoid including OpenSSL headers here.
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef struct ssl_ctx_st SSL_CTX;
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef struct ssl_st SSL;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLSessionCacheOpenSSLImpl;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A class used to implement a custom cache of SSL_SESSION objects.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Usage is as follows:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - Client creates a new cache instance with appropriate configuration,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    associating it with a given SSL_CTX object.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    The configuration must include a pointer to a client-provided function
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    that can retrieve a unique cache key from an existing SSL handle.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - When creating a new SSL connection, call SetSSLSession() with the newly
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    created SSL handle, and a cache key for the current host/port. If a
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    session is already in the cache, it will be added to the connection
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    through SSL_set_session().
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - Otherwise, OpenSSL will create a new SSL_SESSION object during the
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu//    connection, and will pass it to the cache's internal functions,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    transparently to the client.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - Each session has a timeout in seconds, which are checked every N-th call
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//    to SetSSLSession(), where N is the current configuration's
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    |check_expiration_count|. Expired sessions are removed automatically
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    from the cache.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - Clients can call Flush() to remove all sessions from the cache, this is
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    useful when the system's certificate store has changed.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is thread-safe. There shouldn't be any issue with multiple
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSL connections being performed in parallel in multiple threads.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NET_EXPORT SSLSessionCacheOpenSSL {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Type of a function that takes a SSL handle and returns a unique cache
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key string to identify it.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::string GetSessionKeyFunction(const SSL* ssl);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A small structure used to configure a cache on creation.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |key_func| is a function used at runtime to retrieve the unique cache key
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from a given SSL connection handle.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |max_entries| is the maximum number of entries in the cache.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |expiration_check_count| is the number of calls to SetSSLSession() that
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will trigger a check for expired sessions.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |timeout_seconds| is the timeout of new cached sessions in seconds.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Config {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetSessionKeyFunction* key_func;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_entries;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expiration_check_count;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int timeout_seconds;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSessionCacheOpenSSL() : impl_(NULL) {}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a new cache instance.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ctx| is a SSL_CTX context handle that will be associated with this cache.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |key_func| is a function that will be used at runtime to retrieve the
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unique cache key from a SSL connection handle.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |max_entries| is the maximum number of entries in the cache.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |timeout_seconds| is the timeout of new cached sessions in seconds.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |expiration_check_count| is the number of calls to SetSSLSession() that
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will trigger a check for expired sessions.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSessionCacheOpenSSL(SSL_CTX* ctx, const Config& config) : impl_(NULL) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reset(ctx, config);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroy this instance. This must be called before the SSL_CTX handle
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is destroyed.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SSLSessionCacheOpenSSL();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the cache configuration. This flushes any existing entries.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset(SSL_CTX* ctx, const Config& config);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size() const;
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lookup the unique cache key associated with |ssl| connection handle,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and find a cached session for it in the cache. If one is found, associate
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it with the |ssl| connection through SSL_set_session(). Consider using
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetSSLSessionWithKey() if you already have the key.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Every |check_expiration_count| call to either SetSSLSession() or
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetSSLSessionWithKey() triggers a check for, and removal of, expired
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sessions.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return true iff a cached session was associated with the |ssl| connection.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetSSLSession(SSL* ssl);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A more efficient variant of SetSSLSession() that can be used if the caller
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already has the cache key for the session of interest. The caller must
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ensure that the value of |cache_key| matches the result of calling the
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // configuration's |key_func| function with the |ssl| as parameter.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Every |check_expiration_count| call to either SetSSLSession() or
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetSSLSessionWithKey() triggers a check for, and removal of, expired
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sessions.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Return true iff a cached session was associated with the |ssl| connection.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return true iff a cached session was associated with the given |cache_key|.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SSLSessionIsInCache(const std::string& cache_key) const;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Indicates that the SSL session associated with |ssl| is "good" - that is,
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // that all associated cryptographic parameters that were negotiated,
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // including the peer's certificate, were successfully validated. Because
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // OpenSSL does not provide an asynchronous certificate verification
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // callback, it's necessary to manually manage the sessions to ensure that
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // only validated sessions are resumed.
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void MarkSSLSessionAsGood(SSL* ssl);
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Flush removes all entries from the cache. This is typically called when
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the system's certificate store has changed.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Flush();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(digit): Move to client code.
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  static const int kDefaultTimeoutSeconds = 60 * 60;
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  static const size_t kMaxEntries = 1024;
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  static const size_t kMaxExpirationChecks = 256;
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SSLSessionCacheOpenSSL);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSessionCacheOpenSSLImpl* impl_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace net
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)