1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2 --- a/nss/lib/ssl/ssl3con.c 2014-01-17 17:59:03.242109996 -0800 3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-17 17:59:45.862816905 -0800 4 @@ -12383,6 +12383,68 @@ ssl3_InitSocketPolicy(sslSocket *ss) 5 PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites); 6 } 7 8 +SECStatus 9 +ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, 10 + unsigned char *out, 11 + unsigned int *outLen, 12 + unsigned int outLenMax) { 13 + PRBool isTLS; 14 + int index = 0; 15 + unsigned int len; 16 + SECStatus rv = SECFailure; 17 + 18 + *outLen = 0; 19 + 20 + ssl_GetSSL3HandshakeLock(ss); 21 + 22 + ssl_GetSpecReadLock(ss); 23 + isTLS = (PRBool)(ss->ssl3.cwSpec->version > SSL_LIBRARY_VERSION_3_0); 24 + ssl_ReleaseSpecReadLock(ss); 25 + 26 + /* The tls-unique channel binding is the first Finished structure in the 27 + * handshake. In the case of a resumption, that's the server's Finished. 28 + * Otherwise, it's the client's Finished. */ 29 + len = ss->ssl3.hs.finishedBytes; 30 + 31 + /* Sending or receiving a Finished message will set finishedBytes to a 32 + * non-zero value. */ 33 + if (len == 0) { 34 + PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); 35 + goto loser; 36 + } 37 + 38 + /* If we are in the middle of a renegotiation then the channel binding 39 + * value is poorly defined and depends on the direction that it will be 40 + * used on. Therefore we simply return an error in this case. */ 41 + if (ss->firstHsDone && ss->ssl3.hs.ws != idle_handshake) { 42 + PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); 43 + goto loser; 44 + } 45 + 46 + /* If resuming, then we want the second Finished value in the array, which 47 + * is the server's */ 48 + if (ss->ssl3.hs.isResuming) 49 + index = 1; 50 + 51 + *outLen = len; 52 + if (outLenMax < len) { 53 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 54 + goto loser; 55 + } 56 + 57 + if (isTLS) { 58 + memcpy(out, &ss->ssl3.hs.finishedMsgs.tFinished[index], len); 59 + } else { 60 + memcpy(out, &ss->ssl3.hs.finishedMsgs.sFinished[index], len); 61 + } 62 + 63 + rv = SECSuccess; 64 + 65 +loser: 66 + ssl_ReleaseSSL3HandshakeLock(ss); 67 + return rv; 68 +} 69 + 70 /* ssl3_config_match_init must have already been called by 71 * the caller of this function. 72 */ 73 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h 74 --- a/nss/lib/ssl/ssl.h 2014-01-17 17:59:03.242109996 -0800 75 +++ b/nss/lib/ssl/ssl.h 2014-01-17 17:59:45.862816905 -0800 76 @@ -282,6 +282,27 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDe 77 SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy); 78 SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy); 79 80 +/* SSLChannelBindingType enumerates the types of supported channel binding 81 + * values. See RFC 5929. */ 82 +typedef enum SSLChannelBindingType { 83 + SSL_CHANNEL_BINDING_TLS_UNIQUE = 1, 84 +} SSLChannelBindingType; 85 + 86 +/* SSL_GetChannelBinding copies the requested channel binding value, as defined 87 + * in RFC 5929, into |out|. The full length of the binding value is written 88 + * into |*outLen|. 89 + * 90 + * At most |outLenMax| bytes of data are copied. If |outLenMax| is 91 + * insufficient then the function returns SECFailure and sets the error to 92 + * SEC_ERROR_OUTPUT_LEN, but |*outLen| is still set. 93 + * 94 + * This call will fail if made during a renegotiation. */ 95 +SSL_IMPORT SECStatus SSL_GetChannelBinding(PRFileDesc *fd, 96 + SSLChannelBindingType binding_type, 97 + unsigned char *out, 98 + unsigned int *outLen, 99 + unsigned int outLenMax); 100 + 101 /* SSL Version Range API 102 ** 103 ** This API should be used to control SSL 3.0 & TLS support instead of the 104 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 105 --- a/nss/lib/ssl/sslimpl.h 2014-01-17 17:59:03.242109996 -0800 106 +++ b/nss/lib/ssl/sslimpl.h 2014-01-17 17:59:45.862816905 -0800 107 @@ -1853,6 +1853,11 @@ extern PRBool ssl_GetSessionTicketKeysPK 108 extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, 109 unsigned int length); 110 111 +extern SECStatus ssl3_GetTLSUniqueChannelBinding(sslSocket *ss, 112 + unsigned char *out, 113 + unsigned int *outLen, 114 + unsigned int outLenMax); 115 + 116 /* Construct a new NSPR socket for the app to use */ 117 extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); 118 extern void ssl_FreePRSocket(PRFileDesc *fd); 119 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c 120 --- a/nss/lib/ssl/sslsock.c 2014-01-17 17:59:03.252110162 -0800 121 +++ b/nss/lib/ssl/sslsock.c 2014-01-17 17:59:45.872817074 -0800 122 @@ -1308,6 +1308,27 @@ NSS_SetFrancePolicy(void) 123 return NSS_SetDomesticPolicy(); 124 } 125 126 +SECStatus 127 +SSL_GetChannelBinding(PRFileDesc *fd, 128 + SSLChannelBindingType binding_type, 129 + unsigned char *out, 130 + unsigned int *outLen, 131 + unsigned int outLenMax) { 132 + sslSocket *ss = ssl_FindSocket(fd); 133 + 134 + if (!ss) { 135 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelBinding", 136 + SSL_GETPID(), fd)); 137 + return SECFailure; 138 + } 139 + 140 + if (binding_type != SSL_CHANNEL_BINDING_TLS_UNIQUE) { 141 + PORT_SetError(PR_INVALID_ARGUMENT_ERROR); 142 + return SECFailure; 143 + } 144 + 145 + return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax); 146 +} 147 148 149 /* LOCKS ??? XXX */ 150