+
+
+static void get_extended_peer_id(SSLContext *ctx, tls_buffer *extended_peer_id)
+{
+ uint8_t md[CC_SHA256_DIGEST_LENGTH];
+ __block CC_SHA256_CTX hash_ctx;
+
+ CC_SHA256_Init(&hash_ctx);
+
+ CC_SHA256_Update(&hash_ctx, &ctx->allowAnyRoot, sizeof(ctx->allowAnyRoot));
+
+#if !TARGET_OS_IPHONE
+ if(ctx->trustedLeafCerts) {
+ CFArrayForEach(ctx->trustedLeafCerts, ^(const void *value) {
+ SecCertificateRef cert = (SecCertificateRef) value;
+ CC_SHA256_Update(&hash_ctx, SecCertificateGetBytePtr(cert), (CC_LONG)SecCertificateGetLength(cert));
+ });
+ }
+#endif
+
+ CC_SHA256_Update(&hash_ctx, &ctx->trustedCertsOnly, sizeof(ctx->trustedCertsOnly));
+
+
+ if(ctx->trustedCerts) {
+ CFArrayForEach(ctx->trustedCerts, ^(const void *value) {
+ SecCertificateRef cert = (SecCertificateRef) value;
+ CC_SHA256_Update(&hash_ctx, SecCertificateGetBytePtr(cert), (CC_LONG)SecCertificateGetLength(cert));
+ });
+ }
+
+ CC_SHA256_Final(md, &hash_ctx);
+
+ extended_peer_id->length = ctx->peerID.length + sizeof(md);
+ extended_peer_id->data = sslMalloc(extended_peer_id->length);
+ memcpy(extended_peer_id->data, ctx->peerID.data, ctx->peerID.length);
+ memcpy(extended_peer_id->data+ctx->peerID.length, md, sizeof(md));
+}
+
+/* Send the initial client hello */
+static OSStatus
+SSLHandshakeStart(SSLContext *ctx)
+{
+ int err;
+ tls_buffer extended_peer_id;
+ get_extended_peer_id(ctx, &extended_peer_id);
+ err = tls_handshake_negotiate(ctx->hdsk, &extended_peer_id);
+ free(extended_peer_id.data);
+ if(err)
+ return err;
+
+ ctx->readCipher_ready = 0;
+ ctx->writeCipher_ready = 0;
+ SSLChangeHdskState(ctx, SSL_HdskStatePending);
+
+ return noErr;
+}
+
+OSStatus
+SSLReHandshake(SSLContext *ctx)
+{
+ if(ctx == NULL) {
+ return errSecParam;
+ }
+
+ switch (ctx->state) {
+ case SSL_HdskStateGracefulClose:
+ return errSSLClosedGraceful;
+ case SSL_HdskStateErrorClose:
+ case SSL_HdskStateOutOfBandError:
+ return errSSLClosedAbort;
+ case SSL_HdskStatePending:
+ return errSecBadReq;
+ default:
+ break;
+ }
+
+ /* If we are the client, we start the negotiation */
+ if(ctx->protocolSide == kSSLClientSide) {
+ return SSLHandshakeStart(ctx);
+ } else {
+ return tls_handshake_request_renegotiation(ctx->hdsk);
+ }
+}
+