1/* 2 * Copyright (c) 2003-2004,2011-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * pkcs12Coder.cpp - Public P12Coder coder functions. 26 */ 27 28#include "pkcs12Coder.h" 29#include "pkcs12Debug.h" 30#include "pkcs12Utils.h" 31#include <Security/cssmerr.h> 32#include <security_cdsa_utils/cuCdsaUtils.h> 33#include <Security/oidsalg.h> 34#include <Security/SecBase.h> 35/* 36 * Default encryption parameters 37 */ 38#define P12_ENCR_ITER_COUNT 2048 39#define P12_MAC_ITER_COUNT 1 40#define P12_WEAK_ENCR_ALG CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC 41#define P12_STRONG_ENCR_ALG CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC 42 43/* 44 * Default import flags. 45 */ 46#define P12_KC_IMPORT_DEFAULT (kSecImportCertificates | \ 47 kSecImportCRLs | \ 48 kSecImportKeys) 49 50P12Coder::P12Coder() 51{ 52 init(); 53} 54 55/* one-time init from all constructors */ 56void P12Coder::init() 57{ 58 mPrivacyMode = kSecPkcs12ModePassword; 59 mIntegrityMode = kSecPkcs12ModePassword; 60 mMacPassphrase = NULL; 61 mEncrPassPhrase = NULL; 62 mMacPassData.Data = NULL; 63 mMacPassData.Length = 0; 64 mEncrPassData.Data = NULL; 65 mEncrPassData.Length = 0; 66 mMacPassKey = NULL; 67 mEncrPassKey = NULL; 68 mKeychain = NULL; 69 mCspHand = 0; 70 mDlDbHand.DLHandle = 0; 71 mDlDbHand.DBHandle = 0; 72 mPrivKeyImportState = PKIS_NoLimit; 73 mWeakEncrAlg = P12_WEAK_ENCR_ALG; 74 mStrongEncrAlg = P12_STRONG_ENCR_ALG; 75 mWeakEncrIterCount = P12_ENCR_ITER_COUNT; 76 mStrongEncrIterCount = P12_ENCR_ITER_COUNT; 77 mMacIterCount = P12_MAC_ITER_COUNT; 78 mImportFlags = P12_KC_IMPORT_DEFAULT; 79 mRawCspHand = 0; 80 mClHand = 0; 81 mAccess = NULL; 82 mNoAcl = false; 83 mKeyUsage = CSSM_KEYUSE_ANY; /* default */ 84 /* default key attrs; we add CSSM_KEYATTR_PERMANENT if importing to 85 * a keychain */ 86 mKeyAttrs = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | 87 CSSM_KEYATTR_SENSITIVE; 88} 89 90/* 91 * FIXME - can't we get vector's destructor to do this? 92 */ 93#define deleteVect(v) \ 94{ \ 95 while(v.size()) { \ 96 delete v[0]; \ 97 v.erase(v.begin()); \ 98 } \ 99 v.clear(); \ 100} 101 102P12Coder::~P12Coder() 103{ 104 if(mMacPassphrase) { 105 CFRelease(mMacPassphrase); 106 } 107 if(mEncrPassPhrase) { 108 CFRelease(mEncrPassPhrase); 109 } 110 if(mAccess) { 111 CFRelease(mAccess); 112 } 113 deleteVect(mCerts); 114 deleteVect(mCrls); 115 deleteVect(mKeys); 116 deleteVect(mOpaques); 117 118 if(mKeychain) { 119 CFRelease(mKeychain); 120 } 121 if(mRawCspHand) { 122 cuCspDetachUnload(mRawCspHand, CSSM_TRUE); 123 } 124 if(mClHand) { 125 cuClDetachUnload(mClHand); 126 } 127} 128 129void P12Coder::setKeychain( 130 SecKeychainRef keychain) 131{ 132 OSStatus ortn = SecKeychainGetCSPHandle(keychain, &mCspHand); 133 if(ortn) { 134 MacOSError::throwMe(ortn); 135 } 136 ortn = SecKeychainGetDLDBHandle(keychain, &mDlDbHand); 137 if(ortn) { 138 MacOSError::throwMe(ortn); 139 } 140 CFRetain(keychain); 141 mKeychain = keychain; 142} 143 144void P12Coder::setAccess( 145 SecAccessRef access) 146{ 147 if(mAccess) { 148 CFRelease(mAccess); 149 } 150 mAccess = access; 151 if(mAccess) { 152 CFRetain(mAccess); 153 } 154 else { 155 /* NULL ==> no ACL */ 156 mNoAcl = true; 157 } 158} 159 160#define SEC_KEYATTR_RETURN_MASK \ 161 (CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_RETURN_NONE) 162 163void P12Coder::setKeyAttrs( 164 CSSM_KEYATTR_FLAGS keyAttrs) 165{ 166 /* ensure we're generating a ref key no matter what caller asks for */ 167 mKeyAttrs = keyAttrs; 168 mKeyAttrs &= ~SEC_KEYATTR_RETURN_MASK; 169 mKeyAttrs |= CSSM_KEYATTR_RETURN_REF; 170} 171 172/* 173 * Private methods for obtaining passprases in CSSM_DATA form. 174 */ 175const CSSM_DATA *P12Coder::getMacPassPhrase() 176{ 177 if(mMacPassData.Data != NULL) { 178 return &mMacPassData; 179 } 180 else if (mMacPassphrase) { 181 p12ImportPassPhrase(mMacPassphrase, mCoder, mMacPassData); 182 return &mMacPassData; 183 } 184 else { 185 return NULL; 186 } 187} 188 189const CSSM_DATA *P12Coder::getEncrPassPhrase() 190{ 191 if(mEncrPassData.Data != NULL) { 192 return &mEncrPassData; 193 } 194 else if (mEncrPassPhrase) { 195 p12ImportPassPhrase(mEncrPassPhrase, mCoder, mEncrPassData); 196 return &mEncrPassData; 197 } 198 /* no separate passphrase found, use MAC passphrase */ 199 return getMacPassPhrase(); 200} 201 202/* 203 * These return a CSSM_KEY_PTR is the app had specified 204 * PassKeys, else they return NULL. 205 */ 206const CSSM_KEY *P12Coder::getMacPassKey() 207{ 208 return mMacPassKey; 209} 210 211const CSSM_KEY *P12Coder::getEncrPassKey() 212{ 213 if(mEncrPassKey != NULL) { 214 return mEncrPassKey; 215 } 216 else { 217 return getMacPassKey(); 218 } 219} 220 221/* 222 * Lazy evaluation of module handles. 223 */ 224CSSM_CSP_HANDLE P12Coder::rawCspHand() 225{ 226 if(mRawCspHand != 0) { 227 return mRawCspHand; 228 } 229 mRawCspHand = cuCspStartup(CSSM_TRUE); 230 if(mRawCspHand == 0) { 231 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 232 } 233 return mRawCspHand; 234} 235 236CSSM_CL_HANDLE P12Coder::clHand() 237{ 238 if(mClHand != 0) { 239 return mClHand; 240 } 241 mClHand = cuClStartup(); 242 if(mClHand == 0) { 243 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 244 } 245 return mClHand; 246} 247 248/* 249 * These public functions more or less correspond to 250 * the public functions in SecPkcs12.h. 251 */ 252void P12Coder::setMacPassPhrase( 253 CFStringRef passphrase) 254{ 255 CFRetain(passphrase); 256 mMacPassphrase = passphrase; 257} 258 259void P12Coder::setEncrPassPhrase( 260 CFStringRef passphrase) 261{ 262 CFRetain(passphrase); 263 mEncrPassPhrase = passphrase; 264} 265 266void P12Coder::setMacPassKey( 267 const CSSM_KEY *passKey) 268{ 269 mMacPassKey = passKey; 270} 271 272void P12Coder::setEncrPassKey( 273 const CSSM_KEY *passKey) 274{ 275 mEncrPassKey = passKey; 276} 277 278/* getters */ 279unsigned P12Coder::numCerts() 280{ 281 return (unsigned)mCerts.size(); 282} 283 284unsigned P12Coder::numCrls() 285{ 286 return (unsigned)mCrls.size(); 287} 288 289unsigned P12Coder::numKeys() 290{ 291 return (unsigned)mKeys.size(); 292} 293 294unsigned P12Coder::numOpaqueBlobs() 295{ 296 return (unsigned)mOpaques.size(); 297} 298 299P12CertBag *P12Coder::getCert( 300 unsigned dex) 301{ 302 if(mCerts.size() < (dex + 1)) { 303 MacOSError::throwMe(errSecParam); 304 } 305 return mCerts[dex]; 306} 307 308P12CrlBag *P12Coder::getCrl( 309 unsigned dex) 310{ 311 if(mCrls.size() < (dex + 1)) { 312 MacOSError::throwMe(errSecParam); 313 } 314 return mCrls[dex]; 315} 316 317P12KeyBag *P12Coder::getKey( 318 unsigned dex) 319{ 320 if(mKeys.size() < (dex + 1)) { 321 MacOSError::throwMe(errSecParam); 322 } 323 return mKeys[dex]; 324} 325 326P12OpaqueBag *P12Coder::getOpaque( 327 unsigned dex) 328{ 329 if(mOpaques.size() < (dex + 1)) { 330 MacOSError::throwMe(errSecParam); 331 } 332 return mOpaques[dex]; 333} 334 335/* 336 * These four "add" functions are invoked by the app prior to encoding 337 * and by our decoder while decoding. 338 */ 339void P12Coder::addCert( 340 P12CertBag *cert) 341{ 342 mCerts.push_back(cert); 343} 344 345void P12Coder::addCrl( 346 P12CrlBag *crl) 347{ 348 mCrls.push_back(crl); 349} 350 351void P12Coder::addKey( 352 P12KeyBag *key) 353{ 354 mKeys.push_back(key); 355} 356 357void P12Coder::addOpaque( 358 P12OpaqueBag *opaque) 359{ 360 mOpaques.push_back(opaque); 361} 362 363 364/* little known, but public, functions */ 365void P12Coder::integrityMode( 366 SecPkcs12Mode mode) 367{ 368 if(mode != kSecPkcs12ModePassword) { 369 MacOSError::throwMe(errSecParam); 370 } 371 mIntegrityMode = mode; 372} 373 374void P12Coder::privacyMode( 375 SecPkcs12Mode mode) 376{ 377 if(mode != kSecPkcs12ModePassword) { 378 MacOSError::throwMe(errSecParam); 379 } 380 mPrivacyMode = mode; 381} 382 383CFDataRef P12Coder::weakEncrAlg() 384{ 385 return p12CssmDataToCf(mWeakEncrAlg); 386} 387 388CFDataRef P12Coder::strongEncrAlg() 389{ 390 return p12CssmDataToCf(mStrongEncrAlg); 391} 392 393void P12Coder::weakEncrAlg( 394 CFDataRef alg) 395{ 396 p12CfDataToCssm(alg, mWeakEncrAlg, mCoder); 397} 398 399void P12Coder::strongEncrAlg( 400 CFDataRef alg) 401{ 402 p12CfDataToCssm(alg, mStrongEncrAlg, mCoder); 403} 404 405void P12Coder::limitPrivKeyImport( 406 bool foundOneKey) 407{ 408 if(foundOneKey) { 409 mPrivKeyImportState = PKIS_NoMore; 410 } 411 else { 412 mPrivKeyImportState = PKIS_AllowOne; 413 } 414} 415