1// 2// SSLRecordInternal.c 3// Security 4// 5// Created by Fabrice Gautier on 10/25/11. 6// Copyright (c) 2011 Apple, Inc. All rights reserved. 7// 8 9/* THIS FILE CONTAINS KERNEL CODE */ 10 11#include "sslBuildFlags.h" 12#include "SSLRecordInternal.h" 13#include "sslDebug.h" 14#include "cipherSpecs.h" 15#include "symCipher.h" 16#include "sslUtils.h" 17#include "tls_record.h" 18 19#include <AssertMacros.h> 20#include <string.h> 21 22#include <inttypes.h> 23 24#define DEFAULT_BUFFER_SIZE 4096 25 26 27/* 28 * Redirect SSLBuffer-based I/O call to user-supplied I/O. 29 */ 30static 31int sslIoRead(SSLBuffer buf, 32 size_t *actualLength, 33 struct SSLRecordInternalContext *ctx) 34{ 35 size_t dataLength = buf.length; 36 int ortn; 37 38 *actualLength = 0; 39 ortn = (ctx->read)(ctx->ioRef, 40 buf.data, 41 &dataLength); 42 *actualLength = dataLength; 43 return ortn; 44} 45 46static 47int sslIoWrite(SSLBuffer buf, 48 size_t *actualLength, 49 struct SSLRecordInternalContext *ctx) 50{ 51 size_t dataLength = buf.length; 52 int ortn; 53 54 *actualLength = 0; 55 ortn = (ctx->write)(ctx->ioRef, 56 buf.data, 57 &dataLength); 58 *actualLength = dataLength; 59 return ortn; 60} 61 62 63static int 64SSLDisposeCipherSuite(CipherContext *cipher, struct SSLRecordInternalContext *ctx) 65{ int err; 66 67 /* symmetric encryption context */ 68 if(cipher->symCipher) { 69 if ((err = cipher->symCipher->finish(cipher->cipherCtx)) != 0) { 70 return err; 71 } 72 } 73 74 /* per-record hash/hmac context */ 75 ctx->sslTslCalls->freeMac(cipher); 76 77 return 0; 78} 79 80 81 82/* common for sslv3 and tlsv1, except for the computeMac callout */ 83int SSLVerifyMac(uint8_t type, 84 SSLBuffer *data, 85 uint8_t *compareMAC, 86 struct SSLRecordInternalContext *ctx) 87{ 88 int err; 89 uint8_t macData[SSL_MAX_DIGEST_LEN]; 90 SSLBuffer secret, mac; 91 92 secret.data = ctx->readCipher.macSecret; 93 secret.length = ctx->readCipher.macRef->hash->digestSize; 94 mac.data = macData; 95 mac.length = ctx->readCipher.macRef->hash->digestSize; 96 97 check(ctx->sslTslCalls != NULL); 98 if ((err = ctx->sslTslCalls->computeMac(type, 99 *data, 100 mac, 101 &ctx->readCipher, 102 ctx->readCipher.sequenceNum, 103 ctx)) != 0) 104 return err; 105 106 if ((memcmp(mac.data, compareMAC, mac.length)) != 0) { 107 sslErrorLog("SSLVerifyMac: Mac verify failure\n"); 108 return errSSLRecordProtocol; 109 } 110 return 0; 111} 112 113#include "cipherSpecs.h" 114#include "symCipher.h" 115 116static const HashHmacReference *sslCipherSuiteGetHashHmacReference(uint16_t selectedCipher) 117{ 118 HMAC_Algs alg = sslCipherSuiteGetMacAlgorithm(selectedCipher); 119 120 switch (alg) { 121 case HA_Null: 122 return &HashHmacNull; 123 case HA_MD5: 124 return &HashHmacMD5; 125 case HA_SHA1: 126 return &HashHmacSHA1; 127 case HA_SHA256: 128 return &HashHmacSHA256; 129 case HA_SHA384: 130 return &HashHmacSHA384; 131 default: 132 sslErrorLog("Invalid hashAlgorithm %d", alg); 133 check(0); 134 return &HashHmacNull; 135 } 136} 137 138static const SSLSymmetricCipher *sslCipherSuiteGetSymmetricCipher(uint16_t selectedCipher) 139{ 140 141 SSL_CipherAlgorithm alg = sslCipherSuiteGetSymmetricCipherAlgorithm(selectedCipher); 142 switch(alg) { 143 case SSL_CipherAlgorithmNull: 144 return &SSLCipherNull; 145#if ENABLE_RC2 146 case SSL_CipherAlgorithmRC2_128: 147 return &SSLCipherRC2_128; 148#endif 149#if ENABLE_RC4 150 case SSL_CipherAlgorithmRC4_128: 151 return &SSLCipherRC4_128; 152#endif 153#if ENABLE_DES 154 case SSL_CipherAlgorithmDES_CBC: 155 return &SSLCipherDES_CBC; 156#endif 157 case SSL_CipherAlgorithm3DES_CBC: 158 return &SSLCipher3DES_CBC; 159 case SSL_CipherAlgorithmAES_128_CBC: 160 return &SSLCipherAES_128_CBC; 161 case SSL_CipherAlgorithmAES_256_CBC: 162 return &SSLCipherAES_256_CBC; 163#if ENABLE_AES_GCM 164 case SSL_CipherAlgorithmAES_128_GCM: 165 return &SSLCipherAES_128_GCM; 166 case SSL_CipherAlgorithmAES_256_GCM: 167 return &SSLCipherAES_256_GCM; 168#endif 169 default: 170 check(0); 171 return &SSLCipherNull; 172 } 173} 174 175static void InitCipherSpec(struct SSLRecordInternalContext *ctx, uint16_t selectedCipher) 176{ 177 SSLRecordCipherSpec *dst = &ctx->selectedCipherSpec; 178 179 ctx->selectedCipher = selectedCipher; 180 dst->cipher = sslCipherSuiteGetSymmetricCipher(selectedCipher); 181 dst->macAlgorithm = sslCipherSuiteGetHashHmacReference(selectedCipher); 182}; 183 184/* Entry points to Record Layer */ 185 186static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec) 187{ int err; 188 size_t len, contentLen; 189 uint8_t *charPtr; 190 SSLBuffer readData, cipherFragment; 191 size_t head=5; 192 int skipit=0; 193 struct SSLRecordInternalContext *ctx = ref; 194 195 if(ctx->isDTLS) 196 head+=8; 197 198 if (!ctx->partialReadBuffer.data || ctx->partialReadBuffer.length < head) 199 { if (ctx->partialReadBuffer.data) 200 if ((err = SSLFreeBuffer(&ctx->partialReadBuffer)) != 0) 201 { 202 return err; 203 } 204 if ((err = SSLAllocBuffer(&ctx->partialReadBuffer, 205 DEFAULT_BUFFER_SIZE)) != 0) 206 { 207 return err; 208 } 209 } 210 211 if (ctx->negProtocolVersion == SSL_Version_Undetermined) { 212 if (ctx->amountRead < 1) 213 { readData.length = 1 - ctx->amountRead; 214 readData.data = ctx->partialReadBuffer.data + ctx->amountRead; 215 len = readData.length; 216 err = sslIoRead(readData, &len, ctx); 217 if(err != 0) 218 { if (err == errSSLRecordWouldBlock) { 219 ctx->amountRead += len; 220 return err; 221 } 222 else { 223 /* abort */ 224 err = errSSLRecordClosedAbort; 225#if 0 // TODO: revisit this in the transport layer 226 if((ctx->protocolSide == kSSLClientSide) && 227 (ctx->amountRead == 0) && 228 (len == 0)) { 229 /* 230 * Detect "server refused to even try to negotiate" 231 * error, when the server drops the connection before 232 * sending a single byte. 233 */ 234 switch(ctx->state) { 235 case SSL_HdskStateServerHello: 236 sslHdskStateDebug("Server dropped initial connection\n"); 237 err = errSSLConnectionRefused; 238 break; 239 default: 240 break; 241 } 242 } 243#endif 244 return err; 245 } 246 } 247 ctx->amountRead += len; 248 } 249 } 250 251 if (ctx->amountRead < head) 252 { readData.length = head - ctx->amountRead; 253 readData.data = ctx->partialReadBuffer.data + ctx->amountRead; 254 len = readData.length; 255 err = sslIoRead(readData, &len, ctx); 256 if(err != 0) 257 { 258 switch(err) { 259 case errSSLRecordWouldBlock: 260 ctx->amountRead += len; 261 break; 262#if SSL_ALLOW_UNNOTICED_DISCONNECT 263 case errSSLClosedGraceful: 264 /* legal if we're on record boundary and we've gotten past 265 * the handshake */ 266 if((ctx->amountRead == 0) && /* nothing pending */ 267 (len == 0) && /* nothing new */ 268 (ctx->state == SSL_HdskStateClientReady)) { /* handshake done */ 269 /* 270 * This means that the server has disconnected without 271 * sending a closure alert notice. This is technically 272 * illegal per the SSL3 spec, but about half of the 273 * servers out there do it, so we report it as a separate 274 * error which most clients - including (currently) 275 * URLAccess - ignore by treating it the same as 276 * a errSSLClosedGraceful error. Paranoid 277 * clients can detect it and handle it however they 278 * want to. 279 */ 280 SSLChangeHdskState(ctx, SSL_HdskStateNoNotifyClose); 281 err = errSSLClosedNoNotify; 282 break; 283 } 284 else { 285 /* illegal disconnect */ 286 err = errSSLClosedAbort; 287 /* and drop thru to default: fatal alert */ 288 } 289#endif /* SSL_ALLOW_UNNOTICED_DISCONNECT */ 290 default: 291 break; 292 } 293 return err; 294 } 295 ctx->amountRead += len; 296 } 297 298 check(ctx->amountRead >= head); 299 300 charPtr = ctx->partialReadBuffer.data; 301 rec->contentType = *charPtr++; 302 if (rec->contentType < SSL_RecordTypeV3_Smallest || 303 rec->contentType > SSL_RecordTypeV3_Largest) 304 return errSSLRecordProtocol; 305 306 rec->protocolVersion = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2); 307 charPtr += 2; 308 309 if(ctx->isDTLS) 310 { 311 sslUint64 seqNum; 312 SSLDecodeUInt64(charPtr, 8, &seqNum); 313 charPtr += 8; 314 sslLogRecordIo("Read DTLS Record %016llx (seq is: %016llx)", 315 seqNum, ctx->readCipher.sequenceNum); 316 317 /* if the epoch of the record is different of current read cipher, just drop it */ 318 if((seqNum>>48)!=(ctx->readCipher.sequenceNum>>48)) { 319 skipit=1; 320 } else { 321 ctx->readCipher.sequenceNum=seqNum; 322 } 323 } 324 325 contentLen = SSLDecodeInt(charPtr, 2); 326 charPtr += 2; 327 if (contentLen > (16384 + 2048)) /* Maximum legal length of an 328 * SSLCipherText payload */ 329 { 330 return errSSLRecordRecordOverflow; 331 } 332 333 if (ctx->partialReadBuffer.length < head + contentLen) 334 { if ((err = SSLReallocBuffer(&ctx->partialReadBuffer, head + contentLen)) != 0) 335 { 336 return err; 337 } 338 } 339 340 if (ctx->amountRead < head + contentLen) 341 { readData.length = head + contentLen - ctx->amountRead; 342 readData.data = ctx->partialReadBuffer.data + ctx->amountRead; 343 len = readData.length; 344 err = sslIoRead(readData, &len, ctx); 345 if(err != 0) 346 { if (err == errSSLRecordWouldBlock) 347 ctx->amountRead += len; 348 return err; 349 } 350 ctx->amountRead += len; 351 } 352 353 check(ctx->amountRead >= head + contentLen); 354 355 cipherFragment.data = ctx->partialReadBuffer.data + head; 356 cipherFragment.length = contentLen; 357 358 ctx->amountRead = 0; /* We've used all the data in the cache */ 359 360 /* We dont decrypt if we were told to skip this record */ 361 if(skipit) { 362 return errSSLRecordUnexpectedRecord; 363 } 364 /* 365 * Decrypt the payload & check the MAC, modifying the length of the 366 * buffer to indicate the amount of plaintext data after adjusting 367 * for the block size and removing the MAC */ 368 check(ctx->sslTslCalls != NULL); 369 if ((err = ctx->sslTslCalls->decryptRecord(rec->contentType, 370 &cipherFragment, ctx)) != 0) 371 return err; 372 373 /* 374 * We appear to have sucessfully received a record; increment the 375 * sequence number 376 */ 377 IncrementUInt64(&ctx->readCipher.sequenceNum); 378 379 /* Allocate a buffer to return the plaintext in and return it */ 380 if ((err = SSLAllocBuffer(&rec->contents, cipherFragment.length)) != 0) 381 { 382 return err; 383 } 384 memcpy(rec->contents.data, cipherFragment.data, cipherFragment.length); 385 386 387 return 0; 388} 389 390static int SSLRecordWriteInternal(SSLRecordContextRef ref, SSLRecord rec) 391{ 392 int err; 393 struct SSLRecordInternalContext *ctx = ref; 394 395 err=ctx->sslTslCalls->writeRecord(rec, ctx); 396 397 check_noerr(err); 398 399 return err; 400} 401 402/* Record Layer Entry Points */ 403 404static int 405SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref) 406{ 407 int err; 408 struct SSLRecordInternalContext *ctx = ref; 409 410 if ((err = SSLDisposeCipherSuite(&ctx->writePending, ctx)) != 0) 411 return err; 412 413 ctx->writePending = ctx->writeCipher; 414 ctx->writeCipher = ctx->prevCipher; 415 416 /* Zero out old data */ 417 memset(&ctx->prevCipher, 0, sizeof(CipherContext)); 418 419 return 0; 420} 421 422static int 423SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref) 424{ 425 int err; 426 struct SSLRecordInternalContext *ctx = ref; 427 428 if ((err = SSLDisposeCipherSuite(&ctx->prevCipher, ctx)) != 0) 429 return err; 430 431 ctx->prevCipher = ctx->writeCipher; 432 ctx->writeCipher = ctx->writePending; 433 434 /* Zero out old data */ 435 memset(&ctx->writePending, 0, sizeof(CipherContext)); 436 437 return 0; 438} 439 440static int 441SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref) 442{ 443 struct SSLRecordInternalContext *ctx = ref; 444 int err; 445 446 if ((err = SSLDisposeCipherSuite(&ctx->readCipher, ctx)) != 0) 447 return err; 448 449 ctx->readCipher = ctx->readPending; 450 memset(&ctx->readPending, 0, sizeof(CipherContext)); /* Zero out old data */ 451 452 return 0; 453} 454 455static int 456SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref, uint16_t selectedCipher, bool isServer, SSLBuffer key) 457{ int err; 458 uint8_t *keyDataProgress, *keyPtr, *ivPtr; 459 CipherContext *serverPending, *clientPending; 460 461 struct SSLRecordInternalContext *ctx = ref; 462 463 InitCipherSpec(ctx, selectedCipher); 464 465 ctx->readPending.macRef = ctx->selectedCipherSpec.macAlgorithm; 466 ctx->writePending.macRef = ctx->selectedCipherSpec.macAlgorithm; 467 ctx->readPending.symCipher = ctx->selectedCipherSpec.cipher; 468 ctx->writePending.symCipher = ctx->selectedCipherSpec.cipher; 469 /* This need to be reinitialized because the whole thing is zeroed sometimes */ 470 ctx->readPending.encrypting = 0; 471 ctx->writePending.encrypting = 1; 472 473 if(ctx->negProtocolVersion == DTLS_Version_1_0) 474 { 475 ctx->readPending.sequenceNum = (ctx->readPending.sequenceNum & (0xffffULL<<48)) + (1ULL<<48); 476 ctx->writePending.sequenceNum = (ctx->writePending.sequenceNum & (0xffffULL<<48)) + (1ULL<<48); 477 } else { 478 ctx->writePending.sequenceNum = 0; 479 ctx->readPending.sequenceNum = 0; 480 } 481 482 if (isServer) 483 { serverPending = &ctx->writePending; 484 clientPending = &ctx->readPending; 485 } 486 else 487 { serverPending = &ctx->readPending; 488 clientPending = &ctx->writePending; 489 } 490 491 /* Check the size of the 'key' buffer - <rdar://problem/11204357> */ 492 if(key.length != ctx->selectedCipherSpec.macAlgorithm->hash->digestSize*2 493 + ctx->selectedCipherSpec.cipher->params->keySize*2 494 + ctx->selectedCipherSpec.cipher->params->ivSize*2) 495 { 496 return errSSLRecordInternal; 497 } 498 499 keyDataProgress = key.data; 500 memcpy(clientPending->macSecret, keyDataProgress, 501 ctx->selectedCipherSpec.macAlgorithm->hash->digestSize); 502 keyDataProgress += ctx->selectedCipherSpec.macAlgorithm->hash->digestSize; 503 memcpy(serverPending->macSecret, keyDataProgress, 504 ctx->selectedCipherSpec.macAlgorithm->hash->digestSize); 505 keyDataProgress += ctx->selectedCipherSpec.macAlgorithm->hash->digestSize; 506 507 if (ctx->selectedCipherSpec.cipher->params->cipherType == aeadCipherType) 508 goto skipInit; 509 510 /* init the reusable-per-record MAC contexts */ 511 err = ctx->sslTslCalls->initMac(clientPending); 512 if(err) { 513 goto fail; 514 } 515 err = ctx->sslTslCalls->initMac(serverPending); 516 if(err) { 517 goto fail; 518 } 519 520 keyPtr = keyDataProgress; 521 keyDataProgress += ctx->selectedCipherSpec.cipher->params->keySize; 522 /* Skip server write key to get to IV */ 523 ivPtr = keyDataProgress + ctx->selectedCipherSpec.cipher->params->keySize; 524 if ((err = ctx->selectedCipherSpec.cipher->c.cipher.initialize(clientPending->symCipher->params, clientPending->encrypting, keyPtr, ivPtr, 525 &clientPending->cipherCtx)) != 0) 526 goto fail; 527 keyPtr = keyDataProgress; 528 keyDataProgress += ctx->selectedCipherSpec.cipher->params->keySize; 529 /* Skip client write IV to get to server write IV */ 530 ivPtr = keyDataProgress + ctx->selectedCipherSpec.cipher->params->ivSize; 531 if ((err = ctx->selectedCipherSpec.cipher->c.cipher.initialize(serverPending->symCipher->params, serverPending->encrypting, keyPtr, ivPtr, 532 &serverPending->cipherCtx)) != 0) 533 goto fail; 534 535skipInit: 536 /* Ciphers are ready for use */ 537 ctx->writePending.ready = 1; 538 ctx->readPending.ready = 1; 539 540 /* Ciphers get swapped by sending or receiving a change cipher spec message */ 541 err = 0; 542 543fail: 544 return err; 545} 546 547static int 548SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref, SSLProtocolVersion negVersion) 549{ 550 struct SSLRecordInternalContext *ctx = ref; 551 552 switch(negVersion) { 553 case SSL_Version_3_0: 554 ctx->sslTslCalls = &Ssl3RecordCallouts; 555 break; 556 case TLS_Version_1_0: 557 case TLS_Version_1_1: 558 case DTLS_Version_1_0: 559 case TLS_Version_1_2: 560 ctx->sslTslCalls = &Tls1RecordCallouts; 561 break; 562 case SSL_Version_2_0: 563 case SSL_Version_Undetermined: 564 default: 565 return errSSLRecordNegotiation; 566 } 567 ctx->negProtocolVersion = negVersion; 568 569 return 0; 570} 571 572static int 573SSLRecordFreeInternal(SSLRecordContextRef ref, SSLRecord rec) 574{ 575 return SSLFreeBuffer(&rec.contents); 576} 577 578static int 579SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref) 580{ 581 int err = 0, werr = 0; 582 size_t written = 0; 583 SSLBuffer buf; 584 WaitingRecord *rec; 585 struct SSLRecordInternalContext *ctx= ref; 586 587 while (!werr && ((rec = ctx->recordWriteQueue) != 0)) 588 { buf.data = rec->data + rec->sent; 589 buf.length = rec->length - rec->sent; 590 werr = sslIoWrite(buf, &written, ctx); 591 rec->sent += written; 592 if (rec->sent >= rec->length) 593 { 594 check(rec->sent == rec->length); 595 check(err == 0); 596 ctx->recordWriteQueue = rec->next; 597 sslFree(rec); 598 } 599 if (err) { 600 check_noerr(err); 601 return err; 602 } 603 } 604 605 return werr; 606} 607 608/***** Internal Record Layer APIs *****/ 609 610SSLRecordContextRef 611SSLCreateInternalRecordLayer(bool dtls) 612{ 613 struct SSLRecordInternalContext *ctx; 614 615 ctx = sslMalloc(sizeof(struct SSLRecordInternalContext)); 616 if(ctx==NULL) 617 return NULL; 618 619 memset(ctx, 0, sizeof(struct SSLRecordInternalContext)); 620 621 ctx->negProtocolVersion = SSL_Version_Undetermined; 622 623 ctx->sslTslCalls = &Ssl3RecordCallouts; 624 ctx->recordWriteQueue = NULL; 625 626 InitCipherSpec(ctx, TLS_NULL_WITH_NULL_NULL); 627 628 ctx->writeCipher.macRef = ctx->selectedCipherSpec.macAlgorithm; 629 ctx->readCipher.macRef = ctx->selectedCipherSpec.macAlgorithm; 630 ctx->readCipher.symCipher = ctx->selectedCipherSpec.cipher; 631 ctx->writeCipher.symCipher = ctx->selectedCipherSpec.cipher; 632 ctx->readCipher.encrypting = 0; 633 ctx->writeCipher.encrypting = 1; 634 635 ctx->isDTLS = dtls; 636 637 return ctx; 638 639} 640 641int 642SSLSetInternalRecordLayerIOFuncs( 643 SSLRecordContextRef ref, 644 SSLIOReadFunc readFunc, 645 SSLIOWriteFunc writeFunc) 646{ 647 struct SSLRecordInternalContext *ctx = ref; 648 649 ctx->read = readFunc; 650 ctx->write = writeFunc; 651 652 return 0; 653} 654 655int 656SSLSetInternalRecordLayerConnection( 657 SSLRecordContextRef ref, 658 SSLIOConnectionRef ioRef) 659{ 660 struct SSLRecordInternalContext *ctx = ref; 661 662 ctx->ioRef = ioRef; 663 664 return 0; 665} 666 667void 668SSLDestroyInternalRecordLayer(SSLRecordContextRef ref) 669{ 670 struct SSLRecordInternalContext *ctx = ref; 671 WaitingRecord *waitRecord, *next; 672 673 /* RecordContext cleanup : */ 674 SSLFreeBuffer(&ctx->partialReadBuffer); 675 waitRecord = ctx->recordWriteQueue; 676 while (waitRecord) 677 { next = waitRecord->next; 678 sslFree(waitRecord); 679 waitRecord = next; 680 } 681 682 683 /* Cleanup cipher structs */ 684 SSLDisposeCipherSuite(&ctx->readCipher, ctx); 685 SSLDisposeCipherSuite(&ctx->writeCipher, ctx); 686 SSLDisposeCipherSuite(&ctx->readPending, ctx); 687 SSLDisposeCipherSuite(&ctx->writePending, ctx); 688 SSLDisposeCipherSuite(&ctx->prevCipher, ctx); 689 690 sslFree(ctx); 691 692} 693 694struct SSLRecordFuncs SSLRecordLayerInternal = 695{ 696 .read = SSLRecordReadInternal, 697 .write = SSLRecordWriteInternal, 698 .initPendingCiphers = SSLInitInternalRecordLayerPendingCiphers, 699 .advanceWriteCipher = SSLAdvanceInternalRecordLayerWriteCipher, 700 .advanceReadCipher = SSLAdvanceInternalRecordLayerReadCipher, 701 .rollbackWriteCipher = SSLRollbackInternalRecordLayerWriteCipher, 702 .setProtocolVersion = SSLSetInternalRecordLayerProtocolVersion, 703 .free = SSLRecordFreeInternal, 704 .serviceWriteQueue = SSLRecordServiceWriteQueueInternal, 705}; 706 707