OSStatus SSLEncodeChangeCipherSpec(SSLRecord *rec, SSLContext *ctx) { OSStatus err; assert(ctx->writePending_ready); sslLogNegotiateDebug("===Sending changeCipherSpec msg"); rec->contentType = SSL_RecordTypeChangeCipher; assert(ctx->negProtocolVersion >= SSL_Version_3_0); rec->protocolVersion = ctx->negProtocolVersion; rec->contents.length = 1; if ((err = SSLAllocBuffer(&rec->contents, 1))) return err; rec->contents.data[0] = 1; ctx->messageQueueContainsChangeCipherSpec=true; return errSecSuccess; }
int SSLProcessCertificateRequest(tls_buffer message, tls_handshake_t ctx) { unsigned i; unsigned typeCount; unsigned shListLen = 0; UInt8 *charPtr; unsigned dnListLen; unsigned dnLen; tls_buffer dnBuf; DNListElem *dn; int err; /* * Cert request only happens in during client authentication. * Application can send a client cert if they have an appropriate one. * coreTLS does not ensure the client cert is appropriate. */ unsigned minLen = (sslVersionIsLikeTls12(ctx)) ? 5 : 3; if (message.length < minLen) { sslErrorLog("SSLProcessCertificateRequest: length decode error 1\n"); return errSSLProtocol; } charPtr = message.data; typeCount = *charPtr++; if ((typeCount < 1) || (message.length < minLen + typeCount)) { sslErrorLog("SSLProcessCertificateRequest: length decode error 2\n"); return errSSLProtocol; } /* Update the server-specified auth types */ sslFree(ctx->clientAuthTypes); ctx->numAuthTypes = typeCount; ctx->clientAuthTypes = (tls_client_auth_type *) sslMalloc(ctx->numAuthTypes * sizeof(tls_client_auth_type)); if(ctx->clientAuthTypes==NULL) return errSSLInternal; for(i=0; i<ctx->numAuthTypes; i++) { sslLogNegotiateDebug("===Server specifies authType %d", (int)(*charPtr)); ctx->clientAuthTypes[i] = (tls_client_auth_type)(*charPtr++); } if (sslVersionIsLikeTls12(ctx)) { /* Parse the supported_signature_algorithms field added in TLS1.2 */ shListLen = SSLDecodeInt(charPtr, 2); charPtr += 2; if ((shListLen < 2) || (message.length < minLen + typeCount + shListLen)) { sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); return errSSLProtocol; } if (shListLen & 1) { sslErrorLog("SSLProcessCertificateRequest: signAlg len odd\n"); return errSSLProtocol; } sslFree(ctx->peerSigAlgs); ctx->numPeerSigAlgs = shListLen / 2; ctx->peerSigAlgs = (tls_signature_and_hash_algorithm *) sslMalloc((ctx->numPeerSigAlgs) * sizeof(tls_signature_and_hash_algorithm)); if(ctx->peerSigAlgs==NULL) return errSSLInternal; for(i=0; i<ctx->numPeerSigAlgs; i++) { ctx->peerSigAlgs[i].hash = *charPtr++; ctx->peerSigAlgs[i].signature = *charPtr++; sslLogNegotiateDebug("===Server specifies sigAlg %d %d", ctx->peerSigAlgs[i].hash, ctx->peerSigAlgs[i].signature); } } /* Update the acceptable DNList */ SSLFreeDNList(ctx->acceptableDNList); ctx->acceptableDNList=NULL; dnListLen = SSLDecodeInt(charPtr, 2); charPtr += 2; if (message.length != minLen + typeCount + shListLen + dnListLen) { sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); return errSSLProtocol; } while (dnListLen > 0) { if (dnListLen < 2) { sslErrorLog("SSLProcessCertificateRequest: dnListLen error 1\n"); return errSSLProtocol; } dnLen = SSLDecodeInt(charPtr, 2); charPtr += 2; if (dnListLen < 2 + dnLen) { sslErrorLog("SSLProcessCertificateRequest: dnListLen error 2\n"); return errSSLProtocol; } if ((err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem)))) return err; dn = (DNListElem*)dnBuf.data; if ((err = SSLAllocBuffer(&dn->derDN, dnLen))) { SSLFreeBuffer(&dnBuf); return err; } memcpy(dn->derDN.data, charPtr, dnLen); charPtr += dnLen; dn->next = ctx->acceptableDNList; ctx->acceptableDNList = dn; dnListLen -= 2 + dnLen; } assert(charPtr == message.data + message.length); return errSSLSuccess; }
OSStatus SSLProcessChangeCipherSpec(SSLRecord rec, SSLContext *ctx) { OSStatus err; if (rec.contents.length != 1 || rec.contents.data[0] != 1) { if(ctx->isDTLS) return errSSLWouldBlock; SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); sslErrorLog("***bad changeCipherSpec msg: length %d data 0x%x\n", (unsigned)rec.contents.length, (unsigned)rec.contents.data[0]); return errSSLProtocol; } /* * Handle PAC-style session resumption, client side only. * In that case, the handshake state was left in either KeyExchange or * Cert. */ if((ctx->protocolSide == kSSLClientSide) && (ctx->sessionTicket.length != 0) && ((ctx->state == SSL_HdskStateKeyExchange) || (ctx->state == SSL_HdskStateCert)) && (ctx->masterSecretCallback != NULL)) { size_t secretLen = SSL_MASTER_SECRET_SIZE; sslEapDebug("Client side resuming based on masterSecretCallback"); ctx->masterSecretCallback(ctx, ctx->masterSecretArg, ctx->masterSecret, &secretLen); ctx->sessionMatch = 1; /* set up selectedCipherSpec */ if ((err = FindCipherSpec(ctx)) != 0) { return err; } if((err = SSLInitPendingCiphers(ctx)) != 0) { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); return err; } SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); } if (!ctx->readPending_ready || ctx->state != SSL_HdskStateChangeCipherSpec) { if(ctx->isDTLS) return errSSLWouldBlock; SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); sslErrorLog("***bad changeCipherSpec msg: readPending.ready %d state %d\n", (unsigned)ctx->readPending_ready, (unsigned)ctx->state); return errSSLProtocol; } sslLogNegotiateDebug("===Processing changeCipherSpec msg"); /* Install new cipher spec on read side */ if ((err = ctx->recFuncs->advanceReadCipher(ctx->recCtx)) != 0) { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); return err; } ctx->readCipher_ready = 0; /* Can't send data until Finished is sent */ SSLChangeHdskState(ctx, SSL_HdskStateFinished); return errSecSuccess; }