1/* 2 * Copyright (c) 2008-2013 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 * EAPSIMAKAUtil.c 26 * - common definitions/routines for EAP-SIM and EAP-AKA 27 */ 28 29#include "EAPSIMAKAUtil.h" 30#include <stddef.h> 31#include <stdlib.h> 32#include "EAPLog.h" 33#include "symbol_scope.h" 34#include "nbo.h" 35#include "printdata.h" 36#include "EAP.h" 37#include "EAPUtil.h" 38#include "fips186prf.h" 39#include "myCFUtil.h" 40#include <string.h> 41#include <CommonCrypto/CommonHMAC.h> 42 43/* 44 * Modification History 45 * 46 * October 8, 2012 Dieter Siegmund (dieter@apple) 47 * - created (from eapsim_plugin.c) 48 */ 49 50PRIVATE_EXTERN const char * 51EAPSIMAKAPacketSubtypeGetString(EAPSIMAKAPacketSubtype subtype) 52{ 53 static char buf[8]; 54 const char * ret; 55 56 switch (subtype) { 57 /* EAP-AKA only */ 58 case kEAPSIMAKAPacketSubtypeAKAChallenge: 59 ret = "Challenge"; 60 break; 61 case kEAPSIMAKAPacketSubtypeAKAAuthenticationReject: 62 ret = "Authentication Reject"; 63 break; 64 case kEAPSIMAKAPacketSubtypeAKASynchronizationFailure: 65 ret = "Synchronization Failure"; 66 break; 67 case kEAPSIMAKAPacketSubtypeAKAIdentity: 68 ret = "Identity"; 69 break; 70 71 /* EAP-SIM only */ 72 case kEAPSIMAKAPacketSubtypeSIMStart : 73 ret = "Start"; 74 break; 75 case kEAPSIMAKAPacketSubtypeSIMChallenge : 76 ret = "Challenge"; 77 break; 78 79 /* EAP-AKA and EAP-SIM */ 80 case kEAPSIMAKAPacketSubtypeNotification : 81 ret = "Notification"; 82 break; 83 case kEAPSIMAKAPacketSubtypeReauthentication : 84 ret = "Reauthentication"; 85 break; 86 case kEAPSIMAKAPacketSubtypeClientError : 87 ret = "Client Error"; 88 break; 89 default: 90 snprintf(buf, sizeof(buf), "%d", subtype); 91 ret = buf; 92 break; 93 } 94 return (ret); 95} 96 97PRIVATE_EXTERN const char * 98EAPSIMAKAAttributeTypeGetString(EAPSIMAKAAttributeType attr) 99{ 100 static char buf[8]; 101 102 switch (attr) { 103 case kAT_RAND: 104 return "AT_RAND"; 105 case kAT_AUTN: 106 return "AT_AUTN"; 107 case kAT_RES: 108 return "AT_RES"; 109 case kAT_AUTS: 110 return "AT_AUTS"; 111 case kAT_PADDING: 112 return "AT_PADDING"; 113 case kAT_NONCE_MT: 114 return "AT_NONCE_MT"; 115 case kAT_PERMANENT_ID_REQ: 116 return "AT_PERMANENT_ID_REQ"; 117 case kAT_MAC: 118 return "AT_MAC"; 119 case kAT_NOTIFICATION: 120 return "AT_NOTIFICATION"; 121 case kAT_ANY_ID_REQ: 122 return "AT_ANY_ID_REQ"; 123 case kAT_IDENTITY: 124 return "AT_IDENTITY"; 125 case kAT_VERSION_LIST: 126 return "AT_VERSION_LIST"; 127 case kAT_SELECTED_VERSION: 128 return "AT_SELECTED_VERSION"; 129 case kAT_FULLAUTH_ID_REQ: 130 return "AT_FULLAUTH_ID_REQ"; 131 case kAT_COUNTER: 132 return "AT_COUNTER"; 133 case kAT_COUNTER_TOO_SMALL: 134 return "AT_COUNTER_TOO_SMALL"; 135 case kAT_NONCE_S: 136 return "AT_NONCE_S"; 137 case kAT_CLIENT_ERROR_CODE: 138 return "AT_CLIENT_ERROR_CODE"; 139 case kAT_IV: 140 return "AT_IV"; 141 case kAT_ENCR_DATA: 142 return "AT_ENCR_DATA"; 143 case kAT_NEXT_PSEUDONYM: 144 return "AT_NEXT_PSEUDONYM"; 145 case kAT_NEXT_REAUTH_ID: 146 return "AT_NEXT_REAUTH_ID"; 147 case kAT_CHECKCODE: 148 return "AT_CHECKCODE"; 149 case kAT_RESULT_IND: 150 return "AT_RESULT_IND"; 151 default: 152 snprintf(buf, sizeof(buf), "%d", attr); 153 return (buf); 154 } 155} 156 157PRIVATE_EXTERN const char * 158ATNotificationCodeGetString(uint16_t code) 159{ 160 const char * str; 161 162 switch (code) { 163 case kATNotificationCodeGeneralFailureAfterAuthentication: 164 str = "General Failure After Authentication"; 165 break; 166 case kATNotificationCodeGeneralFailureBeforeAuthentication: 167 str = "General Failure Before Authentication"; 168 break; 169 case kATNotificationCodeSuccess: 170 str = "Success"; 171 break; 172 case kATNotificationCodeTemporarilyDeniedAccess: 173 str = "Temporarily Denied Access"; 174 break; 175 case kATNotificationCodeNotSubscribed: 176 str = "Not Subscribed"; 177 break; 178 default: 179 str = NULL; 180 break; 181 } 182 return (str); 183} 184 185/** 186 ** Miscellaneous utilities 187 **/ 188 189PRIVATE_EXTERN CFStringRef 190EAPSIMAKAPacketCopyDescription(const EAPPacketRef pkt, bool * packet_is_valid) 191{ 192 int attrs_length; 193 EAPSIMAKAPacketRef simaka = (EAPSIMAKAPacketRef)pkt; 194 uint16_t length = EAPPacketGetLength(pkt); 195 CFMutableStringRef str = NULL; 196 TLVListDeclare( tlvs_p); 197 bool valid = FALSE; 198 199 switch (pkt->code) { 200 case kEAPCodeRequest: 201 case kEAPCodeResponse: 202 break; 203 default: 204 goto done; 205 } 206 str = CFStringCreateMutable(NULL, 0); 207 if (length < kEAPSIMAKAPacketHeaderLength) { 208 STRING_APPEND(str, "EAPSIMAKAPacket truncated header %d < %d\n", 209 length, (int)kEAPSIMAKAPacketHeaderLength); 210 goto done; 211 } 212 attrs_length = length - kEAPSIMAKAPacketHeaderLength; 213 STRING_APPEND(str, 214 "%s %s: Identifier %d Length %d [%s] Length %d\n", 215 EAPTypeStr(simaka->type), 216 pkt->code == kEAPCodeRequest ? "Request" : "Response", 217 pkt->identifier, length, 218 EAPSIMAKAPacketSubtypeGetString(simaka->subtype), attrs_length); 219 if (attrs_length != 0) { 220 CFStringRef tlvs_str; 221 222 TLVListInit(tlvs_p); 223 if (TLVListParse(tlvs_p, simaka->attrs, attrs_length) == FALSE) { 224 STRING_APPEND(str, "failed to parse TLVs: %s\n", 225 TLVListErrorString(tlvs_p)); 226 goto done; 227 } 228 tlvs_str = TLVListCopyDescription(tlvs_p); 229 TLVListFree(tlvs_p); 230 STRING_APPEND(str, "%@", tlvs_str); 231 CFRelease(tlvs_str); 232 } 233 valid = TRUE; 234 235 done: 236 *packet_is_valid = valid; 237 return (str); 238} 239 240PRIVATE_EXTERN EAPSIMAKAStatus 241EAPSIMAKAStatusForATNotificationCode(uint16_t notification_code) 242{ 243 EAPSIMAKAStatus status = kEAPSIMAKAStatusOK; 244 245 switch (notification_code) { 246 case kATNotificationCodeGeneralFailureAfterAuthentication: 247 status = kEAPSIMAKAStatusFailureAfterAuthentication; 248 break; 249 case kATNotificationCodeGeneralFailureBeforeAuthentication: 250 status = kEAPSIMAKAStatusFailureBeforeAuthentication; 251 break; 252 case kATNotificationCodeSuccess: 253 status = kEAPSIMAKAStatusOK; 254 break; 255 case kATNotificationCodeTemporarilyDeniedAccess: 256 status = kEAPSIMAKAStatusAccessTemporarilyDenied; 257 break; 258 case kATNotificationCodeNotSubscribed: 259 status = kEAPSIMAKAStatusNotSubscribed; 260 break; 261 default: 262 status = kEAPSIMAKAStatusUnrecognizedNotification; 263 break; 264 } 265 return (status); 266} 267 268/* 269 * Function: EAPSIMAKAKeyInfoComputeMAC 270 * Purpose: 271 * Compute the MAC value in the AT_MAC attribute using the 272 * specified EAP packet 'pkt' and assuming 'mac_p' points to 273 * an area within 'pkt' that holds the MAC value. 274 * 275 * This function figures out how much data comes before the 'mac_p' 276 * value and how much comes after, and feeds the before, zero-mac, and after 277 * bytes into the HMAC-SHA1 algorithm. It also includes the 'extra' 278 * value, whose value depends on which packet is being MAC'd. 279 * Returns: 280 * 'hash' value is filled in with HMAC-SHA1 results. 281 */ 282PRIVATE_EXTERN void 283EAPSIMAKAKeyInfoComputeMAC(EAPSIMAKAKeyInfoRef key_info_p, 284 EAPPacketRef pkt, 285 const uint8_t * mac_p, 286 const uint8_t * extra, int extra_length, 287 uint8_t hash[CC_SHA1_DIGEST_LENGTH]) 288{ 289 int after_mac_size; 290 int before_mac_size; 291 CCHmacContext ctx; 292 int pkt_len = EAPPacketGetLength(pkt); 293 uint8_t zero_mac[MAC_SIZE]; 294 295 bzero(&zero_mac, sizeof(zero_mac)); 296 before_mac_size = mac_p - (const uint8_t *)pkt; 297 after_mac_size = pkt_len - (before_mac_size + sizeof(zero_mac)); 298 299 /* compute the hash */ 300 CCHmacInit(&ctx, kCCHmacAlgSHA1, key_info_p->s.k_aut, 301 sizeof(key_info_p->s.k_aut)); 302 CCHmacUpdate(&ctx, pkt, before_mac_size); 303 CCHmacUpdate(&ctx, zero_mac, sizeof(zero_mac)); 304 CCHmacUpdate(&ctx, mac_p + sizeof(zero_mac), after_mac_size); 305 if (extra != NULL) { 306 CCHmacUpdate(&ctx, extra, extra_length); 307 } 308 CCHmacFinal(&ctx, hash); 309 return; 310} 311 312PRIVATE_EXTERN bool 313EAPSIMAKAKeyInfoVerifyMAC(EAPSIMAKAKeyInfoRef key_info, 314 EAPPacketRef pkt, 315 const uint8_t * mac_p, 316 const uint8_t * extra, int extra_length) 317{ 318 uint8_t hash[CC_SHA1_DIGEST_LENGTH]; 319 320 EAPSIMAKAKeyInfoComputeMAC(key_info, pkt, mac_p, extra, extra_length, hash); 321 return (bcmp(hash, mac_p, MAC_SIZE) == 0); 322} 323 324PRIVATE_EXTERN void 325EAPSIMAKAKeyInfoSetMAC(EAPSIMAKAKeyInfoRef key_info, 326 EAPPacketRef pkt, 327 uint8_t * mac_p, 328 const uint8_t * extra, int extra_length) 329{ 330 uint8_t hash[CC_SHA1_DIGEST_LENGTH]; 331 332 EAPSIMAKAKeyInfoComputeMAC(key_info, pkt, mac_p, extra, extra_length, hash); 333 bcopy(hash, mac_p, MAC_SIZE); 334 return; 335} 336 337#include <CommonCrypto/CommonDigest.h> 338#include <CommonCrypto/CommonCryptor.h> 339 340PRIVATE_EXTERN uint8_t * 341EAPSIMAKAKeyInfoDecryptTLVList(EAPSIMAKAKeyInfoRef key_info_p, 342 AT_ENCR_DATA * encr_data_p, AT_IV * iv_p, 343 TLVListRef decrypted_tlvs_p) 344{ 345 CCCryptorRef cryptor = NULL; 346 size_t buf_used; 347 uint8_t * decrypted_buffer = NULL; 348 int encr_data_len; 349 CCCryptorStatus status; 350 bool success = FALSE; 351 352 encr_data_len = encr_data_p->ed_length * TLV_ALIGNMENT 353 - offsetof(AT_ENCR_DATA, ed_encrypted_data); 354 decrypted_buffer = (uint8_t *)malloc(encr_data_len); 355 status = CCCryptorCreate(kCCDecrypt, 356 kCCAlgorithmAES128, 357 0, 358 key_info_p->s.k_encr, 359 sizeof(key_info_p->s.k_encr), 360 iv_p->iv_initialization_vector, 361 &cryptor); 362 if (status != kCCSuccess) { 363 EAPLOG_FL(LOG_NOTICE, "CCCryptoCreate failed with %d", status); 364 goto done; 365 } 366 status = CCCryptorUpdate(cryptor, 367 encr_data_p->ed_encrypted_data, 368 encr_data_len, 369 decrypted_buffer, 370 encr_data_len, 371 &buf_used); 372 if (status != kCCSuccess) { 373 EAPLOG_FL(LOG_NOTICE, "CCCryptoUpdate failed with %d", status); 374 goto done; 375 } 376 if (buf_used != encr_data_len) { 377 EAPLOG_FL(LOG_NOTICE, 378 "decryption consumed %d bytes (!= %d bytes)", 379 (int)buf_used, encr_data_len); 380 goto done; 381 } 382 if (TLVListParse(decrypted_tlvs_p, decrypted_buffer, encr_data_len) 383 == FALSE) { 384 EAPLOG_FL(LOG_NOTICE, 385 "TLVListParse failed on AT_ENCR_DATA, %s", 386 TLVListErrorString(decrypted_tlvs_p)); 387 goto done; 388 } 389 success = TRUE; 390 391 done: 392 if (cryptor != NULL) { 393 status = CCCryptorRelease(cryptor); 394 if (status != kCCSuccess) { 395 EAPLOG_FL(LOG_NOTICE, "CCCryptoRelease failed with %d", status); 396 } 397 } 398 if (success == FALSE && decrypted_buffer != NULL) { 399 free(decrypted_buffer); 400 decrypted_buffer = NULL; 401 } 402 return (decrypted_buffer); 403} 404 405STATIC bool 406EAPSIMAKAKeyInfoEncrypt(EAPSIMAKAKeyInfoRef key_info_p, const uint8_t * iv_p, 407 const uint8_t * clear, int size, uint8_t * encrypted) 408{ 409 size_t buf_used; 410 CCCryptorRef cryptor; 411 bool ret = FALSE; 412 CCCryptorStatus status; 413 414 status = CCCryptorCreate(kCCEncrypt, 415 kCCAlgorithmAES128, 416 0, 417 key_info_p->s.k_encr, 418 sizeof(key_info_p->s.k_encr), 419 iv_p, 420 &cryptor); 421 if (status != kCCSuccess) { 422 EAPLOG_FL(LOG_NOTICE, "encrypt CCCryptoCreate failed with %d", status); 423 goto done; 424 } 425 status = CCCryptorUpdate(cryptor, clear, size, encrypted, size, &buf_used); 426 if (status != kCCSuccess) { 427 EAPLOG_FL(LOG_NOTICE, "encrypt CCCryptoUpdate failed with %d", status); 428 goto done; 429 } 430 if (buf_used != size) { 431 EAPLOG_FL(LOG_NOTICE, 432 "encryption consumed %d, should have been %d", 433 (int)buf_used, size); 434 goto done; 435 } 436 ret = TRUE; 437 438 done: 439 status = CCCryptorRelease(cryptor); 440 if (status != kCCSuccess) { 441 EAPLOG_FL(LOG_NOTICE, "CCCryptoRelease failed with %d", status); 442 } 443 return (ret); 444} 445 446STATIC void 447fill_with_random(uint8_t * buf, int len) 448{ 449 int i; 450 int n; 451 void * p; 452 uint32_t random; 453 454 n = len / sizeof(random); 455 for (i = 0, p = buf; i < n; i++, p += sizeof(random)) { 456 random = arc4random(); 457 bcopy(&random, p, sizeof(random)); 458 } 459 return; 460} 461 462PRIVATE_EXTERN bool 463EAPSIMAKAKeyInfoEncryptTLVs(EAPSIMAKAKeyInfoRef key_info, 464 TLVBufferRef tb_p, TLVBufferRef tb_add_p) 465{ 466 int buf_used; 467 int padding_length; 468 AT_ENCR_DATA * encr_data_p; 469 AT_IV * iv_p; 470 bool ret = FALSE; 471 TLVListDeclare( temp); 472 473 buf_used = TLVBufferUsed(tb_add_p); 474 padding_length = AT_ENCR_DATA_ROUNDUP(buf_used) - buf_used; 475 476 if (padding_length != 0 477 && TLVBufferAddPadding(tb_add_p, padding_length) == FALSE) { 478 EAPLOG_FL(LOG_NOTICE, "failed to add AT_PADDING, %s", 479 TLVBufferErrorString(tb_p)); 480 goto done; 481 } 482 483 if (TLVBufferUsed(tb_add_p) != TLVBufferMaxSize(tb_add_p)) { 484 EAPLOG_FL(LOG_NOTICE, "nested encrypted TLVs length %d != %d", 485 TLVBufferUsed(tb_add_p), TLVBufferMaxSize(tb_add_p)); 486 goto done; 487 } 488 489 TLVListInit(temp); 490 if (TLVListParse(temp, TLVBufferStorage(tb_add_p), 491 TLVBufferUsed(tb_add_p)) == FALSE) { 492 EAPLOG_FL(LOG_NOTICE, "nested TLVs TLVListParse failed, %s", 493 TLVListErrorString(temp)); 494 goto done; 495 } 496 { 497 CFStringRef str; 498 499 str = TLVListCopyDescription(temp); 500 TLVListFree(temp); 501 EAPLOG(LOG_DEBUG, "Encrypted TLVs:\n%@", str); 502 CFRelease(str); 503 } 504 505 /* AT_IV */ 506 iv_p = (AT_IV *) TLVBufferAllocateTLV(tb_p, kAT_IV, sizeof(AT_IV)); 507 if (iv_p == NULL) { 508 EAPLOG_FL(LOG_NOTICE, "failed to allocate AT_IV, %s", 509 TLVBufferErrorString(tb_p)); 510 goto done; 511 } 512 net_uint16_set(iv_p->iv_reserved, 0); 513 fill_with_random(iv_p->iv_initialization_vector, 514 sizeof(iv_p->iv_initialization_vector)); 515 516 /* AT_ENCR_DATA */ 517 encr_data_p = (AT_ENCR_DATA *) 518 TLVBufferAllocateTLV(tb_p, kAT_ENCR_DATA, 519 offsetof(AT_ENCR_DATA, ed_encrypted_data) 520 + TLVBufferUsed(tb_add_p)); 521 if (encr_data_p == NULL) { 522 EAPLOG_FL(LOG_NOTICE, "failed to allocate AT_ENCR_DATA, %s", 523 TLVBufferErrorString(tb_add_p)); 524 goto done; 525 } 526 net_uint16_set(encr_data_p->ed_reserved, 0); 527 if (!EAPSIMAKAKeyInfoEncrypt(key_info, iv_p->iv_initialization_vector, 528 TLVBufferStorage(tb_add_p), 529 TLVBufferUsed(tb_add_p), 530 encr_data_p->ed_encrypted_data)) { 531 EAPLOG_FL(LOG_NOTICE, "failed to encrypt AT_ENCR_DATA"); 532 goto done; 533 } 534 ret = TRUE; 535 536 done: 537 return (ret); 538} 539 540PRIVATE_EXTERN void 541EAPSIMAKAKeyInfoComputeReauthKey(EAPSIMAKAKeyInfoRef key_info, 542 EAPSIMAKAPersistentStateRef persist, 543 const void * identity, 544 int identity_length, 545 AT_COUNTER * counter_p, 546 AT_NONCE_S * nonce_s_p) 547{ 548 CC_SHA1_CTX sha1_context; 549 EAPSIMAKAKeyInfo temp_key_info; 550 uint8_t xkey[CC_SHA1_DIGEST_LENGTH]; 551 552 /* 553 * generate the XKEY': 554 * XKEY' = SHA1(Identity|counter|NONCE_S| MK) 555 */ 556 CC_SHA1_Init(&sha1_context); 557 CC_SHA1_Update(&sha1_context, identity, identity_length); 558 CC_SHA1_Update(&sha1_context, counter_p->co_counter, 559 sizeof(counter_p->co_counter)); 560 CC_SHA1_Update(&sha1_context, nonce_s_p->nc_nonce_s, 561 sizeof(nonce_s_p->nc_nonce_s)); 562 CC_SHA1_Update(&sha1_context, 563 EAPSIMAKAPersistentStateGetMasterKey(persist), 564 EAPSIMAKAPersistentStateGetMasterKeySize(persist)); 565 CC_SHA1_Final(xkey, &sha1_context); 566 567 /* now run PRF to generate keying material */ 568 fips186_2prf(xkey, temp_key_info.key); 569 570 /* copy the new MSK */ 571 bcopy(temp_key_info.key, 572 key_info->s.msk, 573 sizeof(key_info->s.msk)); 574 575 /* copy the new EMSK */ 576 bcopy(temp_key_info.key + sizeof(temp_key_info.s.msk), 577 key_info->s.emsk, 578 sizeof(key_info->s.emsk)); 579 return; 580} 581 582PRIVATE_EXTERN EAPSIMAKAAttributeType 583EAPSIMAKAIdentityTypeGetAttributeType(CFStringRef string) 584{ 585 EAPSIMAKAAttributeType type = kAT_ANY_ID_REQ; 586 587 if (string != NULL) { 588 if (CFEqual(kEAPSIMAKAIdentityTypeFullAuthentication, string)) { 589 type = kAT_FULLAUTH_ID_REQ; 590 } 591 else if (CFEqual(kEAPSIMAKAIdentityTypePermanent, string)) { 592 type = kAT_PERMANENT_ID_REQ; 593 } 594 } 595 return (type); 596} 597 598/** 599 ** TLVBuffer routines 600 **/ 601 602#define NBITS_PER_BYTE 8 603 604struct TLVBuffer { 605 uint8_t * storage; 606 int size; 607 int offset; 608 char err_str[160]; 609}; 610 611PRIVATE_EXTERN int 612TLVBufferSizeof(void) 613{ 614 return (sizeof(struct TLVBuffer)); 615} 616 617PRIVATE_EXTERN int 618TLVBufferUsed(TLVBufferRef tb) 619{ 620 return (tb->offset); 621} 622 623PRIVATE_EXTERN const char * 624TLVBufferErrorString(TLVBufferRef tb) 625{ 626 return (tb->err_str); 627} 628 629PRIVATE_EXTERN int 630TLVBufferMaxSize(TLVBufferRef tb) 631{ 632 return (tb->size); 633} 634 635PRIVATE_EXTERN uint8_t * 636TLVBufferStorage(TLVBufferRef tb) 637{ 638 return (tb->storage); 639} 640 641PRIVATE_EXTERN void 642TLVBufferInit(TLVBufferRef tb, uint8_t * storage, int size) 643{ 644 tb->storage = storage; 645 tb->size = size; 646 tb->offset = 0; 647 tb->err_str[0] = '\0'; 648 return; 649} 650 651PRIVATE_EXTERN TLVRef 652TLVBufferAllocateTLV(TLVBufferRef tb, EAPSIMAKAAttributeType type, int length) 653{ 654 int left; 655 int padded_length; 656 TLVRef tlv_p; 657 658 if (length < offsetof(TLV, tlv_value)) { 659 return (NULL); 660 } 661 padded_length = TLVRoundUp(length); 662 if (padded_length > TLV_MAX_LENGTH) { 663 snprintf(tb->err_str, sizeof(tb->err_str), 664 "padded_length %d > max length %d", 665 padded_length, TLV_MAX_LENGTH); 666 return (NULL); 667 } 668 left = tb->size - tb->offset; 669 if (left < padded_length) { 670 snprintf(tb->err_str, sizeof(tb->err_str), 671 "available space %d < required %d", 672 left, padded_length); 673 return (NULL); 674 } 675 676 /* set the type and length */ 677 tlv_p = (TLVRef)(tb->storage + tb->offset); 678 tlv_p->tlv_type = type; 679 tlv_p->tlv_length = padded_length / TLV_ALIGNMENT; 680 tb->offset += padded_length; 681 return (tlv_p); 682} 683 684PRIVATE_EXTERN Boolean 685TLVBufferAddIdentity(TLVBufferRef tb_p, 686 const uint8_t * identity, int identity_length) 687{ 688 AttrUnion attr; 689 690 attr.tlv_p = TLVBufferAllocateTLV(tb_p, 691 kAT_IDENTITY, 692 offsetof(AT_IDENTITY, id_identity) 693 + identity_length); 694 if (attr.tlv_p == NULL) { 695 return (FALSE); 696 } 697 net_uint16_set(attr.at_identity->id_actual_length, identity_length); 698 bcopy(identity, attr.at_identity->id_identity, identity_length); 699 return (TRUE); 700} 701 702PRIVATE_EXTERN Boolean 703TLVBufferAddIdentityString(TLVBufferRef tb_p, CFStringRef identity, 704 CFDataRef * ret_data) 705{ 706 CFDataRef data; 707 Boolean result; 708 709 *ret_data = NULL; 710 data = CFStringCreateExternalRepresentation(NULL, identity, 711 kCFStringEncodingUTF8, 0); 712 if (data == NULL) { 713 return (FALSE); 714 } 715 result = TLVBufferAddIdentity(tb_p, CFDataGetBytePtr(data), 716 CFDataGetLength(data)); 717 if (result == TRUE && ret_data != NULL) { 718 *ret_data = data; 719 } 720 else { 721 CFRelease(data); 722 } 723 return (result); 724 725} 726 727PRIVATE_EXTERN Boolean 728TLVBufferAddCounter(TLVBufferRef tb_p, uint16_t at_counter) 729{ 730 AT_COUNTER * counter_p; 731 732 counter_p = (AT_COUNTER *)TLVBufferAllocateTLV(tb_p, kAT_COUNTER, 733 sizeof(AT_COUNTER)); 734 if (counter_p == NULL) { 735 return (FALSE); 736 } 737 net_uint16_set(counter_p->co_counter, at_counter); 738 return (TRUE); 739} 740 741PRIVATE_EXTERN Boolean 742TLVBufferAddCounterTooSmall(TLVBufferRef tb_p) 743{ 744 AT_COUNTER_TOO_SMALL * counter_too_small_p; 745 746 counter_too_small_p = (AT_COUNTER_TOO_SMALL *) 747 TLVBufferAllocateTLV(tb_p, kAT_COUNTER_TOO_SMALL, 748 sizeof(AT_COUNTER_TOO_SMALL)); 749 if (counter_too_small_p == NULL) { 750 return (FALSE); 751 } 752 net_uint16_set(counter_too_small_p->cs_reserved, 0); 753 return (TRUE); 754} 755 756PRIVATE_EXTERN Boolean 757TLVBufferAddPadding(TLVBufferRef tb_p, int padding_length) 758{ 759 AT_PADDING * padding_p; 760 761 switch (padding_length) { 762 case 4: 763 case 8: 764 case 12: 765 break; 766 default: 767 snprintf(tb_p->err_str, sizeof(tb_p->err_str), 768 "invalid AT_PADDING %d", padding_length); 769 return (FALSE); 770 } 771 padding_p = (AT_PADDING *) 772 TLVBufferAllocateTLV(tb_p, kAT_PADDING, padding_length); 773 if (padding_p == NULL) { 774 strlcpy(tb_p->err_str,"couldn't allocate TLV", sizeof(tb_p->err_str)); 775 return (FALSE); 776 } 777 bzero(padding_p->pa_padding, 778 padding_length - offsetof(AT_PADDING, pa_padding)); 779 return (TRUE); 780} 781 782/** 783 ** TLVList routines 784 **/ 785#define N_ATTRS_STATIC 10 786struct TLVList { 787 const void * * attrs; /* pointers to attributes */ 788 const void * attrs_static[N_ATTRS_STATIC]; 789 int count; 790 int size; 791 char err_str[160]; 792}; 793 794PRIVATE_EXTERN int 795TLVListSizeof(void) 796{ 797 return (sizeof(struct TLVList)); 798} 799 800INLINE int 801TLVListAttrsStaticSize(void) 802{ 803 const TLVListRef tlvs_p; 804 805 return ((int)sizeof(tlvs_p->attrs_static) 806 / sizeof(tlvs_p->attrs_static[0])); 807} 808 809PRIVATE_EXTERN const char * 810TLVListErrorString(TLVListRef tlvs_p) 811{ 812 return (tlvs_p->err_str); 813} 814 815PRIVATE_EXTERN void 816TLVListInit(TLVListRef tlvs_p) 817{ 818 tlvs_p->attrs = NULL; 819 tlvs_p->count = tlvs_p->size = 0; 820 return; 821} 822 823PRIVATE_EXTERN void 824TLVListFree(TLVListRef tlvs_p) 825{ 826 if (tlvs_p->attrs != NULL && tlvs_p->attrs != tlvs_p->attrs_static) { 827#ifdef TEST_TLVLIST_PARSE 828 printf("freeing data\n"); 829#endif /* TEST_TLVLIST_PARSE */ 830 free(tlvs_p->attrs); 831 } 832 TLVListInit(tlvs_p); 833 return; 834} 835 836PRIVATE_EXTERN void 837TLVListAddAttribute(TLVListRef tlvs_p, const uint8_t * attr) 838{ 839 if (tlvs_p->attrs == NULL) { 840 tlvs_p->attrs = tlvs_p->attrs_static; 841 tlvs_p->size = TLVListAttrsStaticSize(); 842 } 843 else if (tlvs_p->count == tlvs_p->size) { 844 tlvs_p->size += TLVListAttrsStaticSize(); 845 if (tlvs_p->attrs == tlvs_p->attrs_static) { 846 tlvs_p->attrs = (const void * *) 847 malloc(sizeof(*tlvs_p->attrs) * tlvs_p->size); 848 bcopy(tlvs_p->attrs_static, tlvs_p->attrs, 849 sizeof(*tlvs_p->attrs) * tlvs_p->count); 850 } 851 else { 852 tlvs_p->attrs = (const void * *) 853 reallocf(tlvs_p->attrs, 854 sizeof(*tlvs_p->attrs) * tlvs_p->size); 855 } 856 } 857 tlvs_p->attrs[tlvs_p->count++] = attr; 858 return; 859} 860 861enum { 862 kTLVGood = 0, 863 kTLVBad = 1, 864 kTLVUnrecognized = 2 865}; 866 867PRIVATE_EXTERN int 868TLVCheckValidity(TLVListRef tlvs_p, TLVRef tlv_p) 869{ 870 AttrUnion attr; 871 int i; 872 int len; 873 int n_bits; 874 int offset; 875 int ret = kTLVGood; 876 const uint8_t * scan; 877 int tlv_length; 878 879 attr.tlv_p = tlv_p; 880 tlv_length = tlv_p->tlv_length * TLV_ALIGNMENT; 881 switch (tlv_p->tlv_type) { 882 case kAT_RAND: 883 offset = offsetof(AT_RAND, ra_rand); 884 if (tlv_length <= offset) { 885 /* truncated option */ 886 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 887 "%s truncated %d <= %d", 888 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 889 tlv_length, offset); 890 ret = kTLVBad; 891 break; 892 } 893 len = tlv_length - offset; 894 if ((len % RAND_SIZE) != 0) { 895 /* must be a multiple of 16 bytes */ 896 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 897 "AT_RAND rand length %d not multiple of %d", 898 len, RAND_SIZE); 899 ret = kTLVBad; 900 break; 901 } 902 if (len == 0) { 903 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 904 "AT_RAND contains no RANDs"); 905 ret = kTLVBad; 906 break; 907 } 908 break; 909 case kAT_RES: 910 offset = offsetof(AT_RES, rs_res); 911 if (tlv_length <= offset) { 912 /* truncated option */ 913 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 914 "%s truncated %d <= %d", 915 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 916 tlv_length, offset); 917 ret = kTLVBad; 918 break; 919 } 920 n_bits = net_uint16_get(attr.at_res->rs_res_length); 921 len = (n_bits + NBITS_PER_BYTE - 1) / NBITS_PER_BYTE; 922 if (len > (tlv_length - offset)) { 923 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 924 "%s actual length %d > TLV length %d", 925 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 926 len, tlv_length - offset); 927 ret = kTLVBad; 928 break; 929 } 930 break; 931 case kAT_AUTS: 932 offset = offsetof(AT_AUTS, as_auts); 933 if (tlv_length <= offset) { 934 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 935 "%s truncated %d <= %d", 936 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 937 tlv_length, offset); 938 ret = kTLVBad; 939 break; 940 } 941 len = tlv_length - offset; 942 if (len != AUTS_SIZE) { 943 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 944 "%s invalid length %d != %d", 945 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 946 len, AUTS_SIZE); 947 ret = kTLVBad; 948 break; 949 } 950 break; 951 case kAT_PADDING: 952 switch (tlv_length) { 953 case 4: 954 case 8: 955 case 12: 956 len = tlv_length - offsetof(AT_PADDING, pa_padding); 957 for (i = 0, scan = attr.at_padding->pa_padding; 958 i < len; i++, scan++) { 959 if (*scan != 0) { 960 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 961 "AT_PADDING non-zero value 0x%x at offset %d", 962 *scan, i); 963 ret = kTLVBad; 964 break; 965 } 966 } 967 break; 968 default: 969 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 970 "AT_PADDING length %d not 4, 8, or 12", tlv_length); 971 ret = kTLVBad; 972 break; 973 } 974 break; 975 case kAT_AUTN: 976 case kAT_NONCE_MT: 977 case kAT_IV: 978 case kAT_MAC: 979 case kAT_NONCE_S: 980 offset = offsetof(AT_NONCE_MT, nm_nonce_mt); 981 if (tlv_length <= offset) { 982 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 983 "%s truncated %d <= %d", 984 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 985 tlv_length, offset); 986 ret = kTLVBad; 987 break; 988 } 989 len = tlv_length - offset; 990 if (len != sizeof(attr.at_nonce_mt->nm_nonce_mt)) { 991 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 992 "%s invalid length %d != %d", 993 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 994 len, (int)sizeof(attr.at_nonce_mt->nm_nonce_mt)); 995 ret = kTLVBad; 996 break; 997 } 998 break; 999 case kAT_IDENTITY: 1000 case kAT_VERSION_LIST: 1001 case kAT_NEXT_PSEUDONYM: 1002 case kAT_NEXT_REAUTH_ID: 1003 offset = offsetof(AT_IDENTITY, id_identity); 1004 if (tlv_length <= offset) { 1005 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1006 "%s empty/truncated (%d <= %d)", 1007 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 1008 tlv_length, offset); 1009 ret = kTLVBad; 1010 break; 1011 } 1012 len = net_uint16_get(attr.at_identity->id_actual_length); 1013 if (len > (tlv_length - offset)) { 1014 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1015 "%s actual length %d > TLV length %d", 1016 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 1017 len, tlv_length - offset); 1018 ret = kTLVBad; 1019 break; 1020 } 1021 if (tlv_p->tlv_type == kAT_VERSION_LIST && (len & 0x1) != 0) { 1022 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1023 "AT_VERSION_LIST actual length %d not multiple of 2", 1024 len); 1025 ret = kTLVBad; 1026 break; 1027 } 1028 break; 1029 case kAT_ENCR_DATA: 1030 offset = offsetof(AT_ENCR_DATA, ed_encrypted_data); 1031 if (tlv_length <= offset) { 1032 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1033 "AT_ENCR_DATA empty/truncated (%d <= %d)", 1034 tlv_length, offset); 1035 ret = kTLVBad; 1036 break; 1037 } 1038 break; 1039 case kAT_SELECTED_VERSION: 1040 case kAT_PERMANENT_ID_REQ: 1041 case kAT_ANY_ID_REQ: 1042 case kAT_FULLAUTH_ID_REQ: 1043 case kAT_RESULT_IND: 1044 case kAT_COUNTER: 1045 case kAT_COUNTER_TOO_SMALL: 1046 case kAT_CLIENT_ERROR_CODE: 1047 case kAT_NOTIFICATION: 1048 if (tlv_length != 4) { 1049 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1050 "%s length %d != 4", 1051 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 1052 tlv_length); 1053 ret = kTLVBad; 1054 break; 1055 } 1056 break; 1057 default: 1058 ret = kTLVUnrecognized; 1059 break; 1060 } 1061 return (ret); 1062} 1063 1064PRIVATE_EXTERN Boolean 1065TLVListParse(TLVListRef tlvs_p, const uint8_t * attrs, int attrs_length) 1066{ 1067 int offset; 1068 const uint8_t * scan; 1069 Boolean success = TRUE; 1070 int tlv_length; 1071 1072 scan = attrs; 1073 offset = 0; 1074 while (TRUE) { 1075 int left = attrs_length - offset; 1076 TLVRef this_tlv; 1077 int tlv_validity; 1078 1079 if (left == 0) { 1080 /* we're done */ 1081 break; 1082 } 1083 if (left < TLV_HEADER_LENGTH) { 1084 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1085 "Missing/truncated attribute at offset %d", 1086 offset); 1087 success = FALSE; 1088 break; 1089 } 1090 this_tlv = (TLVRef)scan; 1091 tlv_length = this_tlv->tlv_length * TLV_ALIGNMENT; 1092 if (tlv_length > left) { 1093 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1094 "%s too large %d (> %d) at offset %d", 1095 EAPSIMAKAAttributeTypeGetString(this_tlv->tlv_type), 1096 tlv_length, left, offset); 1097 success = FALSE; 1098 break; 1099 } 1100 tlv_validity = TLVCheckValidity(tlvs_p, this_tlv); 1101 if (tlv_validity == kTLVGood) { 1102 TLVListAddAttribute(tlvs_p, scan); 1103 } 1104 else if (tlv_validity == kTLVBad 1105 || ((tlv_validity == kTLVUnrecognized) 1106 && (this_tlv->tlv_type 1107 < kEAPSIM_TLV_SKIPPABLE_RANGE_START))) { 1108 if (tlv_validity == kTLVUnrecognized) { 1109 snprintf(tlvs_p->err_str, sizeof(tlvs_p->err_str), 1110 "unrecognized attribute %d", this_tlv->tlv_type); 1111 } 1112 success = FALSE; 1113 break; 1114 } 1115 offset += tlv_length;; 1116 scan += tlv_length; 1117 } 1118 if (success == FALSE) { 1119 TLVListFree(tlvs_p); 1120 } 1121 return (success); 1122} 1123 1124#define _WIDTH "%18" 1125 1126STATIC void 1127TLVPrintToString(CFMutableStringRef str, TLVRef tlv_p) 1128{ 1129 AttrUnion attr; 1130 char buf[128]; 1131 int count; 1132 int i; 1133 const char * field_name; 1134 int len; 1135 int n_bits; 1136 int pad_len; 1137 uint8_t * scan; 1138 int tlv_length; 1139 uint16_t val16; 1140 1141 attr.tlv_p = tlv_p; 1142 tlv_length = tlv_p->tlv_length * TLV_ALIGNMENT; 1143 STRING_APPEND(str, "%s: Length %d\n", 1144 EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type), 1145 tlv_length); 1146 field_name = EAPSIMAKAAttributeTypeGetString(tlv_p->tlv_type) + 3; 1147 switch (tlv_p->tlv_type) { 1148 case kAT_RAND: 1149 STRING_APPEND(str, _WIDTH "s:\t", "(reserved)"); 1150 print_bytes_cfstr(str, attr.at_rand->ra_reserved, 1151 sizeof(attr.at_rand->ra_reserved)); 1152 len = tlv_length - offsetof(AT_RAND, ra_rand); 1153 count = len / RAND_SIZE; 1154 STRING_APPEND(str, "\n" _WIDTH"s: (n=%d)\n", field_name, count); 1155 for (scan = attr.at_rand->ra_rand, i = 0; 1156 i < count; i++, scan += RAND_SIZE) { 1157 STRING_APPEND(str, _WIDTH "d:\t", i); 1158 print_bytes_cfstr(str, scan, RAND_SIZE); 1159 STRING_APPEND(str, "\n"); 1160 } 1161 break; 1162 case kAT_RES: 1163 n_bits = net_uint16_get(attr.at_res->rs_res_length); 1164 len = (n_bits + NBITS_PER_BYTE - 1) / NBITS_PER_BYTE; 1165 STRING_APPEND(str, _WIDTH "s: %d bits (%d bytes)\n", field_name, n_bits, len); 1166 print_bytes_cfstr(str, attr.at_res->rs_res, len); 1167 STRING_APPEND(str, "\n"); 1168 break; 1169 case kAT_AUTS: 1170 len = tlv_length - offsetof(AT_AUTS, as_auts); 1171 STRING_APPEND(str, _WIDTH "s: %d bytes\n", field_name, len); 1172 print_bytes_cfstr(str, attr.at_auts->as_auts, len); 1173 STRING_APPEND(str, "\n"); 1174 break; 1175 case kAT_PADDING: 1176 len = tlv_length - offsetof(AT_PADDING, pa_padding); 1177 STRING_APPEND(str, _WIDTH "s: %d bytes\n", field_name, len); 1178 STRING_APPEND(str, _WIDTH "s\t", ""); 1179 print_bytes_cfstr(str, attr.at_padding->pa_padding, len); 1180 STRING_APPEND(str, "\n"); 1181 break; 1182 case kAT_AUTN: 1183 case kAT_NONCE_MT: 1184 case kAT_IV: 1185 case kAT_MAC: 1186 case kAT_NONCE_S: 1187 STRING_APPEND(str, _WIDTH "s:\t", "(reserved)"); 1188 print_bytes_cfstr(str, attr.at_nonce_mt->nm_reserved, 1189 sizeof(attr.at_nonce_mt->nm_reserved)); 1190 STRING_APPEND(str, "\n" _WIDTH "s:\t", field_name); 1191 print_bytes_cfstr(str, attr.at_nonce_mt->nm_nonce_mt, 1192 sizeof(attr.at_nonce_mt->nm_nonce_mt)); 1193 STRING_APPEND(str, "\n"); 1194 break; 1195 case kAT_VERSION_LIST: 1196 len = net_uint16_get(attr.at_version_list->vl_actual_length); 1197 count = len / sizeof(uint16_t); 1198 STRING_APPEND(str, _WIDTH "s: Actual Length %d\n", field_name, len); 1199 for (scan = attr.at_version_list->vl_version_list, i = 0; 1200 i < count; i++, scan += sizeof(uint16_t)) { 1201 uint16_t this_vers = net_uint16_get(scan); 1202 1203 STRING_APPEND(str, _WIDTH "d:\t%04d\n", i, this_vers); 1204 } 1205 pad_len = (tlv_length - offsetof(AT_VERSION_LIST, vl_version_list)) 1206 - len; 1207 snprintf(buf, sizeof(buf), "(%d pad bytes)", pad_len); 1208 STRING_APPEND(str, _WIDTH "s:\t", buf); 1209 print_bytes_cfstr(str, attr.at_identity->id_identity + len, pad_len); 1210 STRING_APPEND(str, "\n"); 1211 break; 1212 case kAT_IDENTITY: 1213 case kAT_NEXT_PSEUDONYM: 1214 case kAT_NEXT_REAUTH_ID: 1215 len = net_uint16_get(attr.at_identity->id_actual_length); 1216 STRING_APPEND(str, _WIDTH "s: Actual Length %d\n", field_name, len); 1217 print_data_cfstr(str, attr.at_identity->id_identity, len); 1218 pad_len = (tlv_length - offsetof(AT_IDENTITY, id_identity)) - len; 1219 if (pad_len != 0) { 1220 snprintf(buf, sizeof(buf), "(%d pad bytes)", pad_len); 1221 STRING_APPEND(str, _WIDTH "s:\t", buf); 1222 print_bytes_cfstr(str, attr.at_identity->id_identity + len, pad_len); 1223 STRING_APPEND(str, "\n"); 1224 } 1225 break; 1226 case kAT_ENCR_DATA: 1227 STRING_APPEND(str, _WIDTH "s:\t", "(reserved)"); 1228 print_bytes_cfstr(str, attr.at_encr_data->ed_reserved, 1229 sizeof(attr.at_encr_data->ed_reserved)); 1230 len = tlv_length - offsetof(AT_ENCR_DATA, ed_encrypted_data); 1231 STRING_APPEND(str, "\n" _WIDTH "s: Length %d\n", field_name, len); 1232 print_data_cfstr(str, attr.at_encr_data->ed_encrypted_data, len); 1233 break; 1234 case kAT_SELECTED_VERSION: 1235 case kAT_COUNTER: 1236 case kAT_CLIENT_ERROR_CODE: 1237 case kAT_NOTIFICATION: 1238 val16 = net_uint16_get(attr.at_selected_version->sv_selected_version); 1239 STRING_APPEND(str, _WIDTH "s:\t%04d\n", field_name, val16); 1240 break; 1241 case kAT_PERMANENT_ID_REQ: 1242 case kAT_ANY_ID_REQ: 1243 case kAT_FULLAUTH_ID_REQ: 1244 case kAT_RESULT_IND: 1245 case kAT_COUNTER_TOO_SMALL: 1246 STRING_APPEND(str, _WIDTH "s:\t", "(reserved)"); 1247 print_bytes_cfstr(str, attr.at_encr_data->ed_reserved, 1248 sizeof(attr.at_encr_data->ed_reserved)); 1249 STRING_APPEND(str, "\n"); 1250 break; 1251 default: 1252 break; 1253 } 1254 return; 1255} 1256 1257PRIVATE_EXTERN CFStringRef 1258TLVListCopyDescription(TLVListRef tlvs_p) 1259{ 1260 int i; 1261 const void * * scan; 1262 CFMutableStringRef str; 1263 1264 str = CFStringCreateMutable(NULL, 0); 1265 for (i = 0, scan = tlvs_p->attrs; i < tlvs_p->count; i++, scan++) { 1266 TLVRef tlv_p = (TLVRef)(*scan); 1267 1268 TLVPrintToString(str, tlv_p); 1269 } 1270 return (str); 1271} 1272 1273PRIVATE_EXTERN TLVRef 1274TLVListLookupAttribute(TLVListRef tlvs_p, EAPSIMAKAAttributeType type) 1275{ 1276 int i; 1277 const void * * scan; 1278 1279 for (i = 0, scan = tlvs_p->attrs; i < tlvs_p->count; i++, scan++) { 1280 TLVRef tlv_p = (TLVRef)(*scan); 1281 1282 if (tlv_p->tlv_type == type) { 1283 return (tlv_p); 1284 } 1285 } 1286 return (NULL); 1287} 1288 1289PRIVATE_EXTERN CFStringRef 1290TLVCreateString(TLVRef tlv_p) 1291{ 1292 CFDataRef data; 1293 int len; 1294 AT_IDENTITY * id_p = (AT_IDENTITY *)tlv_p; 1295 CFStringRef str; 1296 1297 len = net_uint16_get(id_p->id_actual_length); 1298 data = CFDataCreateWithBytesNoCopy(NULL, id_p->id_identity, len, 1299 kCFAllocatorNull); 1300 str = CFStringCreateFromExternalRepresentation(NULL, data, 1301 kCFStringEncodingUTF8); 1302 CFRelease(data); 1303 return (str); 1304} 1305 1306PRIVATE_EXTERN CFStringRef 1307TLVListCreateStringFromAttribute(TLVListRef tlvs_p, EAPSIMAKAAttributeType type) 1308{ 1309 TLVRef tlv_p; 1310 1311 switch (type) { 1312 case kAT_NEXT_REAUTH_ID: 1313 case kAT_NEXT_PSEUDONYM: 1314 break; 1315 default: 1316 return (NULL); 1317 } 1318 tlv_p = TLVListLookupAttribute(tlvs_p, type); 1319 if (tlv_p == NULL) { 1320 return (NULL); 1321 } 1322 return (TLVCreateString(tlv_p)); 1323} 1324 1325PRIVATE_EXTERN EAPSIMAKAAttributeType 1326TLVListLookupIdentityAttribute(TLVListRef tlvs_p) 1327{ 1328 STATIC const EAPSIMAKAAttributeType S_types[] = { 1329 kAT_ANY_ID_REQ, 1330 kAT_FULLAUTH_ID_REQ, 1331 kAT_PERMANENT_ID_REQ 1332 }; 1333 int i; 1334 1335 for (i = 0; i < sizeof(S_types) / sizeof(S_types[0]); i++) { 1336 if (TLVListLookupAttribute(tlvs_p, S_types[i]) != NULL) { 1337 return (S_types[i]); 1338 } 1339 } 1340 return (0); 1341} 1342 1343/** 1344 ** 1345 ** - - - - T E S T H A R N E S S E S - - - 1346 ** 1347 **/ 1348 1349#ifdef EAPSIMAKA_PACKET_DUMP 1350PRIVATE_EXTERN bool 1351EAPSIMAKAPacketDump(FILE * out_f, EAPPacketRef pkt) 1352{ 1353 bool packet_is_valid = FALSE; 1354 CFStringRef str; 1355 1356 str = EAPSIMAKAPacketCopyDescription(pkt, &packet_is_valid); 1357 if (str != NULL) { 1358 SCPrint(TRUE, out_f, CFSTR("%@"), str); 1359 CFRelease(str); 1360 } 1361 return (packet_is_valid); 1362} 1363#endif /* EAPSIMAKA_PACKET_DUMP */ 1364 1365#ifdef TEST_TLVLIST_PARSE 1366/* 1367 A.3. EAP-Request/SIM/Start 1368 1369 The server's first packet looks like this: 1370 1371 01 ; Code: Request 1372 01 ; Identifier: 1 1373 00 10 ; Length: 16 octets 1374 12 ; Type: EAP-SIM 1375 0a ; EAP-SIM subtype: Start 1376 00 00 ; (reserved) 1377 0f ; Attribute type: AT_VERSION_LIST 1378 02 ; Attribute length: 8 octets (2*4) 1379 00 02 ; Actual version list length: 2 octets 1380 00 01 ; Version: 1 1381 00 00 ; (attribute padding) 1382*/ 1383const uint8_t eap_request_sim_start[] = { 1384 0x01, 1385 0x01, 1386 0x00, 0x10, 1387 0x12, 1388 0x0a, 1389 0x00, 0x00, 1390 0x0f, 1391 0x02, 1392 0x00, 0x02, 1393 0x00, 0x01, 1394 0x00, 0x00, 1395}; 1396 1397/* 1398 A.4. EAP-Response/SIM/Start 1399 1400 The client selects a nonce and responds with the following packet: 1401 1402 02 ; Code: Response 1403 01 ; Identifier: 1 1404 00 20 ; Length: 32 octets 1405 12 ; Type: EAP-SIM 1406 0a ; EAP-SIM subtype: Start 1407 00 00 ; (reserved) 1408 07 ; Attribute type: AT_NONCE_MT 1409 05 ; Attribute length: 20 octets (5*4) 1410 00 00 ; (reserved) 1411 01 23 45 67 ; NONCE_MT value 1412 89 ab cd ef 1413 fe dc ba 98 1414 76 54 32 10 1415 10 ; Attribute type: AT_SELECTED_VERSION 1416 01 ; Attribute length: 4 octets (1*4) 1417 00 01 ; Version: 1 1418 1419*/ 1420const uint8_t eap_response_sim_start[] = { 1421 0x02, 1422 0x01, 1423 0x00, 0x20, 1424 0x12, 1425 0x0a, 1426 0x00, 0x00, 1427 0x07, 1428 0x05, 1429 0x00, 0x00, 1430 0x01, 0x23, 0x45, 0x67, 1431 0x89, 0xab, 0xcd, 0xef, 1432 0xfe, 0xdc, 0xba, 0x98, 1433 0x76, 0x54, 0x32, 0x10, 1434 0x10, 1435 0x01, 1436 0x00, 0x01 1437}; 1438 1439/* 1440 The EAP packet looks like this: 1441 1442 01 ; Code: Request 1443 02 ; Identifier: 2 1444 01 18 ; Length: 280 octets 1445 12 ; Type: EAP-SIM 1446 0b ; EAP-SIM subtype: Challenge 1447 00 00 ; (reserved) 1448 01 ; Attribute type: AT_RAND 1449 0d ; Attribute length: 52 octets (13*4) 1450 00 00 ; (reserved) 1451 10 11 12 13 ; first RAND 1452 14 15 16 17 1453 18 19 1a 1b 1454 1c 1d 1e 1f 1455 20 21 22 23 ; second RAND 1456 24 25 26 27 1457 28 29 2a 2b 1458 2c 2d 2e 2f 1459 30 31 32 33 ; third RAND 1460 34 35 36 37 1461 38 39 3a 3b 1462 3c 3d 3e 3f 1463 81 ; Attribute type: AT_IV 1464 05 ; Attribute length: 20 octets (5*4) 1465 00 00 ; (reserved) 1466 9e 18 b0 c2 ; IV value 1467 9a 65 22 63 1468 c0 6e fb 54 1469 dd 00 a8 95 1470 82 ; Attribute type: AT_ENCR_DATA 1471 2d ; Attribute length: 180 octets (45*4) 1472 00 00 ; (reserved) 1473 55 f2 93 9b bd b1 b1 9e a1 b4 7f c0 b3 e0 be 4c 1474 ab 2c f7 37 2d 98 e3 02 3c 6b b9 24 15 72 3d 58 1475 ba d6 6c e0 84 e1 01 b6 0f 53 58 35 4b d4 21 82 1476 78 ae a7 bf 2c ba ce 33 10 6a ed dc 62 5b 0c 1d 1477 5a a6 7a 41 73 9a e5 b5 79 50 97 3f c7 ff 83 01 1478 07 3c 6f 95 31 50 fc 30 3e a1 52 d1 e1 0a 2d 1f 1479 4f 52 26 da a1 ee 90 05 47 22 52 bd b3 b7 1d 6f 1480 0c 3a 34 90 31 6c 46 92 98 71 bd 45 cd fd bc a6 1481 11 2f 07 f8 be 71 79 90 d2 5f 6d d7 f2 b7 b3 20 1482 bf 4d 5a 99 2e 88 03 31 d7 29 94 5a ec 75 ae 5d 1483 43 c8 ed a5 fe 62 33 fc ac 49 4e e6 7a 0d 50 4d 1484 0b ; Attribute type: AT_MAC 1485 05 ; Attribute length: 20 octets (5*4) 1486 00 00 ; (reserved) 1487 fe f3 24 ac ; MAC value 1488 39 62 b5 9f 1489 3b d7 82 53 1490 ae 4d cb 6a 1491*/ 1492const uint8_t eap_request_fast_reauth[] = { 1493 0x01, 1494 0x02, 1495 0x01, 0x18, 1496 0x12, 1497 0x0b, 1498 0x00, 0x00, 1499 0x01, 1500 0x0d, 1501 0x00, 0x00, 1502 0x10, 0x11, 0x12, 0x13, 1503 0x14, 0x15, 0x16, 0x17, 1504 0x18, 0x19, 0x1a, 0x1b, 1505 0x1c, 0x1d, 0x1e, 0x1f, 1506 0x20, 0x21, 0x22, 0x23, 1507 0x24, 0x25, 0x26, 0x27, 1508 0x28, 0x29, 0x2a, 0x2b, 1509 0x2c, 0x2d, 0x2e, 0x2f, 1510 0x30, 0x31, 0x32, 0x33, 1511 0x34, 0x35, 0x36, 0x37, 1512 0x38, 0x39, 0x3a, 0x3b, 1513 0x3c, 0x3d, 0x3e, 0x3f, 1514 0x81, 1515 0x05, 1516 0x00, 0x00, 1517 0x9e, 0x18, 0xb0, 0xc2, 1518 0x9a, 0x65, 0x22, 0x63, 1519 0xc0, 0x6e, 0xfb, 0x54, 1520 0xdd, 0x00, 0xa8, 0x95, 1521 0x82, 1522 0x2d, 1523 0x00, 0x00, 1524 0x55, 0xf2, 0x93, 0x9b, 0xbd, 0xb1, 0xb1, 0x9e, 0xa1, 0xb4, 0x7f, 0xc0, 0xb3, 0xe0, 0xbe, 0x4c, 1525 0xab, 0x2c, 0xf7, 0x37, 0x2d, 0x98, 0xe3, 0x02, 0x3c, 0x6b, 0xb9, 0x24, 0x15, 0x72, 0x3d, 0x58, 1526 0xba, 0xd6, 0x6c, 0xe0, 0x84, 0xe1, 0x01, 0xb6, 0x0f, 0x53, 0x58, 0x35, 0x4b, 0xd4, 0x21, 0x82, 1527 0x78, 0xae, 0xa7, 0xbf, 0x2c, 0xba, 0xce, 0x33, 0x10, 0x6a, 0xed, 0xdc, 0x62, 0x5b, 0x0c, 0x1d, 1528 0x5a, 0xa6, 0x7a, 0x41, 0x73, 0x9a, 0xe5, 0xb5, 0x79, 0x50, 0x97, 0x3f, 0xc7, 0xff, 0x83, 0x01, 1529 0x07, 0x3c, 0x6f, 0x95, 0x31, 0x50, 0xfc, 0x30, 0x3e, 0xa1, 0x52, 0xd1, 0xe1, 0x0a, 0x2d, 0x1f, 1530 0x4f, 0x52, 0x26, 0xda, 0xa1, 0xee, 0x90, 0x05, 0x47, 0x22, 0x52, 0xbd, 0xb3, 0xb7, 0x1d, 0x6f, 1531 0x0c, 0x3a, 0x34, 0x90, 0x31, 0x6c, 0x46, 0x92, 0x98, 0x71, 0xbd, 0x45, 0xcd, 0xfd, 0xbc, 0xa6, 1532 0x11, 0x2f, 0x07, 0xf8, 0xbe, 0x71, 0x79, 0x90, 0xd2, 0x5f, 0x6d, 0xd7, 0xf2, 0xb7, 0xb3, 0x20, 1533 0xbf, 0x4d, 0x5a, 0x99, 0x2e, 0x88, 0x03, 0x31, 0xd7, 0x29, 0x94, 0x5a, 0xec, 0x75, 0xae, 0x5d, 1534 0x43, 0xc8, 0xed, 0xa5, 0xfe, 0x62, 0x33, 0xfc, 0xac, 0x49, 0x4e, 0xe6, 0x7a, 0x0d, 0x50, 0x4d, 1535 0x0b, 1536 0x05, 1537 0x00, 0x00, 1538 0xfe, 0xf3, 0x24, 0xac, 1539 0x39, 0x62, 0xb5, 0x9f, 1540 0x3b, 0xd7, 0x82, 0x53, 1541 0xae, 0x4d, 0xcb, 0x6a 1542}; 1543 1544/* 1545 The following plaintext will be encrypted and stored in the 1546 AT_ENCR_DATA attribute: 1547 1548 84 ; Attribute type: AT_NEXT_PSEUDONYM 1549 13 ; Attribute length: 76 octets (19*4) 1550 00 46 ; Actual pseudonym length: 70 octets 1551 77 38 77 34 39 50 65 78 43 61 7a 57 4a 26 78 43 1552 49 41 52 6d 78 75 4d 4b 68 74 35 53 31 73 78 52 1553 44 71 58 53 45 46 42 45 67 33 44 63 5a 50 39 63 1554 49 78 54 65 35 4a 34 4f 79 49 77 4e 47 56 7a 78 1555 65 4a 4f 55 31 47 1556 00 00 ; (attribute padding) 1557 85 ; Attribute type: AT_NEXT_REAUTH_ID 1558 16 ; Attribute length: 88 octets (22*4) 1559 00 51 ; Actual re-auth identity length: 81 octets 1560 59 32 34 66 4e 53 72 7a 38 42 50 32 37 34 6a 4f 1561 4a 61 46 31 37 57 66 78 49 38 59 4f 37 51 58 30 1562 30 70 4d 58 6b 39 58 4d 4d 56 4f 77 37 62 72 6f 1563 61 4e 68 54 63 7a 75 46 71 35 33 61 45 70 4f 6b 1564 6b 33 4c 30 64 6d 40 65 61 70 73 69 6d 2e 66 6f 1565 6f 1566 00 00 00 ; (attribute padding) 1567 06 ; Attribute type: AT_PADDING 1568 03 ; Attribute length: 12 octets (3*4) 1569 00 00 00 00 1570 00 00 00 00 1571 00 00 1572 1573*/ 1574const uint8_t at_encr_attr[] = { 1575 /* faked out to look like packet */ 1576 0x01, 1577 0x02, 1578 0x00, 0xb8, 1579 0x12, 1580 0x0b, 1581 0x00, 0x00, 1582 /* attrs */ 1583 0x84, 1584 0x13, 1585 0x00, 0x46, 1586 0x77, 0x38, 0x77, 0x34, 0x39, 0x50, 0x65, 0x78, 0x43, 0x61, 0x7a, 0x57, 0x4a, 0x26, 0x78, 0x43, 1587 0x49, 0x41, 0x52, 0x6d, 0x78, 0x75, 0x4d, 0x4b, 0x68, 0x74, 0x35, 0x53, 0x31, 0x73, 0x78, 0x52, 1588 0x44, 0x71, 0x58, 0x53, 0x45, 0x46, 0x42, 0x45, 0x67, 0x33, 0x44, 0x63, 0x5a, 0x50, 0x39, 0x63, 1589 0x49, 0x78, 0x54, 0x65, 0x35, 0x4a, 0x34, 0x4f, 0x79, 0x49, 0x77, 0x4e, 0x47, 0x56, 0x7a, 0x78, 1590 0x65, 0x4a, 0x4f, 0x55, 0x31, 0x47, 1591 0x00, 0x00, 1592 0x85, 1593 0x16, 1594 0x00, 0x51, 1595 0x59, 0x32, 0x34, 0x66, 0x4e, 0x53, 0x72, 0x7a, 0x38, 0x42, 0x50, 0x32, 0x37, 0x34, 0x6a, 0x4f, 1596 0x4a, 0x61, 0x46, 0x31, 0x37, 0x57, 0x66, 0x78, 0x49, 0x38, 0x59, 0x4f, 0x37, 0x51, 0x58, 0x30, 1597 0x30, 0x70, 0x4d, 0x58, 0x6b, 0x39, 0x58, 0x4d, 0x4d, 0x56, 0x4f, 0x77, 0x37, 0x62, 0x72, 0x6f, 1598 0x61, 0x4e, 0x68, 0x54, 0x63, 0x7a, 0x75, 0x46, 0x71, 0x35, 0x33, 0x61, 0x45, 0x70, 0x4f, 0x6b, 1599 0x6b, 0x33, 0x4c, 0x30, 0x64, 0x6d, 0x40, 0x65, 0x61, 0x70, 0x73, 0x69, 0x6d, 0x2e, 0x66, 0x6f, 1600 0x6f, 1601 0x00, 0x00, 0x00, 1602 0x06, 1603 0x03, 1604 0x00, 0x00, 0x00, 0x00, 1605 0x00, 0x00, 0x00, 0x00, 1606 0x00, 0x00, 1607}; 1608 1609const uint8_t at_permanent_id_req[] = { 1610 0x01, 1611 0x02, 1612 0x00, 0x0c, 1613 0x12, 1614 0x0b, 1615 0x00, 0x00, 1616 /* PERMANENT_ID_REQ */ 1617 0x0a, 1618 0x01, 1619 0x00, 0x00 1620}; 1621 1622const uint8_t bad_padding1[] = { 1623 0x01, 1624 0x02, 1625 0x00, 0x0f, 1626 0x12, 1627 0x0b, 1628 0x00, 0x00, 1629 /* PADDING */ 1630 0x06, 1631 0x03, 1632 0x00, 0x00, 0x00, 0x00, 1633 0x00, 0x00, 0x00, 0x00, 1634 0x00, 0x10, 1635 1636}; 1637 1638const uint8_t bad_padding2[] = { 1639 0x01, 1640 0x02, 1641 0x00, 0x14, 1642 0x12, 1643 0x0b, 1644 0x00, 0x00, 1645 /* PADDING */ 1646 0x06, 1647 0x03, 1648 0x00, 0x00, 0x00, 0x00, 1649 0x00, 0x00, 0x00, 0x00, 1650 0x00, 0x10, 1651 1652}; 1653 1654const uint8_t bad_padding3[] = { 1655 0x01, 1656 0x02, 1657 0x00, 0x18, 1658 0x12, 1659 0x0b, 1660 0x00, 0x00, 1661 /* PADDING */ 1662 0x06, 1663 0x04, 1664 0x00, 0x00, 0x00, 0x00, 1665 0x00, 0x00, 0x00, 0x00, 1666 0x00, 0x00, 0x00, 0x00, 1667 0x00, 0x00 1668}; 1669 1670const uint8_t bad_at_encr_attr[] = { 1671 /* faked out to look like packet */ 1672 0x01, 1673 0x02, 1674 0x00, 0xb8, 1675 0x12, 1676 0x0b, 1677 0x00, 0x00, 1678 /* attrs */ 1679 0x84, 1680 0x13, 1681 0x00, 0x4a, 1682 0x77, 0x38, 0x77, 0x34, 0x39, 0x50, 0x65, 0x78, 0x43, 0x61, 0x7a, 0x57, 0x4a, 0x26, 0x78, 0x43, 1683 0x49, 0x41, 0x52, 0x6d, 0x78, 0x75, 0x4d, 0x4b, 0x68, 0x74, 0x35, 0x53, 0x31, 0x73, 0x78, 0x52, 1684 0x44, 0x71, 0x58, 0x53, 0x45, 0x46, 0x42, 0x45, 0x67, 0x33, 0x44, 0x63, 0x5a, 0x50, 0x39, 0x63, 1685 0x49, 0x78, 0x54, 0x65, 0x35, 0x4a, 0x34, 0x4f, 0x79, 0x49, 0x77, 0x4e, 0x47, 0x56, 0x7a, 0x78, 1686 0x65, 0x4a, 0x4f, 0x55, 0x31, 0x47, 1687 0x00, 0x00, 1688 0x85, 1689 0x16, 1690 0x00, 0x51, 1691 0x59, 0x32, 0x34, 0x66, 0x4e, 0x53, 0x72, 0x7a, 0x38, 0x42, 0x50, 0x32, 0x37, 0x34, 0x6a, 0x4f, 1692 0x4a, 0x61, 0x46, 0x31, 0x37, 0x57, 0x66, 0x78, 0x49, 0x38, 0x59, 0x4f, 0x37, 0x51, 0x58, 0x30, 1693 0x30, 0x70, 0x4d, 0x58, 0x6b, 0x39, 0x58, 0x4d, 0x4d, 0x56, 0x4f, 0x77, 0x37, 0x62, 0x72, 0x6f, 1694 0x61, 0x4e, 0x68, 0x54, 0x63, 0x7a, 0x75, 0x46, 0x71, 0x35, 0x33, 0x61, 0x45, 0x70, 0x4f, 0x6b, 1695 0x6b, 0x33, 0x4c, 0x30, 0x64, 0x6d, 0x40, 0x65, 0x61, 0x70, 0x73, 0x69, 0x6d, 0x2e, 0x66, 0x6f, 1696 0x6f, 1697 0x00, 0x00, 0x00, 1698 0x06, 1699 0x03, 1700 0x00, 0x00, 0x00, 0x00, 1701 0x00, 0x00, 0x00, 0x00, 1702 0x00, 0x00, 1703}; 1704 1705struct { 1706 const uint8_t * packet; 1707 int size; 1708 bool good; 1709 const char * name; 1710} packets[] = { 1711 { eap_request_sim_start, sizeof(eap_request_sim_start), TRUE, "eap_request_sim_start" }, 1712 { eap_response_sim_start, sizeof(eap_response_sim_start), TRUE, "eap_response_sim_start" }, 1713 { eap_request_fast_reauth, sizeof(eap_request_fast_reauth), TRUE, "eap_request_fast_reauth" }, 1714 { at_encr_attr, sizeof(at_encr_attr), TRUE, "at_encr_attr" }, 1715 { at_permanent_id_req, sizeof(at_permanent_id_req), TRUE, "at_permanent_id_req" }, 1716 { bad_padding1, sizeof(bad_padding1), FALSE, "bad_padding1" }, 1717 { bad_padding2, sizeof(bad_padding2), FALSE, "bad_padding2" }, 1718 { bad_padding3, sizeof(bad_padding3), FALSE, "bad_padding3" }, 1719 { bad_at_encr_attr, sizeof(bad_at_encr_attr), FALSE, "bad_at_encr_attr" }, 1720 { NULL, 0 } 1721}; 1722 1723int 1724main(int argc, char * argv[]) 1725{ 1726 AttrUnion attr; 1727 int i; 1728 EAPSIMPacketRef pkt; 1729 uint8_t buf[1028]; 1730 TLVBufferDeclare( tlv_buf_p); 1731 1732 for (i = 0; packets[i].packet != NULL; i++) { 1733 bool good; 1734 1735 pkt = (EAPSIMPacketRef)packets[i].packet; 1736 good = EAPSIMAKAPacketDump(stdout, (EAPPacketRef)pkt); 1737 printf("Test %d '%s' %s (found%serrors)\n", i, 1738 packets[i].name, 1739 good == packets[i].good ? "PASSED" : "FAILED", 1740 !good ? " " : " no "); 1741 printf("\n"); 1742 } 1743 pkt = (EAPSIMPacketRef)buf; 1744 TLVBufferInit(tlv_buf_p, pkt->attrs, 1745 sizeof(buf) - offsetof(EAPSIMPacket, attrs)); 1746 attr.tlv_p = TLVBufferAllocateTLV(tlv_buf_p, kAT_SELECTED_VERSION, 1747 sizeof(AT_SELECTED_VERSION)); 1748 if (attr.tlv_p == NULL) { 1749 fprintf(stderr, "failed allocating AT_SELECTED_VERSION, %s\n", 1750 TLVBufferErrorString(tlv_buf_p)); 1751 exit(2); 1752 } 1753 net_uint16_set(attr.at_selected_version->sv_selected_version, 1754 kEAPSIMVersion1); 1755 pkt->code = kEAPCodeResponse; 1756 pkt->identifier = 1; 1757 pkt->type = kEAPTypeEAPSIM; 1758 pkt->subtype = kEAPSIMAKAPacketSubtypeSIMStart; 1759 EAPPacketSetLength((EAPPacketRef)pkt, 1760 offsetof(EAPSIMPacket, attrs) 1761 + TLVBufferUsed(tlv_buf_p)); 1762 if (EAPSIMAKAPacketDump(stdout, (EAPPacketRef)pkt) == FALSE) { 1763 fprintf(stderr, "Parse failed!\n"); 1764 exit(2); 1765 } 1766 1767 exit(0); 1768 return (0); 1769} 1770 1771#endif /* TEST_TLVLIST_PARSE */ 1772 1773#ifdef TEST_SIM_CRYPTO 1774#include <CommonCrypto/CommonDigest.h> 1775#include <CommonCrypto/CommonCryptor.h> 1776#include <CommonCrypto/CommonHMAC.h> 1777#include <CoreFoundation/CFPropertyList.h> 1778#include "fips186prf.h" 1779 1780typedef struct { 1781 uint8_t Kc[SIM_KC_SIZE]; 1782} SIMKc, *SIMKcRef; 1783 1784typedef struct { 1785 uint8_t SRES[SIM_SRES_SIZE]; 1786} SIMSRES, *SIMSRESRef; 1787 1788typedef struct { 1789 uint8_t RAND[SIM_RAND_SIZE]; 1790} SIMRAND, *SIMRANDRef; 1791 1792/* 1793 A.5. EAP-Request/SIM/Challenge 1794 1795 Next, the server selects three authentication triplets 1796 1797 (RAND1,SRES1,Kc1) = (10111213 14151617 18191a1b 1c1d1e1f, 1798 d1d2d3d4, 1799 a0a1a2a3 a4a5a6a7) 1800 (RAND2,SRES2,Kc2) = (20212223 24252627 28292a2b 2c2d2e2f, 1801 e1e2e3e4, 1802 b0b1b2b3 b4b5b6b7) 1803 (RAND3,SRES3,Kc3) = (30313233 34353637 38393a3b 3c3d3e3f, 1804 f1f2f3f4, 1805 c0c1c2c3 c4c5c6c7) 1806*/ 1807 1808const SIMKc test_kc[EAPSIM_MAX_RANDS] = { 1809 { { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 } }, 1810 { { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 } }, 1811 { { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 } }, 1812}; 1813 1814const SIMSRES test_sres[EAPSIM_MAX_RANDS] = { 1815 { { 0xd1, 0xd2, 0xd3, 0xd4 } }, 1816 { { 0xe1, 0xe2, 0xe3, 0xe4 } }, 1817 { { 0xf1, 0xf2, 0xf3, 0xf4 } } 1818}; 1819 1820const SIMRAND test_rand[EAPSIM_MAX_RANDS] = { 1821 { { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 1822 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f } }, 1823 { { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 1824 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f } } , 1825 { { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 1826 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f } } 1827}; 1828 1829const uint8_t test_nonce_mt[NONCE_MT_SIZE] = { 1830 0x01, 0x23, 0x45, 0x67, 1831 0x89, 0xab, 0xcd, 0xef, 1832 0xfe, 0xdc, 0xba, 0x98, 1833 0x76, 0x54, 0x32, 0x10 1834}; 1835const uint8_t test_identity[] = "1244070100000001@eapsim.foo"; 1836 1837/* 1838 Next, the MK is calculated as specified in Section 7*. 1839 1840 MK = e576d5ca 332e9930 018bf1ba ee2763c7 95b3c712 1841 1842 And the other keys are derived using the PRNG: 1843 1844 K_encr = 536e5ebc 4465582a a6a8ec99 86ebb620 1845 K_aut = 25af1942 efcbf4bc 72b39434 21f2a974 1846 MSK = 39d45aea f4e30601 983e972b 6cfd46d1 1847 c3637733 65690d09 cd44976b 525f47d3 1848 a60a985e 955c53b0 90b2e4b7 3719196a 1849 40254296 8fd14a88 8f46b9a7 886e4488 1850 EMSK = 5949eab0 fff69d52 315c6c63 4fd14a7f 1851 0d52023d 56f79698 fa6596ab eed4f93f 1852 bb48eb53 4d985414 ceed0d9a 8ed33c38 1853 7c9dfdab 92ffbdf2 40fcecf6 5a2c93b9 1854*/ 1855 1856const uint8_t test_mk[CC_SHA1_DIGEST_LENGTH] = { 1857 0xe5, 0x76, 0xd5, 0xca, 1858 0x33, 0x2e, 0x99, 0x30, 1859 0x01, 0x8b, 0xf1, 0xba, 1860 0xee, 0x27, 0x63, 0xc7, 1861 0x95, 0xb3, 0xc7, 0x12 1862}; 1863 1864#define EAPSIMAKA_KEY_SIZE (EAPSIMAKA_K_ENCR_SIZE + EAPSIMAKA_K_AUT_SIZE \ 1865 + EAPSIMAKA_MSK_SIZE + EAPSIMAKA_EMSK_SIZE) 1866 1867uint8_t key_block[EAPSIMAKA_KEY_SIZE] = { 1868 0x53, 0x6e, 0x5e, 0xbc, 0x44, 0x65, 0x58, 0x2a, 0xa6, 0xa8, 0xec, 0x99, 0x86, 0xeb, 0xb6, 0x20, 1869 0x25, 0xaf, 0x19, 0x42, 0xef, 0xcb, 0xf4, 0xbc, 0x72, 0xb3, 0x94, 0x34, 0x21, 0xf2, 0xa9, 0x74, 1870 0x39, 0xd4, 0x5a, 0xea, 0xf4, 0xe3, 0x06, 0x01, 0x98, 0x3e, 0x97, 0x2b, 0x6c, 0xfd, 0x46, 0xd1, 1871 0xc3, 0x63, 0x77, 0x33, 0x65, 0x69, 0x0d, 0x09, 0xcd, 0x44, 0x97, 0x6b, 0x52, 0x5f, 0x47, 0xd3, 1872 0xa6, 0x0a, 0x98, 0x5e, 0x95, 0x5c, 0x53, 0xb0, 0x90, 0xb2, 0xe4, 0xb7, 0x37, 0x19, 0x19, 0x6a, 1873 0x40, 0x25, 0x42, 0x96, 0x8f, 0xd1, 0x4a, 0x88, 0x8f, 0x46, 0xb9, 0xa7, 0x88, 0x6e, 0x44, 0x88, 1874 0x59, 0x49, 0xea, 0xb0, 0xff, 0xf6, 0x9d, 0x52, 0x31, 0x5c, 0x6c, 0x63, 0x4f, 0xd1, 0x4a, 0x7f, 1875 0x0d, 0x52, 0x02, 0x3d, 0x56, 0xf7, 0x96, 0x98, 0xfa, 0x65, 0x96, 0xab, 0xee, 0xd4, 0xf9, 0x3f, 1876 0xbb, 0x48, 0xeb, 0x53, 0x4d, 0x98, 0x54, 0x14, 0xce, 0xed, 0x0d, 0x9a, 0x8e, 0xd3, 0x3c, 0x38, 1877 0x7c, 0x9d, 0xfd, 0xab, 0x92, 0xff, 0xbd, 0xf2, 0x40, 0xfc, 0xec, 0xf6, 0x5a, 0x2c, 0x93, 0xb9, 1878}; 1879 1880const uint8_t test_version_list[2] = { 0x0, 0x1 }; 1881const uint8_t test_selected_version[2] = { 0x0, 0x1 }; 1882 1883const uint8_t test_packet[] = { 1884 0x01, /* code = 1 (request) */ 1885 0x37, /* identifier = 55 */ 1886 0x00, 0x50, /* length = 0x50 = 80 */ 1887 0x12, /* type = 0x12 = 18 = EAP-SIM */ 1888 0x0b, /* subtype = 0x0b = 11 = Challenge */ 1889 0x00, 0x00, /* reserved */ 1890 1891 /* AT_RAND */ 1892 0x01, 1893 0x0d, /* 0x0d (13) * 4 = 52 bytes */ 1894 0x00, 0x00, /* reserved */ 1895 0x10, 0x11, 0x12, 0x13, 1896 0x14, 0x15, 0x16, 0x17, 1897 0x18, 0x19, 0x1a, 0x1b, 1898 0x1c, 0x1d, 0x1e, 0x1f, 1899 0x20, 0x21, 0x22, 0x23, 1900 0x24, 0x25, 0x26, 0x27, 1901 0x28, 0x29, 0x2a, 0x2b, 1902 0x2c, 0x2d, 0x2e, 0x2f, 1903 0x30, 0x31, 0x32, 0x33, 1904 0x34, 0x35, 0x36, 0x37, 1905 0x38, 0x39, 0x3a, 0x3b, 1906 0x3c, 0x3d, 0x3e, 0x3f, 1907 1908 /* AT_MAC */ 1909 0x0b, 1910 0x05, /* 0x05 * 4 = 20 bytes */ 1911 0x00, 0x00, /* padding */ 1912 0x00, 0x97, 0xc3, 0x64, 1913 0xf8, 0x43, 0x1d, 0xa4, 1914 0x92, 0x5b, 0xb2, 0xb1, 1915 0x95, 0xd0, 0xbe, 0x22 1916}; 1917 1918static void 1919dump_plist(FILE * f, CFTypeRef p) 1920{ 1921 CFDataRef data; 1922 data = CFPropertyListCreateXMLData(NULL, p); 1923 if (data == NULL) { 1924 return; 1925 } 1926 fwrite(CFDataGetBytePtr(data), CFDataGetLength(data), 1, f); 1927 CFRelease(data); 1928 return; 1929} 1930 1931static void 1932dump_triplets(void) 1933{ 1934 CFMutableDictionaryRef dict; 1935 int i; 1936 CFMutableArrayRef array; 1937 1938 dict = CFDictionaryCreateMutable(NULL, 0, 1939 &kCFTypeDictionaryKeyCallBacks, 1940 &kCFTypeDictionaryValueCallBacks); 1941 1942 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1943 for (i = 0; i < EAPSIM_MAX_RANDS; i++) { 1944 CFDataRef data; 1945 1946 data = CFDataCreateWithBytesNoCopy(NULL, test_kc[i].Kc, SIM_KC_SIZE, 1947 kCFAllocatorNull); 1948 CFArrayAppendValue(array, data); 1949 CFRelease(data); 1950 } 1951 CFDictionarySetValue(dict, CFSTR("KcList"), array); 1952 CFRelease(array); 1953 1954 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1955 for (i = 0; i < EAPSIM_MAX_RANDS; i++) { 1956 CFDataRef data; 1957 1958 data = CFDataCreateWithBytesNoCopy(NULL, test_sres[i].SRES, 1959 SIM_SRES_SIZE, 1960 kCFAllocatorNull); 1961 CFArrayAppendValue(array, data); 1962 CFRelease(data); 1963 } 1964 CFDictionarySetValue(dict, CFSTR("SRESList"), array); 1965 CFRelease(array); 1966 1967 array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1968 for (i = 0; i < EAPSIM_MAX_RANDS; i++) { 1969 CFDataRef data; 1970 1971 data = CFDataCreateWithBytesNoCopy(NULL, test_rand[i].RAND, 1972 SIM_RAND_SIZE, 1973 kCFAllocatorNull); 1974 CFArrayAppendValue(array, data); 1975 CFRelease(data); 1976 } 1977 CFDictionarySetValue(dict, CFSTR("RANDList"), array); 1978 CFRelease(array); 1979 1980 dump_plist(stdout, dict); 1981 CFRelease(dict); 1982 return; 1983} 1984 1985 1986const uint8_t attrs_plaintext[] = { 1987 0x84, 1988 0x13, 1989 0x00, 0x46, 1990 0x77, 0x38, 0x77, 0x34, 0x39, 0x50, 0x65, 0x78, 0x43, 0x61, 0x7a, 0x57, 0x4a, 0x26, 0x78, 0x43, 1991 0x49, 0x41, 0x52, 0x6d, 0x78, 0x75, 0x4d, 0x4b, 0x68, 0x74, 0x35, 0x53, 0x31, 0x73, 0x78, 0x52, 1992 0x44, 0x71, 0x58, 0x53, 0x45, 0x46, 0x42, 0x45, 0x67, 0x33, 0x44, 0x63, 0x5a, 0x50, 0x39, 0x63, 1993 0x49, 0x78, 0x54, 0x65, 0x35, 0x4a, 0x34, 0x4f, 0x79, 0x49, 0x77, 0x4e, 0x47, 0x56, 0x7a, 0x78, 1994 0x65, 0x4a, 0x4f, 0x55, 0x31, 0x47, 1995 0x00, 0x00, 1996 0x85, 1997 0x16, 1998 0x00, 0x51, 1999 0x59, 0x32, 0x34, 0x66, 0x4e, 0x53, 0x72, 0x7a, 0x38, 0x42, 0x50, 0x32, 0x37, 0x34, 0x6a, 0x4f, 2000 0x4a, 0x61, 0x46, 0x31, 0x37, 0x57, 0x66, 0x78, 0x49, 0x38, 0x59, 0x4f, 0x37, 0x51, 0x58, 0x30, 2001 0x30, 0x70, 0x4d, 0x58, 0x6b, 0x39, 0x58, 0x4d, 0x4d, 0x56, 0x4f, 0x77, 0x37, 0x62, 0x72, 0x6f, 2002 0x61, 0x4e, 0x68, 0x54, 0x63, 0x7a, 0x75, 0x46, 0x71, 0x35, 0x33, 0x61, 0x45, 0x70, 0x4f, 0x6b, 2003 0x6b, 0x33, 0x4c, 0x30, 0x64, 0x6d, 0x40, 0x65, 0x61, 0x70, 0x73, 0x69, 0x6d, 0x2e, 0x66, 0x6f, 2004 0x6f, 2005 0x00, 0x00, 0x00, 2006 0x06, 2007 0x03, 2008 0x00, 0x00, 0x00, 0x00, 2009 0x00, 0x00, 0x00, 0x00, 2010 0x00, 0x00 2011}; 2012 2013const static uint8_t attrs_encrypted[] = { 2014 0x55, 0xf2, 0x93, 0x9b, 0xbd, 0xb1, 0xb1, 0x9e, 2015 0xa1, 0xb4, 0x7f, 0xc0, 0xb3, 0xe0, 0xbe, 0x4c, 2016 0xab, 0x2c, 0xf7, 0x37, 0x2d, 0x98, 0xe3, 0x02, 2017 0x3c, 0x6b, 0xb9, 0x24, 0x15, 0x72, 0x3d, 0x58, 2018 0xba, 0xd6, 0x6c, 0xe0, 0x84, 0xe1, 0x01, 0xb6, 2019 0x0f, 0x53, 0x58, 0x35, 0x4b, 0xd4, 0x21, 0x82, 2020 0x78, 0xae, 0xa7, 0xbf, 0x2c, 0xba, 0xce, 0x33, 2021 0x10, 0x6a, 0xed, 0xdc, 0x62, 0x5b, 0x0c, 0x1d, 2022 0x5a, 0xa6, 0x7a, 0x41, 0x73, 0x9a, 0xe5, 0xb5, 2023 0x79, 0x50, 0x97, 0x3f, 0xc7, 0xff, 0x83, 0x01, 2024 0x07, 0x3c, 0x6f, 0x95, 0x31, 0x50, 0xfc, 0x30, 2025 0x3e, 0xa1, 0x52, 0xd1, 0xe1, 0x0a, 0x2d, 0x1f, 2026 0x4f, 0x52, 0x26, 0xda, 0xa1, 0xee, 0x90, 0x05, 2027 0x47, 0x22, 0x52, 0xbd, 0xb3, 0xb7, 0x1d, 0x6f, 2028 0x0c, 0x3a, 0x34, 0x90, 0x31, 0x6c, 0x46, 0x92, 2029 0x98, 0x71, 0xbd, 0x45, 0xcd, 0xfd, 0xbc, 0xa6, 2030 0x11, 0x2f, 0x07, 0xf8, 0xbe, 0x71, 0x79, 0x90, 2031 0xd2, 0x5f, 0x6d, 0xd7, 0xf2, 0xb7, 0xb3, 0x20, 2032 0xbf, 0x4d, 0x5a, 0x99, 0x2e, 0x88, 0x03, 0x31, 2033 0xd7, 0x29, 0x94, 0x5a, 0xec, 0x75, 0xae, 0x5d, 2034 0x43, 0xc8, 0xed, 0xa5, 0xfe, 0x62, 0x33, 0xfc, 2035 0xac, 0x49, 0x4e, 0xe6, 0x7a, 0x0d, 0x50, 0x4d 2036}; 2037 2038const static uint8_t test_iv[] = { 2039 0x9e, 0x18, 0xb0, 0xc2, 2040 0x9a, 0x65, 0x22, 0x63, 2041 0xc0, 0x6e, 0xfb, 0x54, 2042 0xdd, 0x00, 0xa8, 0x95 2043}; 2044 2045static void 2046test_encr_data(void) 2047{ 2048 uint8_t buf[sizeof(attrs_encrypted)]; 2049 size_t buf_used; 2050 CCCryptorRef cryptor; 2051 EAPSIMAKAKeyInfoRef key_info_p = (EAPSIMAKAKeyInfoRef)key_block; 2052 CCCryptorStatus status; 2053 2054 status = CCCryptorCreate(kCCEncrypt, 2055 kCCAlgorithmAES128, 2056 0, 2057 key_info_p->s.k_encr, 2058 sizeof(key_info_p->s.k_encr), 2059 test_iv, 2060 &cryptor); 2061 if (status != kCCSuccess) { 2062 fprintf(stderr, "CCCryptoCreate failed with %d\n", 2063 status); 2064 return; 2065 } 2066 status = CCCryptorUpdate(cryptor, 2067 attrs_plaintext, 2068 sizeof(attrs_plaintext), 2069 buf, 2070 sizeof(buf), 2071 &buf_used); 2072 if (status != kCCSuccess) { 2073 fprintf(stderr, "CCCryptoUpdate failed with %d\n", 2074 status); 2075 goto done; 2076 } 2077 if (buf_used != sizeof(buf)) { 2078 fprintf(stderr, "buf consumed %d, should have been %d\n", 2079 (int)buf_used, (int)sizeof(buf)); 2080 goto done; 2081 } 2082 2083 if (bcmp(attrs_encrypted, buf, sizeof(attrs_encrypted))) { 2084 fprintf(stderr, "encryption yielded different results\n"); 2085 goto done; 2086 } 2087 fprintf(stderr, "encryption matches!\n"); 2088 2089 done: 2090 status = CCCryptorRelease(cryptor); 2091 if (status != kCCSuccess) { 2092 fprintf(stderr, "CCCryptoRelease failed with %d\n", 2093 status); 2094 return; 2095 } 2096 return; 2097} 2098 2099static void 2100test_decrypt_data(void) 2101{ 2102 uint8_t buf[sizeof(attrs_encrypted)]; 2103 size_t buf_used; 2104 CCCryptorRef cryptor; 2105 EAPSIMAKAKeyInfoRef key_info_p = (EAPSIMAKAKeyInfoRef)key_block; 2106 CCCryptorStatus status; 2107 2108 status = CCCryptorCreate(kCCDecrypt, 2109 kCCAlgorithmAES128, 2110 0, 2111 key_info_p->s.k_encr, 2112 sizeof(key_info_p->s.k_encr), 2113 test_iv, 2114 &cryptor); 2115 if (status != kCCSuccess) { 2116 fprintf(stderr, "CCCryptoCreate failed with %d\n", 2117 status); 2118 return; 2119 } 2120 status = CCCryptorUpdate(cryptor, 2121 attrs_encrypted, 2122 sizeof(attrs_encrypted), 2123 buf, 2124 sizeof(buf), 2125 &buf_used); 2126 if (status != kCCSuccess) { 2127 fprintf(stderr, "CCCryptoUpdate failed with %d\n", 2128 status); 2129 goto done; 2130 } 2131 if (buf_used != sizeof(buf)) { 2132 fprintf(stderr, "buf consumed %d, should have been %d\n", 2133 (int)buf_used, (int)sizeof(buf)); 2134 goto done; 2135 } 2136 2137 if (bcmp(attrs_plaintext, buf, sizeof(attrs_plaintext))) { 2138 fprintf(stderr, "decryption yielded different results\n"); 2139 goto done; 2140 } 2141 fprintf(stderr, "decryption matches!\n"); 2142 2143 done: 2144 status = CCCryptorRelease(cryptor); 2145 if (status != kCCSuccess) { 2146 fprintf(stderr, "CCCryptoRelease failed with %d\n", 2147 status); 2148 return; 2149 } 2150 return; 2151} 2152 2153int 2154main(int argc, char * argv[]) 2155{ 2156 int attrs_length; 2157 CC_SHA1_CTX context; 2158 EAPSIMPacketRef eapsim; 2159 uint8_t hash[CC_SHA1_DIGEST_LENGTH]; 2160 EAPSIMAKAKeyInfo key_info; 2161 AT_MAC * mac_p; 2162 uint8_t mk[CC_SHA1_DIGEST_LENGTH]; 2163 TLVListDeclare( tlvs_p); 2164 2165 /* MK = SHA1(Identity|n*Kc| NONCE_MT| Version List| Selected Version) */ 2166 CC_SHA1_Init(&context); 2167 CC_SHA1_Update(&context, test_identity, sizeof(test_identity) - 1); 2168 CC_SHA1_Update(&context, test_kc, sizeof(test_kc)); 2169 CC_SHA1_Update(&context, test_nonce_mt, sizeof(test_nonce_mt)); 2170 CC_SHA1_Update(&context, test_version_list, sizeof(test_version_list)); 2171 CC_SHA1_Update(&context, test_selected_version, 2172 sizeof(test_selected_version)); 2173 CC_SHA1_Final(mk, &context); 2174 2175 if (bcmp(mk, test_mk, sizeof(test_mk))) { 2176 fprintf(stderr, "The mk values are different\n"); 2177 printf("Computed:\n"); 2178 print_data(mk, sizeof(mk)); 2179 printf("Desired:\n"); 2180 print_data((void *)test_mk, sizeof(test_mk)); 2181 } 2182 else { 2183 printf("The MK values are the same!\n"); 2184 printf("Computed:\n"); 2185 print_data(mk, sizeof(mk)); 2186 printf("Desired:\n"); 2187 print_data((void *)test_mk, sizeof(test_mk)); 2188 } 2189 2190 /* now run PRF to generate keying material */ 2191 fips186_2prf(mk, key_info.key); 2192 2193 /* make sure the key blocks are the same */ 2194 if (bcmp(key_info.key, key_block, sizeof(key_info.key))) { 2195 fprintf(stderr, "key blocks are different!\n"); 2196 exit(1); 2197 } 2198 else { 2199 printf("key blocks match\n"); 2200 } 2201 2202 if (EAPSIMAKAPacketDump(stdout, (EAPPacketRef)test_packet) == FALSE) { 2203 fprintf(stderr, "packet is bad\n"); 2204 exit(1); 2205 } 2206 2207 eapsim = (EAPSIMPacketRef)test_packet; 2208 attrs_length = EAPPacketGetLength((EAPPacketRef)eapsim) 2209 - kEAPSIMAKAPacketHeaderLength; 2210 TLVListInit(tlvs_p); 2211 if (TLVListParse(tlvs_p, eapsim->attrs, attrs_length) == FALSE) { 2212 fprintf(stderr, "failed to parse TLVs: %s\n", 2213 TLVListErrorString(tlvs_p)); 2214 exit(1); 2215 } 2216 mac_p = (AT_MAC *)TLVListLookupAttribute(tlvs_p, kAT_MAC); 2217 if (mac_p == NULL) { 2218 fprintf(stderr, "Challenge is missing AT_MAC\n"); 2219 exit(1); 2220 } 2221 EAPSIMAKAKeyInfoComputeMAC(&key_info, (EAPPacketRef)test_packet, 2222 mac_p->ma_mac, 2223 test_nonce_mt, sizeof(test_nonce_mt), 2224 hash); 2225 if (bcmp(hash, mac_p->ma_mac, MAC_SIZE) != 0) { 2226 print_data(hash, sizeof(hash)); 2227 fprintf(stderr, "AT_MAC mismatch\n"); 2228 exit(1); 2229 } 2230 else { 2231 printf("AT_MAC is good\n"); 2232 } 2233 2234 dump_triplets(); 2235 test_encr_data(); 2236 test_decrypt_data(); 2237 exit(0); 2238 return (0); 2239} 2240 2241#endif /* TEST_SIM_CRYPTO */ 2242