Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * SSL3 Protocol | 2 * SSL3 Protocol |
| 3 * | 3 * |
| 4 * ***** BEGIN LICENSE BLOCK ***** | 4 * ***** BEGIN LICENSE BLOCK ***** |
| 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 6 * | 6 * |
| 7 * The contents of this file are subject to the Mozilla Public License Version | 7 * The contents of this file are subject to the Mozilla Public License Version |
| 8 * 1.1 (the "License"); you may not use this file except in compliance with | 8 * 1.1 (the "License"); you may not use this file except in compliance with |
| 9 * the License. You may obtain a copy of the License at | 9 * the License. You may obtain a copy of the License at |
| 10 * http://www.mozilla.org/MPL/ | 10 * http://www.mozilla.org/MPL/ |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, | 83 static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, |
| 84 PRUint16 ex_type, SECItem *data); | 84 PRUint16 ex_type, SECItem *data); |
| 85 static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, | 85 static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, |
| 86 PRUint32 maxBytes); | 86 PRUint32 maxBytes); |
| 87 static SECStatus ssl3_ServerHandleEncryptedClientCertsXtn(sslSocket *ss, | 87 static SECStatus ssl3_ServerHandleEncryptedClientCertsXtn(sslSocket *ss, |
| 88 PRUint16 ex_type, SECItem *data); | 88 PRUint16 ex_type, SECItem *data); |
| 89 static SECStatus ssl3_ClientHandleEncryptedClientCertsXtn(sslSocket *ss, | 89 static SECStatus ssl3_ClientHandleEncryptedClientCertsXtn(sslSocket *ss, |
| 90 PRUint16 ex_type, SECItem *data); | 90 PRUint16 ex_type, SECItem *data); |
| 91 static PRInt32 ssl3_SendEncryptedClientCertsXtn(sslSocket *ss, | 91 static PRInt32 ssl3_SendEncryptedClientCertsXtn(sslSocket *ss, |
| 92 PRBool append, PRUint32 maxBytes); | 92 PRBool append, PRUint32 maxBytes); |
| 93 static SECStatus ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxB ytes); | |
| 94 SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) ; | |
| 95 | |
| 93 | 96 |
| 94 /* | 97 /* |
| 95 * Write bytes. Using this function means the SECItem structure | 98 * Write bytes. Using this function means the SECItem structure |
| 96 * cannot be freed. The caller is expected to call this function | 99 * cannot be freed. The caller is expected to call this function |
| 97 * on a shallow copy of the structure. | 100 * on a shallow copy of the structure. |
| 98 */ | 101 */ |
| 99 static SECStatus | 102 static SECStatus |
| 100 ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes) | 103 ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes) |
| 101 { | 104 { |
| 102 if (bytes > item->len) | 105 if (bytes > item->len) |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, | 246 { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
| 244 #ifdef NSS_ENABLE_ECC | 247 #ifdef NSS_ENABLE_ECC |
| 245 { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn }, | 248 { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn }, |
| 246 { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn }, | 249 { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn }, |
| 247 #endif | 250 #endif |
| 248 { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, | 251 { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, |
| 249 { ssl_encrypted_client_certs, &ssl3_ServerHandleEncryptedClientCertsXtn }, | 252 { ssl_encrypted_client_certs, &ssl3_ServerHandleEncryptedClientCertsXtn }, |
| 250 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | 253 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| 251 { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, | 254 { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, |
| 252 { ssl_ob_cert_xtn, &ssl3_ServerHandleOBCertXtn }, | 255 { ssl_ob_cert_xtn, &ssl3_ServerHandleOBCertXtn }, |
| 256 { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, | |
| 253 { -1, NULL } | 257 { -1, NULL } |
| 254 }; | 258 }; |
| 255 | 259 |
| 256 /* These two tables are used by the client, to handle server hello | 260 /* These two tables are used by the client, to handle server hello |
| 257 * extensions. */ | 261 * extensions. */ |
| 258 static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { | 262 static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { |
| 259 { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, | 263 { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
| 260 /* TODO: add a handler for ssl_ec_point_formats_xtn */ | 264 /* TODO: add a handler for ssl_ec_point_formats_xtn */ |
| 261 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, | 265 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
| 262 { ssl_encrypted_client_certs, &ssl3_ClientHandleEncryptedClientCertsXtn }, | 266 { ssl_encrypted_client_certs, &ssl3_ClientHandleEncryptedClientCertsXtn }, |
| 263 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | 267 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| 264 { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, | 268 { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
| 265 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, | 269 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
| 266 { ssl_ob_cert_xtn, &ssl3_ClientHandleOBCertXtn }, | 270 { ssl_ob_cert_xtn, &ssl3_ClientHandleOBCertXtn }, |
| 271 { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn}, | |
| 267 { -1, NULL } | 272 { -1, NULL } |
| 268 }; | 273 }; |
| 269 | 274 |
| 270 static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = { | 275 static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = { |
| 271 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | 276 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| 272 { -1, NULL } | 277 { -1, NULL } |
| 273 }; | 278 }; |
| 274 | 279 |
| 275 /* Tables of functions to format TLS hello extensions, one function per | 280 /* Tables of functions to format TLS hello extensions, one function per |
| 276 * extension. | 281 * extension. |
| 277 * These static tables are for the formatting of client hello extensions. | 282 * These static tables are for the formatting of client hello extensions. |
| 278 * The server's table of hello senders is dynamic, in the socket struct, | 283 * The server's table of hello senders is dynamic, in the socket struct, |
| 279 * and sender functions are registered there. | 284 * and sender functions are registered there. |
| 280 */ | 285 */ |
| 281 static const | 286 static const |
| 282 ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { | 287 ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { |
| 283 { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, | 288 { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, |
| 284 { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, | 289 { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, |
| 285 #ifdef NSS_ENABLE_ECC | 290 #ifdef NSS_ENABLE_ECC |
| 286 { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, | 291 { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, |
| 287 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, | 292 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
| 288 #endif | 293 #endif |
| 289 { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, | 294 { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
| 290 { ssl_encrypted_client_certs, &ssl3_SendEncryptedClientCertsXtn }, | 295 { ssl_encrypted_client_certs, &ssl3_SendEncryptedClientCertsXtn }, |
| 291 { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, | 296 { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
| 292 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, | 297 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
| 293 { ssl_ob_cert_xtn, &ssl3_SendOBCertXtn } | 298 { ssl_ob_cert_xtn, &ssl3_SendOBCertXtn }, |
| 299 { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn } | |
| 294 /* any extra entries will appear as { 0, NULL } */ | 300 /* any extra entries will appear as { 0, NULL } */ |
| 295 }; | 301 }; |
| 296 | 302 |
| 297 static const | 303 static const |
| 298 ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = { | 304 ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = { |
| 299 { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn } | 305 { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn } |
| 300 /* any extra entries will appear as { 0, NULL } */ | 306 /* any extra entries will appear as { 0, NULL } */ |
| 301 }; | 307 }; |
| 302 | 308 |
| 303 static PRBool | 309 static PRBool |
| (...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1663 | 1669 |
| 1664 /* call each of the extension senders and return the accumulated length */ | 1670 /* call each of the extension senders and return the accumulated length */ |
| 1665 PRInt32 | 1671 PRInt32 |
| 1666 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, | 1672 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, |
| 1667 const ssl3HelloExtensionSender *sender) | 1673 const ssl3HelloExtensionSender *sender) |
| 1668 { | 1674 { |
| 1669 PRInt32 total_exten_len = 0; | 1675 PRInt32 total_exten_len = 0; |
| 1670 int i; | 1676 int i; |
| 1671 | 1677 |
| 1672 if (!sender) { | 1678 if (!sender) { |
| 1673 » sender = ss->version > SSL_LIBRARY_VERSION_3_0 ? | 1679 » sender = (ss->version > SSL_LIBRARY_VERSION_3_0 || IS_DTLS(ss)) ? |
|
wtc
2012/04/04 23:32:49
This is no longer necessary after we made ss->vers
ekr
2012/04/19 14:29:35
Concur.
| |
| 1674 &clientHelloSendersTLS[0] : &clientHelloSendersSSL3[0]; | 1680 &clientHelloSendersTLS[0] : &clientHelloSendersSSL3[0]; |
| 1675 } | 1681 } |
| 1676 | 1682 |
| 1677 for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { | 1683 for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { |
| 1678 if (sender->ex_sender) { | 1684 if (sender->ex_sender) { |
| 1679 PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes); | 1685 PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes); |
| 1680 if (extLen < 0) | 1686 if (extLen < 0) |
| 1681 return -1; | 1687 return -1; |
| 1682 maxBytes -= extLen; | 1688 maxBytes -= extLen; |
| 1683 total_exten_len += extLen; | 1689 total_exten_len += extLen; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1861 | 1867 |
| 1862 /* The echoed extension must be empty. */ | 1868 /* The echoed extension must be empty. */ |
| 1863 if (data->len != 0) | 1869 if (data->len != 0) |
| 1864 return SECFailure; | 1870 return SECFailure; |
| 1865 | 1871 |
| 1866 /* Keep track of negotiated extensions. */ | 1872 /* Keep track of negotiated extensions. */ |
| 1867 ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | 1873 ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
| 1868 | 1874 |
| 1869 return SECSuccess; | 1875 return SECSuccess; |
| 1870 } | 1876 } |
| 1877 | |
| 1878 static SECStatus | |
| 1879 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) | |
| 1880 { | |
| 1881 PRUint32 ext_data_len; | |
| 1882 PRInt16 i; | |
| 1883 SECStatus rv; | |
| 1884 | |
| 1885 if (!ss) | |
| 1886 return 0; | |
| 1887 | |
| 1888 if (!ss->sec.isServer) { | |
| 1889 /* Client */ | |
| 1890 | |
| 1891 if (!ss->ssl3.dtlsSRTPCipherCt) | |
| 1892 return 0; /* Not relevant */ | |
| 1893 | |
| 1894 ext_data_len = 2 + (2*ss->ssl3.dtlsSRTPCipherCt) + 1; | |
| 1895 | |
| 1896 if (append && ((4 + ext_data_len) <= maxBytes)) { | |
| 1897 /* Xtn type */ | |
| 1898 rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); | |
| 1899 if (rv != SECSuccess) return -1; | |
| 1900 /* Length of extension data */ | |
| 1901 rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2); | |
| 1902 if (rv != SECSuccess) return -1; | |
| 1903 /* Length of the SRTP cipher list */ | |
| 1904 rv = ssl3_AppendHandshakeNumber(ss, 2 * ss->ssl3.dtlsSRTPCipherCt, 2 ); | |
| 1905 if (rv != SECSuccess) return -1; | |
| 1906 /* The SRTP ciphers */ | |
| 1907 for (i=0; i<ss->ssl3.dtlsSRTPCipherCt; i++) { | |
| 1908 rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCiphers[i], 2); | |
| 1909 } | |
| 1910 /* Empty MKI value */ | |
| 1911 ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); | |
| 1912 | |
| 1913 ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_use_srtp_x tn; | |
| 1914 } | |
| 1915 | |
| 1916 return ext_data_len + 4; | |
| 1917 } | |
| 1918 | |
| 1919 /* Server side */ | |
| 1920 if (append && (maxBytes >= 9)) { | |
| 1921 /* Xtn type */ | |
| 1922 rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); | |
| 1923 if (rv != SECSuccess) return -1; | |
| 1924 /* Length of extension data */ | |
| 1925 rv = ssl3_AppendHandshakeNumber(ss, 5, 2); | |
| 1926 if (rv != SECSuccess) return -1; | |
| 1927 /* Length of the SRTP cipher list */ | |
| 1928 rv = ssl3_AppendHandshakeNumber(ss, 2, 2); | |
| 1929 if (rv != SECSuccess) return -1; | |
| 1930 /* The selected cipher */ | |
| 1931 rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2); | |
| 1932 if (rv != SECSuccess) return -1; | |
| 1933 /* Empty MKI value */ | |
| 1934 ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); | |
| 1935 } | |
| 1936 | |
| 1937 return 9; | |
| 1938 } | |
| 1939 | |
| 1940 SECStatus | |
| 1941 ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) | |
| 1942 { | |
| 1943 SECStatus rv; | |
| 1944 PRInt16 i; | |
| 1945 PRInt16 bestIndex; | |
| 1946 PRBool found = PR_FALSE; | |
| 1947 SECItem litem; | |
| 1948 PRUint32 cipherLenBytes; | |
| 1949 PRUint32 cipher; | |
| 1950 | |
| 1951 if (!ss->sec.isServer) { | |
| 1952 /* Client side */ | |
| 1953 if (!data->data || !data->len || | |
| 1954 !ssl3_ClientExtensionAdvertised(ss, ssl_use_srtp_xtn)) { | |
| 1955 /* malformed or was not initiated by the client.*/ | |
| 1956 return SECFailure; | |
| 1957 } | |
| 1958 | |
| 1959 if (data->len != 5) { /* Must always be 9 since we don't offer MKI */ | |
| 1960 /* malformed or was not initiated by the client.*/ | |
| 1961 return SECFailure; | |
| 1962 } | |
| 1963 | |
| 1964 /* Now check that the number of ciphers listed is 1 (len = 2) */ | |
| 1965 cipherLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data-> len); | |
| 1966 if (cipherLenBytes != 2) | |
| 1967 return SECFailure; | |
| 1968 | |
| 1969 /* Get the selected cipher */ | |
| 1970 cipher = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); | |
| 1971 | |
| 1972 /* Get the use_mki value */ | |
| 1973 rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1 , &data->data, &data->l en); | |
| 1974 if (rv != SECSuccess) { | |
| 1975 return SECFailure; | |
| 1976 } | |
| 1977 /* We didn't offer an MKI, so this must be 0 length */ | |
| 1978 if (litem.len != 0) | |
| 1979 return SECFailure; | |
| 1980 | |
| 1981 /* Now check that this is one of the ciphers we offered */ | |
| 1982 for (i=0; i<ss->ssl3.dtlsSRTPCipherCt; i++) { | |
| 1983 if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) { | |
| 1984 found = PR_TRUE; | |
| 1985 break; | |
| 1986 } | |
| 1987 } | |
| 1988 | |
| 1989 if (!found) | |
| 1990 return SECFailure; | |
| 1991 | |
| 1992 /* OK, this looks fine. */ | |
| 1993 ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; | |
| 1994 ss->ssl3.dtlsSRTPCipherSuite = cipher; | |
| 1995 return SECSuccess; | |
| 1996 } | |
| 1997 | |
| 1998 /* Server side */ | |
| 1999 if (!data->data || data->len < 5) { | |
| 2000 /* malformed */ | |
| 2001 return SECFailure; | |
| 2002 } | |
| 2003 | |
| 2004 /* Get the length of the cipher list */ | |
| 2005 cipherLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len) ; | |
| 2006 /* Check that there is room for the ciphers and that the list is even length */ | |
| 2007 if ((cipherLenBytes > (data->len - 1)) || (cipherLenBytes % 2)) | |
| 2008 return SECFailure; | |
| 2009 | |
| 2010 /* Walk through the offered list one at a time and pick the most preferred | |
| 2011 of our ciphers, if any */ | |
| 2012 while (cipherLenBytes > 0) { | |
| 2013 cipher = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); | |
| 2014 cipherLenBytes -= 2; | |
| 2015 | |
| 2016 for (i=0; i<ss->ssl3.dtlsSRTPCipherCt; i++) { | |
| 2017 /* Unknown ciphers just go through the entire list */ | |
| 2018 if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) { | |
| 2019 if (!found) { | |
| 2020 found = PR_TRUE; | |
| 2021 bestIndex = i; | |
| 2022 } | |
| 2023 else { | |
| 2024 if (i < bestIndex) | |
| 2025 bestIndex = i; | |
| 2026 } | |
| 2027 break; | |
| 2028 } | |
| 2029 } | |
| 2030 } | |
| 2031 | |
| 2032 /* Get the use_mki value */ | |
| 2033 rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len); | |
| 2034 if (rv != SECSuccess) { | |
| 2035 return SECFailure; | |
| 2036 } | |
| 2037 | |
| 2038 if (data->len) | |
| 2039 return SECFailure; /* Malformed */ | |
| 2040 | |
| 2041 /* Now figure out what to do */ | |
| 2042 if (!found) { | |
| 2043 /* No matching ciphers */ | |
| 2044 return SECSuccess; | |
| 2045 } | |
| 2046 | |
| 2047 /* OK, we have a valid cipher and we've selected it */ | |
| 2048 ss->ssl3.dtlsSRTPCipherSuite = ss->ssl3.dtlsSRTPCiphers[bestIndex]; | |
| 2049 ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; | |
| 2050 | |
| 2051 rv = ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn, | |
| 2052 ssl3_SendUseSRTPXtn); | |
| 2053 if (rv != SECSuccess) | |
| 2054 return rv; | |
| 2055 | |
| 2056 return SECSuccess; | |
| 2057 } | |
| 2058 | |
| OLD | NEW |