14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// Copyright (c) 2010 The Chromium Authors. All rights reserved.
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// Use of this source code is governed by a BSD-style license that can be
34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// found in the LICENSE file.
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#ifndef BASE_OPENSSL_UTIL_H_
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#define BASE_OPENSSL_UTIL_H_
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#pragma once
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#include "base/basictypes.h"
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#include "base/compiler_specific.h"
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#include "base/tracked.h"
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromnamespace base {
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// A helper class that takes care of destroying OpenSSL objects when it goes out
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// of scope.
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromtemplate <typename T, void (*destructor)(T*)>
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromclass ScopedOpenSSL {
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public:
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  ScopedOpenSSL() : ptr_(NULL) { }
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  explicit ScopedOpenSSL(T* ptr) : ptr_(ptr) { }
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  ~ScopedOpenSSL() {
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    reset(NULL);
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  T* get() const { return ptr_; }
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  void reset(T* ptr) {
284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    if (ptr != ptr_) {
294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom      if (ptr_) (*destructor)(ptr_);
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom      ptr_ = ptr;
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  T* release() WARN_UNUSED_RESULT {
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    T* result = ptr_;
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    ptr_ = NULL;
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    return result;
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private:
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  T* ptr_;
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSL);
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom};
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// Provides a buffer of at least MIN_SIZE bytes, for use when calling OpenSSL's
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// SHA256, HMAC, etc functions, adapting the buffer sizing rules to meet those
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// of the our base wrapper APIs.
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// This allows the library to write directly to the caller's buffer if it is of
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// sufficient size, but if not it will write to temporary |min_sized_buffer_|
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// of required size and then its content is automatically copied out on
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// destruction, with truncation as appropriate.
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromtemplate<int MIN_SIZE>
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromclass ScopedOpenSSLSafeSizeBuffer {
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public:
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  ScopedOpenSSLSafeSizeBuffer(unsigned char* output, size_t output_len)
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom      : output_(output),
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        output_len_(output_len) {
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  ~ScopedOpenSSLSafeSizeBuffer() {
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    if (output_len_ < MIN_SIZE) {
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom      // Copy the temporary buffer out, truncating as needed.
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom      memcpy(output_, min_sized_buffer_, output_len_);
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    // else... any writing already happened directly into |output_|.
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  unsigned char* safe_buffer() {
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    return output_len_ < MIN_SIZE ? min_sized_buffer_ : output_;
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private:
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // Pointer to the caller's data area and it's associated size, where data
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // written via safe_buffer() will [eventually] end up.
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  unsigned char* output_;
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  size_t output_len_;
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // Temporary buffer writen into in the case where the caller's
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // buffer is not of sufficient size.
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  unsigned char min_sized_buffer_[MIN_SIZE];
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSLSafeSizeBuffer);
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom};
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// Initialize OpenSSL if it isn't already initialized. This must be called
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// before any other OpenSSL functions.
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// This function is thread-safe, and OpenSSL will only ever be initialized once.
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// OpenSSL will be properly shut down on program exit.
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromvoid EnsureOpenSSLInit();
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// Drains the OpenSSL ERR_get_error stack. On a debug build the error codes
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// are send to VLOG(1), on a release build they are disregarded. In most
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// cases you should pass FROM_HERE as the |location|.
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromvoid ClearOpenSSLERRStack(const tracked_objects::Location& location);
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// Place an instance of this class on the call stack to automatically clear
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom// the OpenSSL error stack on function exit.
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromclass OpenSSLErrStackTracer {
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public:
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // Pass FROM_HERE as |location|, to help track the source of OpenSSL error
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // messages. Note any diagnostic emitted will be tagged with the location of
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  // the constructor call as it's not possible to trace a destructor's callsite.
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  explicit OpenSSLErrStackTracer(const tracked_objects::Location& location)
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom      : location_(location) {
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    EnsureOpenSSLInit();
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  ~OpenSSLErrStackTracer() {
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    ClearOpenSSLERRStack(location_);
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  }
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private:
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  const tracked_objects::Location location_;
1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom  DISALLOW_IMPLICIT_CONSTRUCTORS(OpenSSLErrStackTracer);
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom};
1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}  // namespace base
1184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom#endif  // BASE_OPENSSL_UTIL_H_
1204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom