1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#ifndef CRYPTO_SCOPED_CAPI_TYPES_H_
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define CRYPTO_SCOPED_CAPI_TYPES_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <windows.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <wincrypt.h>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace crypto {
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Simple destructor for the Free family of CryptoAPI functions, such as
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CryptDestroyHash, which take only a single argument to release.
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle)>
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct CAPIDestroyer {
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void operator()(CAPIHandle handle) const {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (handle) {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BOOL ok = Destroyer(handle);
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DCHECK(ok);
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Destructor for the Close/Release family of CryptoAPI functions, which take
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a second DWORD parameter indicating flags to use when closing or releasing.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This includes functions like CertCloseStore or CryptReleaseContext.
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle, DWORD),
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          DWORD flags>
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct CAPIDestroyerWithFlags {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void operator()(CAPIHandle handle) const {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (handle) {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BOOL ok = Destroyer(handle, flags);
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DCHECK(ok);
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// scoped_ptr-like class for the CryptoAPI cryptography and certificate
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// handles. Because these handles are defined as integer types, and not
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// pointers, the existing scoped classes, such as scoped_ptr_malloc, are
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// insufficient. The semantics are the same as scoped_ptr.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <class CAPIHandle, typename FreeProc>
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScopedCAPIHandle {
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {}
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~ScopedCAPIHandle() {
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    free_(handle_);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void reset(CAPIHandle handle = NULL) {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (handle_ != handle) {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      free_(handle_);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handle_ = handle;
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  operator CAPIHandle() const { return handle_; }
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CAPIHandle get() const { return handle_; }
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CAPIHandle* receive() {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CHECK(handle_ == NULL);
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return &handle_;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool operator==(CAPIHandle handle) const {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return handle_ == handle;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool operator!=(CAPIHandle handle) const {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return handle_ != handle;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void swap(ScopedCAPIHandle& b) {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CAPIHandle tmp = b.handle_;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    b.handle_ = handle_;
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    handle_ = tmp;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CAPIHandle release() {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CAPIHandle tmp = handle_;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    handle_ = NULL;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return tmp;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CAPIHandle handle_;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const FreeProc free_;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ScopedCAPIHandle);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<class CH, typename FP>
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst FP ScopedCAPIHandle<CH, FP>::free_ = FP();
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<class CH, typename FP> inline
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool operator==(CH h, const ScopedCAPIHandle<CH, FP>& b) {
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return h == b.get();
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<class CH, typename FP> inline
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool operator!=(CH h, const ScopedCAPIHandle<CH, FP>& b) {
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return h != b.get();
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef ScopedCAPIHandle<
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HCRYPTPROV,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CAPIDestroyerWithFlags<HCRYPTPROV,
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           CryptReleaseContext, 0> > ScopedHCRYPTPROV;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef ScopedCAPIHandle<
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HCRYPTKEY, CAPIDestroyer<HCRYPTKEY, CryptDestroyKey> > ScopedHCRYPTKEY;
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef ScopedCAPIHandle<
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HCRYPTHASH, CAPIDestroyer<HCRYPTHASH, CryptDestroyHash> > ScopedHCRYPTHASH;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}  // namespace crypto
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif  // CRYPTO_SCOPED_CAPI_TYPES_H_
126