1/* 2 * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19// 20// AppleCSPUtils.cpp - CSP-wide utility functions 21// 22 23#include "AppleCSPUtils.h" 24#include <Security/cssmerr.h> 25#include <security_utilities/alloc.h> 26#include <security_cdsa_utilities/cssmdates.h> 27#include <string.h> 28#include <FEECSPUtils.h> 29#include <SHA1_MD5_Object.h> 30#include "RSA_DSA_keys.h" 31#include <syslog.h> 32 33/* 34 * Validate key attribute bits per specified key type. 35 * 36 * Used to check requested key attributes for new keys and for validating 37 * incoming existing keys. For checking key attributes for new keys, 38 * assumes that KEYATTR_RETURN_xxx bits have been checked elsewhere 39 * and stripped off before coming here. 40 */ 41void cspValidateKeyAttr( 42 cspKeyType keyType, 43 uint32 keyAttr) 44{ 45 uint32 sensitiveBit = (keyAttr & CSSM_KEYATTR_SENSITIVE) ? 1 : 0; 46 uint32 extractBit = (keyAttr & CSSM_KEYATTR_EXTRACTABLE) ? 1 : 0; 47 48 /* first general CSP-wide checks */ 49 if(keyAttr & KEY_ATTR_RETURN_MASK) { 50 //errorLog0(" KEY_ATTR_RETURN bits set\n"); 51 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 52 } 53 if(keyAttr & CSSM_KEYATTR_PERMANENT) { 54 //errorLog0(" PERMANENT bit not supported\n"); 55 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK); 56 } 57 if(keyAttr & CSSM_KEYATTR_PRIVATE) { 58 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK); 59 } 60 /* Anything else? */ 61 62 /* now check per keyType */ 63 switch(keyType) { 64 case CKT_Session: 65 break; 66 67 case CKT_Public: 68 if(sensitiveBit || !extractBit) { 69 //errorLog0("Public keys must be extractable in the clear\n"); 70 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 71 } 72 break; 73 74 case CKT_Private: 75 //if(!sensitiveBit) { 76 // errorLog0("Private keys must have KEYATTR_SENSITIVE\n"); 77 // CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 78 //} 79 80 /* 81 * One more restriction - EXTRACTABLE - caller must check since 82 * that involves KEYUSE bits. 83 */ 84 break; 85 default: 86 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); 87 } 88 return; 89} 90 91/* 92 * Perform sanity check of incoming key attribute bits for a given 93 * key type, and return a cspKeyStorage value. 94 * 95 * Called from any routine which generates a new key. This specifically 96 * excludes WrapKey(). 97 */ 98cspKeyStorage cspParseKeyAttr( 99 cspKeyType keyType, 100 uint32 keyAttr) 101{ 102 uint32 sensitiveBit = (keyAttr & CSSM_KEYATTR_SENSITIVE) ? 1 : 0; 103 uint32 rtnDataBit = (keyAttr & CSSM_KEYATTR_RETURN_DATA) ? 1 : 0; 104 uint32 rtnRefBit = (keyAttr & CSSM_KEYATTR_RETURN_REF) ? 1 : 0; 105 uint32 extractBit = (keyAttr & CSSM_KEYATTR_EXTRACTABLE) ? 1 : 0; 106 107 cspKeyStorage rtn; 108 109 /* first general CDSA-wide checks */ 110 if(keyAttr & (CSSM_KEYATTR_ALWAYS_SENSITIVE | 111 CSSM_KEYATTR_NEVER_EXTRACTABLE)) { 112 //errorLog0("ALWAYS_SENSITIVE, NEVER_EXTRACTABLE illegal at SPI\n"); 113 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 114 } 115 switch(keyAttr & KEY_ATTR_RETURN_MASK) { 116 /* ensure only one bit is set */ 117 case CSSM_KEYATTR_RETURN_DATA: 118 rtn = CKS_Data; 119 break; 120 case CSSM_KEYATTR_RETURN_REF: 121 rtn = CKS_Ref; 122 break; 123 case CSSM_KEYATTR_RETURN_NONE: 124 rtn = CKS_None; 125 break; 126 case CSSM_KEYATTR_RETURN_DEFAULT: 127 /* CSP default */ 128 rtnRefBit = 1; 129 rtn = CKS_Ref; 130 break; 131 default: 132 //errorLog0("Multiple KEYATTR_RETURN bits set\n"); 133 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 134 } 135 136 /* now CSP-wide checks for all key types */ 137 if(keyType != CKT_Session) { 138 /* session keys modifiable, no others are */ 139 if(keyAttr & CSSM_KEYATTR_MODIFIABLE) { 140 //errorLog0("CSSM_KEYATTR_MODIFIABLE not supported\n"); 141 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 142 } 143 } 144 if(rtnDataBit) { 145 if(!extractBit) { 146 //errorLog0("RETURN_DATA and !EXTRACTABLE not supported\n"); 147 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 148 } 149 if(sensitiveBit) { 150 //errorLog0("RETURN_DATA and SENSITIVE not supported\n"); 151 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); 152 } 153 } 154 155 /* now check per keyType. We're ust checking for things specific 156 * to KEYATTR_RETURN_xxx; cspValidateKeyAttr will check other fields. */ 157 #if 0 158 // nothing for now 159 switch(keyType) { 160 case CKT_Session: 161 break; 162 163 case MKT_Public: 164 break; 165 166 case MKT_Private: 167 if(rtnDataBit) { 168 errorLog0("Private keys must be generated by ref\n"); 169 goto errorOut; 170 } 171 /* 172 * One more restriction - EXTRACTABLE - caller must check since 173 * that involves KEYUSE bits. 174 */ 175 break; 176 default: 177 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); 178 } 179 #endif // 0 180 181 /* validate other common static attributes */ 182 cspValidateKeyAttr(keyType, (keyAttr & ~KEY_ATTR_RETURN_MASK)); 183 return rtn; 184} 185 186 187/* used in cspValidateKeyUsageBits() */ 188/* 189 * This is a vestige from OS9/ASA. In the real world there are in fact certs with 190 * keyUsage extensions which specify, e.g., verify and wrap. I think we'll just 191 * have to ignore the old exclusivity rules. 192 */ 193#define IGNORE_KEYUSE_EXCLUSIVITY 1 194#if IGNORE_KEYUSE_EXCLUSIVITY 195#define checkExclusiveUsage(ku, cb, ob, em) 196#else 197static void checkExclusiveUsage( 198 uint32 keyUsage, // requested usage word 199 uint32 checkBits, // if any of these are set 200 uint32 otherBits, // these are the only other bits which can be set 201 const char *errMsg) 202{ 203 if(keyUsage & checkBits) { 204 if(keyUsage & ~otherBits) { 205 errorLog0((char *)errMsg); 206 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 207 } 208 } 209} 210#endif /* IGNORE_KEYUSE_EXCLUSIVITY */ 211 212/* 213 * Validate key usage bits for specified key type. 214 */ 215void cspValidateKeyUsageBits ( 216 cspKeyType keyType, 217 uint32 keyUsage) 218{ 219 /* general restrictions */ 220 checkExclusiveUsage(keyUsage, 221 CSSM_KEYUSE_ANY, 222 CSSM_KEYUSE_ANY, 223 "CSSM_KEYUSE_ANY overload"); 224 checkExclusiveUsage(keyUsage, 225 CSSM_KEYUSE_DERIVE, 226 CSSM_KEYUSE_DERIVE, 227 "CSSM_KEYUSE_DERIVE overload\n"); 228 229 /* brute force per key type. */ 230 switch(keyType) { 231 case CKT_Session: 232 checkExclusiveUsage(keyUsage, 233 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, 234 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, 235 "session key usage: encrypt/decrypt overload\n"); 236 checkExclusiveUsage(keyUsage, 237 CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY | 238 CSSM_KEYUSE_SIGN_RECOVER | CSSM_KEYUSE_VERIFY_RECOVER, 239 CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY | 240 CSSM_KEYUSE_SIGN_RECOVER | CSSM_KEYUSE_VERIFY_RECOVER, 241 "session key usage: sign/verify overload\n"); 242 checkExclusiveUsage(keyUsage, 243 CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, 244 CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP, 245 "session key usage: wrap/unwrap overload\n"); 246 break; 247 248 case CKT_Public: 249 checkExclusiveUsage(keyUsage, 250 CSSM_KEYUSE_ENCRYPT, 251 CSSM_KEYUSE_ENCRYPT, 252 "public key usage: encrypt overload\n"); 253 if(keyUsage & CSSM_KEYUSE_DECRYPT) { 254 errorLog0("public key usage: DECRYPT illegal\n"); 255 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 256 } 257 if(keyUsage & (CSSM_KEYUSE_SIGN | CSSM_KEYUSE_SIGN_RECOVER)) { 258 errorLog0("public key usage: SIGN illegal\n"); 259 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 260 } 261 checkExclusiveUsage(keyUsage, 262 CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_VERIFY_RECOVER, 263 CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_VERIFY_RECOVER, 264 "public key usage: verify overload\n"); 265 checkExclusiveUsage(keyUsage, 266 CSSM_KEYUSE_WRAP, 267 CSSM_KEYUSE_WRAP, 268 "public key usage: wrap overload\n"); 269 if(keyUsage & CSSM_KEYUSE_UNWRAP) { 270 errorLog0("public key usage: UNWRAP illegal\n"); 271 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 272 } 273 break; 274 275 case CKT_Private: 276 if(keyUsage & CSSM_KEYUSE_ENCRYPT) { 277 errorLog0("private key usage: ENCRYPT illegal\n"); 278 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 279 } 280 checkExclusiveUsage(keyUsage, 281 CSSM_KEYUSE_DECRYPT, 282 CSSM_KEYUSE_DECRYPT, 283 "private key usage: decrypt overload\n"); 284 checkExclusiveUsage(keyUsage, 285 CSSM_KEYUSE_SIGN | CSSM_KEYUSE_SIGN_RECOVER, 286 CSSM_KEYUSE_SIGN | CSSM_KEYUSE_SIGN_RECOVER, 287 "private key usage: sign overload\n"); 288 if(keyUsage & (CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_VERIFY_RECOVER)) { 289 errorLog0("private key usage: VERIFY illegal\n"); 290 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 291 } 292 if(keyUsage & CSSM_KEYUSE_WRAP) { 293 errorLog0("private key usage: WRAP illegal\n"); 294 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK); 295 } 296 checkExclusiveUsage(keyUsage, 297 CSSM_KEYUSE_UNWRAP, 298 CSSM_KEYUSE_UNWRAP, 299 "private key usage: unwrap overload\n"); 300 break; 301 default: 302 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); 303 } 304} 305 306/* 307 * Validate existing key's usage bits against intended use. 308 */ 309 310/* 311 * For now, a key marked for KEYUSE_{WRAP|UNWRAP} can also be used for 312 * KEYUSE_{ENCRYPT|DECRYPT}. This is a temporary workaround for 313 * Radar 2716153. 314 */ 315#define RELAXED_WRAP_USAGE 1 316 317void cspValidateIntendedKeyUsage( 318 const CSSM_KEYHEADER *hdr, 319 CSSM_KEYUSE intendedUsage) 320{ 321 uint32 keyUsage = hdr->KeyUsage; 322 cspKeyType keyType; 323 324 /* first, the obvious */ 325 if(keyUsage & CSSM_KEYUSE_ANY) { 326 /* OK for now */ 327 return; 328 } 329 if(!(keyUsage & intendedUsage)) { 330 #if RELAXED_WRAP_USAGE 331 if(! ( ( (keyUsage & CSSM_KEYUSE_WRAP) && 332 (intendedUsage == CSSM_KEYUSE_ENCRYPT) 333 ) || 334 ( (keyUsage & CSSM_KEYUSE_UNWRAP) && 335 (intendedUsage == CSSM_KEYUSE_DECRYPT) 336 ) 337 ) ) 338 #endif 339 CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT); 340 } 341 342 /* now validate all of the key's usage bits - this is mainly to 343 * prevent and detect tampering */ 344 switch(hdr->KeyClass) { 345 case CSSM_KEYCLASS_SESSION_KEY: 346 keyType = CKT_Session; 347 break; 348 case CSSM_KEYCLASS_PUBLIC_KEY: 349 keyType = CKT_Public; 350 break; 351 case CSSM_KEYCLASS_PRIVATE_KEY: 352 keyType = CKT_Private; 353 break; 354 default: 355 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); 356 } 357 try { 358 cspValidateKeyUsageBits(keyType, keyUsage); 359 } 360 catch (...) { 361 /* override error.... */ 362 CssmError::throwMe(CSSMERR_CSP_KEY_USAGE_INCORRECT); 363 } 364} 365 366/* 367 * Set up a key header. 368 */ 369void setKeyHeader( 370 CSSM_KEYHEADER &hdr, 371 const Guid &myGuid, 372 CSSM_ALGORITHMS alg, 373 CSSM_KEYCLASS keyClass, 374 CSSM_KEYATTR_FLAGS attrs, 375 CSSM_KEYUSE use) 376{ 377 memset(&hdr, 0, sizeof(CSSM_KEYHEADER)); 378 hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; 379 hdr.CspId = myGuid; 380 hdr.AlgorithmId = alg; 381 hdr.KeyClass = keyClass; 382 hdr.KeyUsage = use; 383 hdr.KeyAttr = attrs; 384 385 // defaults (change as needed) 386 hdr.WrapAlgorithmId = CSSM_ALGID_NONE; 387} 388 389/* 390 * Ensure that indicated CssmData can handle 'length' bytes 391 * of data. Malloc the Data ptr if necessary. 392 */ 393void setUpCssmData( 394 CssmData &data, 395 size_t length, 396 Allocator &allocator) 397{ 398 /* FIXME - I'm sure Perry has more elegant ways of doing this, 399 * but I can't figure them out. */ 400 if(data.Length == 0) { 401 data.Data = (uint8 *)allocator.malloc(length); 402 } 403 else if(data.Length < length) { 404 CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); 405 } 406 data.Length = length; 407} 408 409void setUpData( 410 CSSM_DATA &data, 411 size_t length, 412 Allocator &allocator) 413{ 414 setUpCssmData(CssmData::overlay(data), length, allocator); 415} 416 417void freeCssmData( 418 CssmData &data, 419 Allocator &allocator) 420{ 421 if(data.Data) { 422 allocator.free(data.Data); 423 data.Data = NULL; 424 } 425 data.Length = 0; 426} 427 428void freeData( 429 CSSM_DATA *data, 430 Allocator &allocator, 431 bool freeStruct) // free the CSSM_DATA itself 432{ 433 if(data == NULL) { 434 return; 435 } 436 if(data->Data) { 437 allocator.free(data->Data); 438 data->Data = NULL; 439 } 440 data->Length = 0; 441 if(freeStruct) { 442 allocator.free(data); 443 } 444} 445 446/* 447 * Copy source to destination, mallocing destination if necessary. 448 */ 449void copyCssmData( 450 const CssmData &src, 451 CssmData &dst, 452 Allocator &allocator) 453{ 454 setUpCssmData(dst, src.Length, allocator); 455 memmove(dst.Data, src.Data, src.Length); 456} 457 458void copyData( 459 const CSSM_DATA &src, 460 CSSM_DATA &dst, 461 Allocator &allocator) 462{ 463 copyCssmData(CssmData::overlay(src), 464 CssmData::overlay(dst), 465 allocator); 466} 467 468/* 469 * Compare two CSSM_DATAs, return CSSM_TRUE if identical. 470 */ 471CSSM_BOOL cspCompareCssmData( 472 const CSSM_DATA *data1, 473 const CSSM_DATA *data2) 474{ 475 if((data1 == NULL) || (data1->Data == NULL) || 476 (data2 == NULL) || (data2->Data == NULL) || 477 (data1->Length != data2->Length)) { 478 return CSSM_FALSE; 479 } 480 if(data1->Length != data2->Length) { 481 return CSSM_FALSE; 482 } 483 if(memcmp(data1->Data, data2->Data, data1->Length) == 0) { 484 return CSSM_TRUE; 485 } 486 else { 487 return CSSM_FALSE; 488 } 489} 490 491/* 492 * This takes care of mallocing the KeyLabel field. 493 */ 494void copyCssmHeader( 495 const CssmKey::Header &src, 496 CssmKey::Header &dst, 497 Allocator &allocator) 498{ 499 dst = src; 500} 501 502/* 503 * Given a wrapped key, infer its raw format for custom Apple unwrapping. 504 * This is a real kludge; it only works as long as each the key's 505 * default format is used to generate the blob to be wrapped. 506 */ 507CSSM_KEYBLOB_FORMAT inferFormat( 508 const CssmKey &wrappedKey) 509{ 510 switch(wrappedKey.keyClass()) { 511 case CSSM_KEYCLASS_SESSION_KEY: 512 return CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; 513 case CSSM_KEYCLASS_PUBLIC_KEY: 514 switch(wrappedKey.algorithm()) { 515 case CSSM_ALGID_RSA: 516 return RSA_PUB_KEY_FORMAT; 517 case CSSM_ALGID_DSA: 518 return DSA_PUB_KEY_FORMAT; 519 #ifdef CRYPTKIT_CSP_ENABLE 520 case CSSM_ALGID_FEE: 521 return FEE_KEYBLOB_DEFAULT_FORMAT; 522 case CSSM_ALGID_ECDSA: 523 return CSSM_KEYBLOB_RAW_FORMAT_X509; 524 #endif 525 case CSSM_ALGID_DH: 526 return CSSM_KEYBLOB_RAW_FORMAT_PKCS3; 527 default: 528 /* punt */ 529 return CSSM_KEYBLOB_RAW_FORMAT_NONE; 530 } 531 case CSSM_KEYCLASS_PRIVATE_KEY: 532 switch(wrappedKey.algorithm()) { 533 case CSSM_ALGID_RSA: 534 return RSA_PRIV_KEY_FORMAT; 535 case CSSM_ALGID_DSA: 536 return DSA_PRIV_KEY_FORMAT; 537 #ifdef CRYPTKIT_CSP_ENABLE 538 case CSSM_ALGID_FEE: 539 return FEE_KEYBLOB_DEFAULT_FORMAT; 540 case CSSM_ALGID_ECDSA: 541 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; 542 #endif 543 case CSSM_ALGID_DH: 544 return CSSM_KEYBLOB_RAW_FORMAT_PKCS3; 545 default: 546 /* punt */ 547 return CSSM_KEYBLOB_RAW_FORMAT_NONE; 548 } 549 default: 550 /* punt */ 551 return CSSM_KEYBLOB_RAW_FORMAT_NONE; 552 } 553} 554 555/* 556 * Given a key and a Context, obtain the optional associated 557 * CSSM_ATTRIBUTE_{PUBLIC,PRIVATE,SYMMETRIC}_KEY_FORMAT attribute as a 558 * CSSM_KEYBLOB_FORMAT. 559 */ 560CSSM_KEYBLOB_FORMAT requestedKeyFormat( 561 const Context &context, 562 const CssmKey &key) 563{ 564 CSSM_ATTRIBUTE_TYPE attrType; 565 566 switch(key.keyClass()) { 567 case CSSM_KEYCLASS_SESSION_KEY: 568 attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT; 569 break; 570 case CSSM_KEYCLASS_PUBLIC_KEY: 571 attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT; 572 break; 573 case CSSM_KEYCLASS_PRIVATE_KEY: 574 attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT; 575 break; 576 default: 577 return CSSM_KEYBLOB_RAW_FORMAT_NONE; 578 } 579 /* not present ==> 0 ==> CSSM_KEYBLOB_RAW_FORMAT_NONE */ 580 return context.getInt(attrType); 581} 582 583/* one-shot SHA1 digest */ 584void cspGenSha1Hash( 585 const void *inData, 586 size_t inDataLen, 587 void *out) // caller mallocs, digest goes here 588{ 589 SHA1Object sha1; 590 591 sha1.digestInit(); 592 sha1.digestUpdate(inData, inDataLen); 593 sha1.digestFinal(out); 594} 595 596/* 597 * Convert a CSSM_DATE to a CssmUniformDate, or NULL if the CSSM_DATE 598 * is empty. 599 */ 600static CssmUniformDate *cspGetUniformDate( 601 const CSSM_DATE &cdate) 602{ 603 bool isZero = true; 604 unsigned char *cp = (unsigned char *)&cdate; 605 for(unsigned i=0; i<sizeof(cdate); i++) { 606 if(*cp++ != 0) { 607 isZero = false; 608 break; 609 } 610 } 611 if(isZero) { 612 return NULL; 613 } 614 else { 615 return new CssmUniformDate(CssmDate::overlay(cdate)); 616 } 617} 618 619/* 620 * Get "now" as a CssmUniformDate. 621 */ 622static CssmUniformDate *cspNow() 623{ 624 CFAbsoluteTime cfTime = CFAbsoluteTimeGetCurrent(); 625 return new CssmUniformDate(cfTime); 626} 627 628#define keyDateDebug(args...) secdebug("keyDate", ## args) 629 630/* 631 * Verify temporal validity of specified key. 632 * An empty (all zero) time field means "ignore this". 633 * Throws CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE or 634 * CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE as appropriate. 635 */ 636void cspVerifyKeyTimes( 637 const CSSM_KEYHEADER &hdr) 638{ 639 CSSM_RETURN err = CSSM_OK; 640 CssmUniformDate *now = NULL; // evaluate lazily 641 CssmUniformDate *end = NULL; // ditto 642 CssmUniformDate *start = cspGetUniformDate(hdr.StartDate); 643 644 if(start) { 645 now = cspNow(); 646 if(*now < *start) { 647 keyDateDebug("Invalid start date"); 648 err = CSSMERR_CSP_APPLE_INVALID_KEY_START_DATE; 649 } 650 else { 651 keyDateDebug("Valid start date"); 652 } 653 } 654 else { 655 keyDateDebug("Empty start date"); 656 } 657 658 if(!err) { 659 end = cspGetUniformDate(hdr.EndDate); 660 if(end) { 661 if(now == NULL) { 662 now = cspNow(); 663 } 664 if(*now > *end) { 665 keyDateDebug("Invalid end date"); 666 err = CSSMERR_CSP_APPLE_INVALID_KEY_END_DATE; 667 } 668 else { 669 keyDateDebug("Valid end date"); 670 } 671 } 672 else { 673 keyDateDebug("Empty end date"); 674 } 675 } 676 if(now) { 677 delete now; 678 } 679 if(end) { 680 delete end; 681 } 682 if(start) { 683 delete start; 684 } 685 if(err) { 686 CssmError::throwMe(err); 687 } 688} 689 690