// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/cssm_init.h"

#include <Security/SecBase.h>
#include <stdint.h>

#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/singleton.h"
#include "base/strings/sys_string_conversions.h"

// When writing crypto code for Mac OS X, you may find the following
// documentation useful:
// - Common Security: CDSA and CSSM, Version 2 (with corrigenda)
//   http://www.opengroup.org/security/cdsa.htm
// - Apple Cryptographic Service Provider Functional Specification
// - CryptoSample: http://developer.apple.com/SampleCode/CryptoSample/

// CSSM functions are deprecated as of OSX 10.7, but have no replacement.
// https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

namespace {

void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) {
  return malloc(size);
}

void CSSMFree(void* mem_ptr, void* alloc_ref) {
  free(mem_ptr);
}

void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) {
  return realloc(ptr, size);
}

void* CSSMCalloc(uint32_t num, CSSM_SIZE size, void* alloc_ref) {
  return calloc(num, size);
}

class CSSMInitSingleton {
 public:
  static CSSMInitSingleton* GetInstance() {
    return base::Singleton<CSSMInitSingleton, base::LeakySingletonTraits<
                                                  CSSMInitSingleton>>::get();
  }

  CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; }
  CSSM_CL_HANDLE cl_handle() const { return cl_handle_; }
  CSSM_TP_HANDLE tp_handle() const { return tp_handle_; }

 private:
  CSSMInitSingleton()
      : inited_(false), csp_loaded_(false), cl_loaded_(false),
        tp_loaded_(false), csp_handle_(CSSM_INVALID_HANDLE),
        cl_handle_(CSSM_INVALID_HANDLE), tp_handle_(CSSM_INVALID_HANDLE) {
    static CSSM_VERSION version = {2, 0};
    // TODO(wtc): what should our caller GUID be?
    static const CSSM_GUID test_guid = {
      0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 }
    };
    CSSM_RETURN crtn;
    CSSM_PVC_MODE pvc_policy = CSSM_PVC_NONE;
    crtn = CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &test_guid,
                     CSSM_KEY_HIERARCHY_NONE, &pvc_policy, NULL);
    if (crtn) {
      NOTREACHED();
      return;
    }
    inited_ = true;

    crtn = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
    if (crtn) {
      NOTREACHED();
      return;
    }
    csp_loaded_ = true;
    crtn = CSSM_ModuleLoad(
        &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
    if (crtn) {
      NOTREACHED();
      return;
    }
    cl_loaded_ = true;
    crtn = CSSM_ModuleLoad(
        &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
    if (crtn) {
      NOTREACHED();
      return;
    }
    tp_loaded_ = true;

    const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = {
      CSSMMalloc,
      CSSMFree,
      CSSMRealloc,
      CSSMCalloc,
      NULL
    };

    crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0,
                             CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE,
                             NULL, 0, NULL, &csp_handle_);
    DCHECK_EQ(CSSM_OK, crtn);
    crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions,
                             0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE,
                             NULL, 0, NULL, &cl_handle_);
    DCHECK_EQ(CSSM_OK, crtn);
    crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions,
                             0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE,
                             NULL, 0, NULL, &tp_handle_);
    DCHECK_EQ(CSSM_OK, crtn);
  }

  ~CSSMInitSingleton() {
    CSSM_RETURN crtn;
    if (csp_handle_) {
      CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_);
      DCHECK_EQ(CSSM_OK, crtn);
    }
    if (cl_handle_) {
      CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_);
      DCHECK_EQ(CSSM_OK, crtn);
    }
    if (tp_handle_) {
      CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_);
      DCHECK_EQ(CSSM_OK, crtn);
    }
    if (csp_loaded_) {
      crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL);
      DCHECK_EQ(CSSM_OK, crtn);
    }
    if (cl_loaded_) {
      crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL);
      DCHECK_EQ(CSSM_OK, crtn);
    }
    if (tp_loaded_) {
      crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL);
      DCHECK_EQ(CSSM_OK, crtn);
    }
    if (inited_) {
      crtn = CSSM_Terminate();
      DCHECK_EQ(CSSM_OK, crtn);
    }
  }

  bool inited_;  // True if CSSM_Init has been called successfully.
  bool csp_loaded_;  // True if gGuidAppleCSP has been loaded
  bool cl_loaded_;  // True if gGuidAppleX509CL has been loaded.
  bool tp_loaded_;  // True if gGuidAppleX509TP has been loaded.
  CSSM_CSP_HANDLE csp_handle_;
  CSSM_CL_HANDLE cl_handle_;
  CSSM_TP_HANDLE tp_handle_;

  friend struct base::DefaultSingletonTraits<CSSMInitSingleton>;
};

}  // namespace

namespace crypto {

void EnsureCSSMInit() {
  CSSMInitSingleton::GetInstance();
}

CSSM_CSP_HANDLE GetSharedCSPHandle() {
  return CSSMInitSingleton::GetInstance()->csp_handle();
}

CSSM_CL_HANDLE GetSharedCLHandle() {
  return CSSMInitSingleton::GetInstance()->cl_handle();
}

CSSM_TP_HANDLE GetSharedTPHandle() {
  return CSSMInitSingleton::GetInstance()->tp_handle();
}

void* CSSMMalloc(CSSM_SIZE size) {
  return ::CSSMMalloc(size, NULL);
}

void CSSMFree(void* ptr) {
  ::CSSMFree(ptr, NULL);
}

void LogCSSMError(const char* fn_name, CSSM_RETURN err) {
  if (!err)
    return;
  base::ScopedCFTypeRef<CFStringRef> cfstr(
      SecCopyErrorMessageString(err, NULL));
  LOG(ERROR) << fn_name << " returned " << err
             << " (" << base::SysCFStringRefToUTF8(cfstr) << ")";
}

ScopedCSSMData::ScopedCSSMData() {
  memset(&data_, 0, sizeof(data_));
}

ScopedCSSMData::~ScopedCSSMData() {
  if (data_.Data) {
    CSSMFree(data_.Data);
    data_.Data = NULL;
  }
}

}  // namespace crypto

#pragma clang diagnostic pop  // "-Wdeprecated-declarations"
