1/* 2 * Copyright (c) 2002,2005-2007,2010-2011 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 * ssl3RecordCallouts.c - SSLv3-specific routines for SslTlsCallouts. 26 */ 27 28/* THIS FILE CONTAINS KERNEL CODE */ 29 30#include <AssertMacros.h> 31#include <string.h> 32#include <stdint.h> 33#include <inttypes.h> 34 35#ifdef KERNEL 36#include <sys/types.h> 37#else 38#include <stddef.h> 39#endif 40 41#include "sslDebug.h" 42#include "sslMemory.h" 43#include "sslUtils.h" 44#include "sslRand.h" 45 46#include "tls_record.h" 47 48 49/* 50 * ssl3WriteRecord does not send alerts on failure, out of the assumption/fear 51 * that this might result in a loop (since sending an alert causes ssl3WriteRecord 52 * to be called). 53 * 54 * As far as I can tell, we can use this same routine for SSLv3 and TLSv1, as long 55 * as we're not trying to use the "variable length padding" feature of TLSv1. 56 * OpenSSL doesn't use that feature; for now, neither will we. Thus this routine 57 * is used for the SslTlsCallouts.writeRecord function for both protocols. 58 */ 59int ssl3WriteRecord( 60 SSLRecord rec, 61 struct SSLRecordInternalContext *ctx) 62{ 63 int err; 64 int padding = 0, i; 65 WaitingRecord *out = NULL, *queue; 66 SSLBuffer payload, mac; 67 uint8_t *charPtr; 68 uint16_t payloadSize,blockSize = 0; 69 int head = 5; 70 71 switch(rec.protocolVersion) { 72 case DTLS_Version_1_0: 73 head += 8; 74 case SSL_Version_3_0: 75 case TLS_Version_1_0: 76 case TLS_Version_1_1: 77 case TLS_Version_1_2: 78 break; 79 default: 80 check(0); 81 return errSSLRecordInternal; 82 } 83 check(rec.contents.length <= 16384); 84 85 sslLogRecordIo("type = %02x, ver = %04x, len = %ld, seq = %016llx", 86 rec.contentType, rec.protocolVersion, rec.contents.length, 87 ctx->writeCipher.sequenceNum); 88 89 /* Allocate enough room for the transmitted record, which will be: 90 * 5 bytes of header (13 for DTLS) + 91 * IV [block cipher and TLS1.1 or DTLS 1.0 only] 92 * encrypted contents + 93 * macLength + 94 * padding [block ciphers only] + 95 * padding length field (1 byte) [block ciphers only] 96 */ 97 payloadSize = (uint16_t) rec.contents.length; 98 CipherType cipherType = ctx->writeCipher.symCipher->params->cipherType; 99 const Cipher *cipher = &ctx->writeCipher.symCipher->c.cipher; 100 const AEADCipher *aead = &ctx->writeCipher.symCipher->c.aead; 101 blockSize = ctx->writeCipher.symCipher->params->blockSize; 102 switch (cipherType) { 103 case blockCipherType: 104 payloadSize += ctx->writeCipher.macRef->hash->digestSize; 105 padding = blockSize - (payloadSize % blockSize) - 1; 106 payloadSize += padding + 1; 107 /* TLS 1.1, TLS1.2 and DTLS 1.0 have an extra block for IV */ 108 if(ctx->negProtocolVersion >= TLS_Version_1_1) { 109 payloadSize += blockSize; 110 } 111 break; 112 case streamCipherType: 113 payloadSize += ctx->writeCipher.macRef->hash->digestSize; 114 break; 115 case aeadCipherType: 116 /* AES_GCM doesn't need padding. */ 117 payloadSize += aead->macSize; 118 break; 119 default: 120 check(0); 121 return errSSLRecordInternal; 122 } 123 124 out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) + 125 head + payloadSize); 126 out->next = NULL; 127 out->sent = 0; 128 out->length = head + payloadSize; 129 130 charPtr = out->data; 131 *(charPtr++) = rec.contentType; 132 charPtr = SSLEncodeInt(charPtr, rec.protocolVersion, 2); 133 134 /* DTLS sequence number */ 135 if(rec.protocolVersion == DTLS_Version_1_0) 136 charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum); 137 138 charPtr = SSLEncodeInt(charPtr, payloadSize, 2); 139 140 /* Also for DTLS */ 141 if((ctx->negProtocolVersion >= TLS_Version_1_1) && 142 (cipherType == blockCipherType)) 143 { 144 SSLBuffer randomIV; 145 randomIV.data = charPtr; 146 randomIV.length = blockSize; 147 if((err = sslRand(&randomIV)) != 0) 148 return err; 149 charPtr += blockSize; 150 } 151 if (cipherType == aeadCipherType) { 152 /* Encode the explicit iv, for AES_GCM we just use the 8 byte 153 sequenceNum as the explicitIV. 154 Ideally this needs to be done in the algorithm itself, by an 155 extra function pointer in AEADCipher. */ 156 charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum); 157 /* TODO: If we ever add any mode other than GCM this code might have 158 to be different. */ 159 /* TODO: Pass 4 byte implicit and 8 byte explicit IV to cipher */ 160 //err = ctx->writeCipher.symCipher->c.aead.setIV(charPtr, &ctx->writeCipher, ctx); 161 } 162 163 /* Copy the contents into the output buffer */ 164 memcpy(charPtr, rec.contents.data, rec.contents.length); 165 payload.data = charPtr; 166 payload.length = rec.contents.length; 167 168 charPtr += rec.contents.length; 169 170 /* MAC the data */ 171 if (cipherType != aeadCipherType) { 172 /* MAC immediately follows data */ 173 mac.data = charPtr; 174 mac.length = ctx->writeCipher.macRef->hash->digestSize; 175 charPtr += mac.length; 176 if (mac.length > 0) /* Optimize away null case */ 177 { 178 check(ctx->sslTslCalls != NULL); 179 if ((err = ctx->sslTslCalls->computeMac(rec.contentType, 180 payload, 181 mac, 182 &ctx->writeCipher, 183 ctx->writeCipher.sequenceNum, 184 ctx)) != 0) 185 goto fail; 186 } 187 } 188 189 /* For TLS 1.1 and DTLS, we would need to specifiy the IV, but instead 190 we are clever like this: since the IV is just one block in front, 191 we encrypt it with the rest of the data. The actual transmitted IV 192 is the result of the encryption, with whatever internal IV is used. 193 This method is explained in the TLS 1.1 RFC */ 194 if(ctx->negProtocolVersion >= TLS_Version_1_1 && 195 cipherType == blockCipherType) 196 { 197 payload.data -= blockSize; 198 } 199 200 /* Update payload to reflect encrypted data: IV, contents, mac & padding */ 201 payload.length = payloadSize; 202 203 204 switch (cipherType) { 205 case blockCipherType: 206 /* Fill in the padding bytes & padding length field with the 207 * padding value; the protocol only requires the last byte, 208 * but filling them all in avoids leaking data */ 209 for (i = 1; i <= padding + 1; ++i) 210 payload.data[payload.length - i] = padding; 211 /* DROPTRHOUGH */ 212 case streamCipherType: 213 /* Encrypt the data */ 214 if ((err = cipher->encrypt(payload.data, 215 payload.data, payload.length, ctx->writeCipher.cipherCtx)) != 0) 216 goto fail; 217 break; 218 case aeadCipherType: 219 check(0); 220 break; 221 default: 222 check(0); 223 return errSSLRecordInternal; 224 } 225 226 /* Enqueue the record to be written from the idle loop */ 227 if (ctx->recordWriteQueue == 0) 228 ctx->recordWriteQueue = out; 229 else 230 { queue = ctx->recordWriteQueue; 231 while (queue->next != 0) 232 queue = queue->next; 233 queue->next = out; 234 } 235 236 /* Increment the sequence number */ 237 IncrementUInt64(&ctx->writeCipher.sequenceNum); 238 239 return 0; 240 241fail: 242 /* 243 * Only for if we fail between when the WaitingRecord is allocated and when 244 * it is queued 245 */ 246 sslFree(out); 247 return err; 248} 249 250static int ssl3DecryptRecord( 251 uint8_t type, 252 SSLBuffer *payload, 253 struct SSLRecordInternalContext *ctx) 254{ 255 int err; 256 SSLBuffer content; 257 258 CipherType cipherType = ctx->readCipher.symCipher->params->cipherType; 259 const Cipher *c = &ctx->readCipher.symCipher->c.cipher; 260 switch (cipherType) { 261 case blockCipherType: 262 if ((payload->length % ctx->readCipher.symCipher->params->blockSize) != 0) 263 { 264 return errSSLRecordDecryptionFail; 265 } 266 /* DROPTHROUGH */ 267 case streamCipherType: 268 /* Decrypt in place */ 269 err = c->decrypt(payload->data, payload->data, 270 payload->length, ctx->readCipher.cipherCtx); 271 break; 272 case aeadCipherType: 273 default: 274 check(0); 275 return errSSLRecordInternal; 276 } 277 if (err != 0) 278 { 279 return errSSLRecordDecryptionFail; 280 } 281 282 /* Locate content within decrypted payload */ 283 content.data = payload->data; 284 content.length = payload->length - ctx->readCipher.macRef->hash->digestSize; 285 if (cipherType == blockCipherType) 286 { /* padding can't be equal to or more than a block */ 287 if (payload->data[payload->length - 1] >= ctx->readCipher.symCipher->params->blockSize) 288 { 289 sslErrorLog("DecryptSSLRecord: bad padding length (%d)\n", 290 (unsigned)payload->data[payload->length - 1]); 291 return errSSLRecordDecryptionFail; 292 } 293 content.length -= 1 + payload->data[payload->length - 1]; 294 /* Remove block size padding */ 295 } 296 297 /* Verify MAC on payload */ 298 if (ctx->readCipher.macRef->hash->digestSize > 0) 299 /* Optimize away MAC for null case */ 300 if ((err = SSLVerifyMac(type, &content, 301 payload->data + content.length, ctx)) != 0) 302 { 303 return errSSLRecordBadRecordMac; 304 } 305 306 *payload = content; /* Modify payload buffer to indicate content length */ 307 308 return 0; 309} 310 311/* initialize a per-CipherContext HashHmacContext for use in MACing each record */ 312static int ssl3InitMac ( 313 CipherContext *cipherCtx) // macRef, macSecret valid on entry 314 // macCtx valid on return 315{ 316 const HashReference *hash; 317 SSLBuffer *hashCtx; 318 int serr; 319 320 check(cipherCtx->macRef != NULL); 321 hash = cipherCtx->macRef->hash; 322 check(hash != NULL); 323 324 hashCtx = &cipherCtx->macCtx.hashCtx; 325 if(hashCtx->data != NULL) { 326 SSLFreeBuffer(hashCtx); 327 } 328 serr = SSLAllocBuffer(hashCtx, hash->contextSize); 329 if(serr) { 330 return serr; 331 } 332 return 0; 333} 334 335static int ssl3FreeMac ( 336 CipherContext *cipherCtx) 337{ 338 SSLBuffer *hashCtx; 339 340 check(cipherCtx != NULL); 341 /* this can be called on a completely zeroed out CipherContext... */ 342 if(cipherCtx->macRef == NULL) { 343 return 0; 344 } 345 hashCtx = &cipherCtx->macCtx.hashCtx; 346 if(hashCtx->data != NULL) { 347 sslFree(hashCtx->data); 348 hashCtx->data = NULL; 349 } 350 hashCtx->length = 0; 351 return 0; 352} 353 354static int ssl3ComputeMac ( 355 uint8_t type, 356 SSLBuffer data, 357 SSLBuffer mac, // caller mallocs data 358 CipherContext *cipherCtx, // assumes macCtx, macRef 359 sslUint64 seqNo, 360 struct SSLRecordInternalContext *ctx) 361{ 362 int err; 363 uint8_t innerDigestData[SSL_MAX_DIGEST_LEN]; 364 uint8_t scratchData[11], *charPtr; 365 SSLBuffer digest, digestCtx, scratch; 366 SSLBuffer secret; 367 368 const HashReference *hash; 369 370 check(cipherCtx != NULL); 371 check(cipherCtx->macRef != NULL); 372 hash = cipherCtx->macRef->hash; 373 check(hash != NULL); 374 check(hash->macPadSize <= MAX_MAC_PADDING); 375 check(hash->digestSize <= SSL_MAX_DIGEST_LEN); 376 digestCtx = cipherCtx->macCtx.hashCtx; // may be NULL, for null cipher 377 secret.data = cipherCtx->macSecret; 378 secret.length = hash->digestSize; 379 380 /* init'd early in SSLNewContext() */ 381 check(SSLMACPad1[0] == 0x36 && SSLMACPad2[0] == 0x5C); 382 383 /* 384 * MAC = hash( MAC_write_secret + pad_2 + 385 * hash( MAC_write_secret + pad_1 + seq_num + type + 386 * length + content ) 387 * ) 388 */ 389 if ((err = hash->init(&digestCtx)) != 0) 390 goto exit; 391 if ((err = hash->update(&digestCtx, &secret)) != 0) /* MAC secret */ 392 goto exit; 393 scratch.data = (uint8_t *)SSLMACPad1; 394 scratch.length = hash->macPadSize; 395 if ((err = hash->update(&digestCtx, &scratch)) != 0) /* pad1 */ 396 goto exit; 397 charPtr = scratchData; 398 charPtr = SSLEncodeUInt64(charPtr, seqNo); 399 *charPtr++ = type; 400 charPtr = SSLEncodeSize(charPtr, data.length, 2); 401 scratch.data = scratchData; 402 scratch.length = 11; 403 check(charPtr = scratchData+11); 404 if ((err = hash->update(&digestCtx, &scratch)) != 0) 405 /* sequenceNo, type & length */ 406 goto exit; 407 if ((err = hash->update(&digestCtx, &data)) != 0) /* content */ 408 goto exit; 409 digest.data = innerDigestData; 410 digest.length = hash->digestSize; 411 if ((err = hash->final(&digestCtx, &digest)) != 0) /* figure inner digest */ 412 goto exit; 413 414 if ((err = hash->init(&digestCtx)) != 0) 415 goto exit; 416 if ((err = hash->update(&digestCtx, &secret)) != 0) /* MAC secret */ 417 goto exit; 418 scratch.data = (uint8_t *)SSLMACPad2; 419 scratch.length = hash->macPadSize; 420 if ((err = hash->update(&digestCtx, &scratch)) != 0) /* pad2 */ 421 goto exit; 422 if ((err = hash->update(&digestCtx, &digest)) != 0) /* inner digest */ 423 goto exit; 424 if ((err = hash->final(&digestCtx, &mac)) != 0) /* figure the mac */ 425 goto exit; 426 427 err = 0; /* redundant, I know */ 428 429exit: 430 return err; 431} 432 433 434const SslRecordCallouts Ssl3RecordCallouts = { 435 ssl3DecryptRecord, 436 ssl3WriteRecord, 437 ssl3InitMac, 438 ssl3FreeMac, 439 ssl3ComputeMac, 440}; 441