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