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)