1 // Copyright (c) 2011 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/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_(NULL), cl_handle_(NULL), 54 tp_handle_(NULL) { 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(crtn == CSSM_OK); 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(crtn == CSSM_OK); 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(crtn == CSSM_OK); 111 } 112 113 ~CSSMInitSingleton() { 114 CSSM_RETURN crtn; 115 if (csp_handle_) { 116 CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_); 117 DCHECK(crtn == CSSM_OK); 118 } 119 if (cl_handle_) { 120 CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_); 121 DCHECK(crtn == CSSM_OK); 122 } 123 if (tp_handle_) { 124 CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_); 125 DCHECK(crtn == CSSM_OK); 126 } 127 if (csp_loaded_) { 128 crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL); 129 DCHECK(crtn == CSSM_OK); 130 } 131 if (cl_loaded_) { 132 crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); 133 DCHECK(crtn == CSSM_OK); 134 } 135 if (tp_loaded_) { 136 crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); 137 DCHECK(crtn == CSSM_OK); 138 } 139 if (inited_) { 140 crtn = CSSM_Terminate(); 141 DCHECK(crtn == CSSM_OK); 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::mac::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