blob: 485a08b189b6048405ef1ac20e935b51f3fa2f4f [file] [log] [blame]
// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Implements a simple framework for scoping TSS values.
// Based on chrome's base/memory/scoped_ptr_malloc implementation.
//
// Example usage:
// ScopedTssContext context_handle;
// TSS_RESULT result;
// if (!OpenAndConnectTpm(context_handle.ptr(), &result))
// ...
// ScopedTssKey srk(context_handle);
// if (!LoadSrk(context_handle, srk_handle.ptr(), &result))
// ...
//
// See the bottom of this file for common typedefs.
#ifndef CRYPTOHOME_SCOPED_TSS_TYPE_H_
#define CRYPTOHOME_SCOPED_TSS_TYPE_H_
#include <assert.h>
#include <base/compiler_specific.h>
#include <trousers/tss.h>
#include <trousers/trousers.h>
#include <vector>
namespace cryptohome {
class ScopedTssContextRelease {
public:
inline void operator()(TSS_HCONTEXT unused, TSS_HCONTEXT context) const {
// Usually, only |context| is used, but if the ScopedTssContext is
// used slightly differently, it may end up with a context in |unused|.
// For now, treat that as a bug.
assert(unused == 0);
if (context)
Tspi_Context_Close(context);
}
};
class ScopedTssMemoryRelease {
public:
inline void operator()(TSS_HCONTEXT context, BYTE* memory) const {
// TODO(wad) make the test code friendly for assert()ing context/memory != 0
if (context && memory)
Tspi_Context_FreeMemory(context, memory);
}
};
class ScopedTssObjectRelease {
public:
inline void operator()(TSS_HCONTEXT context, TSS_HOBJECT handle) const {
// TODO(wad) make the test code friendly for assert() context/handle != 0
if (context && handle)
Tspi_Context_CloseObject(context, handle);
}
};
// Provide a basic scoped container for TSS managed objects.
template<class TssType, class ReleaseProc = ScopedTssObjectRelease>
class ScopedTssType {
public:
explicit ScopedTssType(TSS_HCONTEXT c = 0, TssType t = 0) :
context_(c),
type_(t) {}
virtual ~ScopedTssType() {
release_(context_, type_);
}
// Provide a means to access the value without conversion.
virtual TssType value() {
return type_;
}
// Allow direct referencing of the wrapped value.
virtual TssType* ptr() {
return &type_;
}
// Returns the assigned context.
virtual TSS_HCONTEXT context() {
return context_;
}
virtual TssType release() WARN_UNUSED_RESULT {
TssType tmp = type_;
type_ = 0;
context_ = 0;
return tmp;
}
virtual void reset(TSS_HCONTEXT c = 0, TssType t = 0) {
release_(context_, type_);
context_ = c;
type_ = t;
}
private:
static ReleaseProc const release_;
TSS_HCONTEXT context_;
TssType type_;
};
// Wrap ScopedTssObject to allow implicit conversion only when safe.
template<class TssType = TSS_HOBJECT,
class ReleaseProc = ScopedTssObjectRelease>
class ScopedTssObject : public ScopedTssType<TssType, ReleaseProc> {
public:
// Enforce a context for scoped objects.
explicit ScopedTssObject(TSS_HCONTEXT c, TssType t = 0) {}
virtual ~ScopedTssObject() {}
// Allow implicit conversion to anything TSS_HOBJECT based.
virtual operator TssType() {
return this->value();
}
};
class ScopedTssContext
: public ScopedTssObject<TSS_HCONTEXT, ScopedTssContextRelease> {
public:
// Enforce a context for scoped objects.
explicit ScopedTssContext(TSS_HCONTEXT t = 0)
: ScopedTssObject<TSS_HCONTEXT,ScopedTssContextRelease>(0, t) {}
virtual ~ScopedTssContext() {}
};
// Provide clear-cut typedefs for the common cases.
typedef ScopedTssType<BYTE*, ScopedTssMemoryRelease> ScopedTssMemory;
typedef ScopedTssObject<TSS_HKEY> ScopedTssKey;
typedef ScopedTssObject<TSS_HPOLICY> ScopedTssPolicy;
typedef ScopedTssObject<TSS_HPCRS> ScopedTssPcrs;
typedef ScopedTssObject<TSS_HNVSTORE> ScopedTssNvStore;
} // namespace cryptohome
#endif // CRYPTOHOME_SCOPED_TSS_TYPE_H_