Home | History | Annotate | Download | only in crypto
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "crypto/cssm_init.h"
      6 
      7 #include <Security/SecBase.h>
      8 
      9 #include "base/logging.h"
     10 #include "base/mac/scoped_cftyperef.h"
     11 #include "base/memory/singleton.h"
     12 #include "base/strings/sys_string_conversions.h"
     13 
     14 // When writing crypto code for Mac OS X, you may find the following
     15 // documentation useful:
     16 // - Common Security: CDSA and CSSM, Version 2 (with corrigenda)
     17 //   http://www.opengroup.org/security/cdsa.htm
     18 // - Apple Cryptographic Service Provider Functional Specification
     19 // - CryptoSample: http://developer.apple.com/SampleCode/CryptoSample/
     20 
     21 namespace {
     22 
     23 void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) {
     24   return malloc(size);
     25 }
     26 
     27 void CSSMFree(void* mem_ptr, void* alloc_ref) {
     28   free(mem_ptr);
     29 }
     30 
     31 void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) {
     32   return realloc(ptr, size);
     33 }
     34 
     35 void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) {
     36   return calloc(num, size);
     37 }
     38 
     39 class CSSMInitSingleton {
     40  public:
     41   static CSSMInitSingleton* GetInstance() {
     42     return Singleton<CSSMInitSingleton,
     43                      LeakySingletonTraits<CSSMInitSingleton> >::get();
     44   }
     45 
     46   CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; }
     47   CSSM_CL_HANDLE cl_handle() const { return cl_handle_; }
     48   CSSM_TP_HANDLE tp_handle() const { return tp_handle_; }
     49 
     50  private:
     51   CSSMInitSingleton()
     52       : inited_(false), csp_loaded_(false), cl_loaded_(false),
     53         tp_loaded_(false), csp_handle_(CSSM_INVALID_HANDLE),
     54         cl_handle_(CSSM_INVALID_HANDLE), tp_handle_(CSSM_INVALID_HANDLE) {
     55     static CSSM_VERSION version = {2, 0};
     56     // TODO(wtc): what should our caller GUID be?
     57     static const CSSM_GUID test_guid = {
     58       0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 }
     59     };
     60     CSSM_RETURN crtn;
     61     CSSM_PVC_MODE pvc_policy = CSSM_PVC_NONE;
     62     crtn = CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &test_guid,
     63                      CSSM_KEY_HIERARCHY_NONE, &pvc_policy, NULL);
     64     if (crtn) {
     65       NOTREACHED();
     66       return;
     67     }
     68     inited_ = true;
     69 
     70     crtn = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
     71     if (crtn) {
     72       NOTREACHED();
     73       return;
     74     }
     75     csp_loaded_ = true;
     76     crtn = CSSM_ModuleLoad(
     77         &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
     78     if (crtn) {
     79       NOTREACHED();
     80       return;
     81     }
     82     cl_loaded_ = true;
     83     crtn = CSSM_ModuleLoad(
     84         &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
     85     if (crtn) {
     86       NOTREACHED();
     87       return;
     88     }
     89     tp_loaded_ = true;
     90 
     91     const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = {
     92       CSSMMalloc,
     93       CSSMFree,
     94       CSSMRealloc,
     95       CSSMCalloc,
     96       NULL
     97     };
     98 
     99     crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0,
    100                              CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE,
    101                              NULL, 0, NULL, &csp_handle_);
    102     DCHECK_EQ(CSSM_OK, crtn);
    103     crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions,
    104                              0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE,
    105                              NULL, 0, NULL, &cl_handle_);
    106     DCHECK_EQ(CSSM_OK, crtn);
    107     crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions,
    108                              0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE,
    109                              NULL, 0, NULL, &tp_handle_);
    110     DCHECK_EQ(CSSM_OK, crtn);
    111   }
    112 
    113   ~CSSMInitSingleton() {
    114     CSSM_RETURN crtn;
    115     if (csp_handle_) {
    116       CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_);
    117       DCHECK_EQ(CSSM_OK, crtn);
    118     }
    119     if (cl_handle_) {
    120       CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_);
    121       DCHECK_EQ(CSSM_OK, crtn);
    122     }
    123     if (tp_handle_) {
    124       CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_);
    125       DCHECK_EQ(CSSM_OK, crtn);
    126     }
    127     if (csp_loaded_) {
    128       crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL);
    129       DCHECK_EQ(CSSM_OK, crtn);
    130     }
    131     if (cl_loaded_) {
    132       crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL);
    133       DCHECK_EQ(CSSM_OK, crtn);
    134     }
    135     if (tp_loaded_) {
    136       crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL);
    137       DCHECK_EQ(CSSM_OK, crtn);
    138     }
    139     if (inited_) {
    140       crtn = CSSM_Terminate();
    141       DCHECK_EQ(CSSM_OK, crtn);
    142     }
    143   }
    144 
    145   bool inited_;  // True if CSSM_Init has been called successfully.
    146   bool csp_loaded_;  // True if gGuidAppleCSP has been loaded
    147   bool cl_loaded_;  // True if gGuidAppleX509CL has been loaded.
    148   bool tp_loaded_;  // True if gGuidAppleX509TP has been loaded.
    149   CSSM_CSP_HANDLE csp_handle_;
    150   CSSM_CL_HANDLE cl_handle_;
    151   CSSM_TP_HANDLE tp_handle_;
    152 
    153   friend struct DefaultSingletonTraits<CSSMInitSingleton>;
    154 };
    155 
    156 }  // namespace
    157 
    158 namespace crypto {
    159 
    160 void EnsureCSSMInit() {
    161   CSSMInitSingleton::GetInstance();
    162 }
    163 
    164 CSSM_CSP_HANDLE GetSharedCSPHandle() {
    165   return CSSMInitSingleton::GetInstance()->csp_handle();
    166 }
    167 
    168 CSSM_CL_HANDLE GetSharedCLHandle() {
    169   return CSSMInitSingleton::GetInstance()->cl_handle();
    170 }
    171 
    172 CSSM_TP_HANDLE GetSharedTPHandle() {
    173   return CSSMInitSingleton::GetInstance()->tp_handle();
    174 }
    175 
    176 void* CSSMMalloc(CSSM_SIZE size) {
    177   return ::CSSMMalloc(size, NULL);
    178 }
    179 
    180 void CSSMFree(void* ptr) {
    181   ::CSSMFree(ptr, NULL);
    182 }
    183 
    184 void LogCSSMError(const char* fn_name, CSSM_RETURN err) {
    185   if (!err)
    186     return;
    187   base::ScopedCFTypeRef<CFStringRef> cfstr(
    188       SecCopyErrorMessageString(err, NULL));
    189   LOG(ERROR) << fn_name << " returned " << err
    190              << " (" << base::SysCFStringRefToUTF8(cfstr) << ")";
    191 }
    192 
    193 ScopedCSSMData::ScopedCSSMData() {
    194   memset(&data_, 0, sizeof(data_));
    195 }
    196 
    197 ScopedCSSMData::~ScopedCSSMData() {
    198   if (data_.Data) {
    199     CSSMFree(data_.Data);
    200     data_.Data = NULL;
    201   }
    202 }
    203 
    204 }  // namespace crypto
    205