diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
--- a/nss/lib/ssl/ssl3con.c	2014-01-17 17:59:03.242109996 -0800
+++ b/nss/lib/ssl/ssl3con.c	2014-01-17 17:59:45.862816905 -0800
@@ -12383,6 +12383,68 @@ ssl3_InitSocketPolicy(sslSocket *ss)
     PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites);
 }
 
+SECStatus
+ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
+				unsigned char *out,
+				unsigned int *outLen,
+				unsigned int outLenMax) {
+    PRBool       isTLS;
+    int          index = 0;
+    unsigned int len;
+    SECStatus    rv = SECFailure;
+
+    *outLen = 0;
+
+    ssl_GetSSL3HandshakeLock(ss);
+
+    ssl_GetSpecReadLock(ss);
+    isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0);
+    ssl_ReleaseSpecReadLock(ss);
+
+    /* The tls-unique channel binding is the first Finished structure in the
+     * handshake. In the case of a resumption, that's the server's Finished.
+     * Otherwise, it's the client's Finished. */
+    len = ss->ssl3.hs.finishedBytes;
+
+    /* Sending or receiving a Finished message will set finishedBytes to a
+     * non-zero value. */
+    if (len == 0) {
+	PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
+	goto loser;
+    }
+
+    /* If we are in the middle of a renegotiation then the channel binding
+     * value is poorly defined and depends on the direction that it will be
+     * used on. Therefore we simply return an error in this case. */
+    if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) {
+	PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
+	goto loser;
+    }
+
+    /* If resuming, then we want the second Finished value in the array, which
+     * is the server's */
+    if (ss->ssl3.hs.isResuming)
+	index = 1;
+
+    *outLen = len;
+    if (outLenMax < len) {
+	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+	goto loser;
+    }
+
+    if (isTLS) {
+	memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len);
+    } else {
+	memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len);
+    }
+
+    rv = SECSuccess;
+
+loser:
+    ssl_ReleaseSSL3HandshakeLock(ss);
+    return rv;
+}
+
 /* ssl3_config_match_init must have already been called by
  * the caller of this function.
  */
diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
--- a/nss/lib/ssl/ssl.h	2014-01-17 17:59:03.242109996 -0800
+++ b/nss/lib/ssl/ssl.h	2014-01-17 17:59:45.862816905 -0800
@@ -282,6 +282,27 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDe
 SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
 SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
 
+/* SSLChannelBindingType enumerates the types of supported channel binding
+ * values. See RFC 5929. */
+typedef enum SSLChannelBindingType {
+    SSL_CHANNEL_BINDING_TLS_UNIQUE = 1,
+} SSLChannelBindingType;
+
+/* SSL_GetChannelBinding copies the requested channel binding value, as defined
+ * in RFC 5929, into |out|. The full length of the binding value is written
+ * into |*outLen|.
+ *
+ * At most |outLenMax| bytes of data are copied. If |outLenMax| is
+ * insufficient then the function returns SECFailure and sets the error to
+ * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set.
+ *
+ * This call will fail if made during a renegotiation. */
+SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd,
+					   SSLChannelBindingType binding_type,
+					   unsigned char *out,
+					   unsigned int *outLen,
+					   unsigned int outLenMax);
+
 /* SSL Version Range API
 **
 ** This API should be used to control SSL 3.0 & TLS support instead of the
diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
--- a/nss/lib/ssl/sslimpl.h	2014-01-17 17:59:03.242109996 -0800
+++ b/nss/lib/ssl/sslimpl.h	2014-01-17 17:59:45.862816905 -0800
@@ -1853,6 +1853,11 @@ extern PRBool ssl_GetSessionTicketKeysPK
 extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
 					    unsigned int length);
 
+extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss,
+						 unsigned char *out,
+						 unsigned int *outLen,
+						 unsigned int outLenMax);
+
 /* Construct a new NSPR socket for the app to use */
 extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
 extern void ssl_FreePRSocket(PRFileDesc *fd);
diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
--- a/nss/lib/ssl/sslsock.c	2014-01-17 17:59:03.252110162 -0800
+++ b/nss/lib/ssl/sslsock.c	2014-01-17 17:59:45.872817074 -0800
@@ -1308,6 +1308,27 @@ NSS_SetFrancePolicy(void)
     return NSS_SetDomesticPolicy();
 }
 
+SECStatus
+SSL_GetChannelBinding(PRFileDesc *fd,
+		      SSLChannelBindingType binding_type,
+		      unsigned char *out,
+		      unsigned int *outLen,
+		      unsigned int outLenMax) {
+    sslSocket *ss = ssl_FindSocket(fd);
+
+    if (!ss) {
+	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding",
+		 SSL_GETPID(), fd));
+	return SECFailure;
+    }
+
+    if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) {
+	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
+	return SECFailure;
+    }
+
+    return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax);
+}
 
 
 /* LOCKS ??? XXX */