Add support for the TLS Channel ID extension.

See http://tools.ietf.org/html/draft-balfanz-tls-channelid-00.

Change-Id: Id5b9799f96c0f7a1ef5ed8db9e40111a700d091f
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 8b8350c..50aa465 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -2951,6 +2951,11 @@
 #ifndef OPENSSL_NO_SRP
 	SSL_SRP_CTX_init(s);
 #endif
+#if !defined(OPENSSL_NO_TLSEXT)
+	s->tlsext_channel_id_enabled = s->ctx->tlsext_channel_id_enabled;
+	if (s->ctx->tlsext_channel_id_private)
+		s->tlsext_channel_id_private = EVP_PKEY_dup(s->ctx->tlsext_channel_id_private);
+#endif
 	s->method->ssl_clear(s);
 	return(1);
 err:
@@ -3074,6 +3079,10 @@
 		s->next_proto_negotiated_len = 0;
 		}
 #endif
+
+#if !defined(OPENSSL_NO_TLSEXT)
+	s->s3->tlsext_channel_id_valid = 0;
+#endif
 	}
 
 #ifndef OPENSSL_NO_SRP
@@ -3348,6 +3357,35 @@
 		ret = 1;
 		break;
 #endif
+	case SSL_CTRL_CHANNEL_ID:
+		if (!s->server)
+			break;
+		s->tlsext_channel_id_enabled = 1;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_SET_CHANNEL_ID:
+		if (s->server)
+			break;
+		s->tlsext_channel_id_enabled = 1;
+		if (EVP_PKEY_bits(parg) != 256)
+			{
+			SSLerr(SSL_F_SSL3_CTRL,SSL_R_CHANNEL_ID_NOT_P256);
+			break;
+			}
+		if (s->tlsext_channel_id_private)
+			EVP_PKEY_free(s->tlsext_channel_id_private);
+		s->tlsext_channel_id_private = (EVP_PKEY*) parg;
+		ret = 1;
+		break;
+
+	case SSL_CTRL_GET_CHANNEL_ID:
+		if (!s->server)
+			break;
+		if (!s->s3->tlsext_channel_id_valid)
+			break;
+		memcpy(parg, s->s3->tlsext_channel_id, larg < 64 ? larg : 64);
+		return 64;
 
 #endif /* !OPENSSL_NO_TLSEXT */
 	default:
@@ -3569,6 +3607,12 @@
 			}
 		return 1;
 		}
+	case SSL_CTRL_CHANNEL_ID:
+		/* must be called on a server */
+		if (ctx->method->ssl_accept == ssl_undefined_function)
+			return 0;
+		ctx->tlsext_channel_id_enabled=1;
+		return 1;
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
 	case SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG:
@@ -3637,6 +3681,18 @@
 			}
 		break;
 
+	case SSL_CTRL_SET_CHANNEL_ID:
+		ctx->tlsext_channel_id_enabled = 1;
+		if (EVP_PKEY_bits(parg) != 256)
+			{
+			SSLerr(SSL_F_SSL3_CTX_CTRL,SSL_R_CHANNEL_ID_NOT_P256);
+			break;
+			}
+		if (ctx->tlsext_channel_id_private)
+			EVP_PKEY_free(ctx->tlsext_channel_id_private);
+		ctx->tlsext_channel_id_private = (EVP_PKEY*) parg;
+		break;
+
 	default:
 		return(0);
 		}