ALPN : add option to continue in case of client/server protocol mismatch (like OpenSSL)

This commit is contained in:
Ludovic FLAMENT
2015-10-13 09:38:40 +02:00
parent 266936db93
commit 10f5154389
7 changed files with 173 additions and 52 deletions

View File

@ -194,7 +194,7 @@ static void Usage(void)
printf("-C Disable CRL\n");
#endif
#ifdef HAVE_ALPN
printf("-n <str> Application-Layer Protocole Name\n");
printf("-n <str> Application-Layer Protocole Name ({C,F}:<list>)\n");
#endif
}
@ -247,6 +247,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int overrideDateErrors = 0;
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
char* alpnList = NULL;
unsigned char alpn_opt = 0;
char* cipherList = NULL;
const char* verifyCert = caCert;
const char* ourCert = cliCert;
@ -294,6 +295,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
(void)disableCRL;
(void)minDhKeyBits;
(void)alpnList;
(void)alpn_opt;
StackTrap();
@ -500,6 +502,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
case 'n' :
#ifdef HAVE_ALPN
alpnList = myoptarg;
if (alpnList[0] == 'C' && alpnList[1] == ':')
alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
else if (alpnList[0] == 'F' && alpnList[1] == ':')
alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
else {
Usage();
exit(MY_EX_USAGE);
}
alpnList += 2;
#endif
break;
@ -812,7 +826,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef HAVE_ALPN
if (alpnList != NULL) {
printf("ALPN accepted protocols list : %s\n", alpnList);
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList));
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
}
#endif
@ -885,16 +899,19 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
showPeer(ssl);
#ifdef HAVE_ALPN
{
if (alpnList != NULL) {
int err;
char *protocol_name = NULL;
word16 protocol_nameSz = 0;
if (wolfSSL_ALPN_GetProtocol(ssl, &protocol_name,
&protocol_nameSz) != SSL_SUCCESS)
printf("Getting ALPN protocol name failed\n");
else
err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
if (err == SSL_SUCCESS)
printf("Received ALPN protocol : %s (%d)\n",
protocol_name, protocol_nameSz);
else if (err == SSL_ALPN_NOT_FOUND)
printf("Not received ALPN response (no match with server)\n");
else
printf("Getting ALPN protocol name failed\n");
}
#endif
@ -988,7 +1005,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef HAVE_ALPN
if (alpnList != NULL) {
printf("ALPN accepted protocols list : %s\n", alpnList);
wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList));
wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList),
alpn_opt);
}
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
@ -1024,17 +1042,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
printf("didn't reuse session id!!!\n");
#ifdef HAVE_ALPN
{
if (alpnList != NULL) {
int err;
char *protocol_name = NULL;
word16 protocol_nameSz = 0;
printf("Sending ALPN accepted list : %s\n", alpnList);
if (wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name,
&protocol_nameSz) != SSL_SUCCESS)
printf("Getting ALPN protocol name failed\n");
else
err = wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name,
&protocol_nameSz);
if (err == SSL_SUCCESS)
printf("Received ALPN protocol : %s (%d)\n",
protocol_name, protocol_nameSz);
else if (err == SSL_ALPN_NOT_FOUND)
printf("Not received ALPN response (no match with server)\n");
else
printf("Getting ALPN protocol name failed\n");
}
#endif
if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)

View File

@ -162,7 +162,7 @@ static void Usage(void)
printf("-I Do not send PSK identity hint\n");
#endif
#ifdef HAVE_ALPN
printf("-L <str> Application-Layer Protocole Name\n");
printf("-L <str> Application-Layer Protocole Name ({C,F}:<list>)\n");
#endif
}
@ -198,6 +198,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
int ret;
char* alpnList = NULL;
unsigned char alpn_opt = 0;
char* cipherList = NULL;
const char* verifyCert = cliCert;
const char* ourCert = svrCert;
@ -237,6 +238,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
(void)doCliCertCheck;
(void)minDhKeyBits;
(void)alpnList;
(void)alpn_opt;
#ifdef CYASSL_TIRTOS
fdOpenSession(Task_self());
@ -384,6 +386,18 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
case 'L' :
#ifdef HAVE_ALPN
alpnList = myoptarg;
if (alpnList[0] == 'C' && alpnList[1] == ':')
alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
else if (alpnList[0] == 'F' && alpnList[1] == ':')
alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
else {
Usage();
exit(MY_EX_USAGE);
}
alpnList += 2;
#endif
break;
default:
@ -636,7 +650,7 @@ while (1) { /* allow resume option */
#ifdef HAVE_ALPN
if (alpnList != NULL) {
printf("ALPN accepted protocols list : %s\n", alpnList);
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList));
wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
}
#endif
@ -683,16 +697,19 @@ while (1) { /* allow resume option */
showPeer(ssl);
#ifdef HAVE_ALPN
{
if (alpnList != NULL) {
int err;
char *protocol_name = NULL;
word16 protocol_nameSz = 0;
if (wolfSSL_ALPN_GetProtocol(ssl, &protocol_name,
&protocol_nameSz) != SSL_SUCCESS)
printf("Getting ALPN protocol name failed\n");
else
err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
if (err == SSL_SUCCESS)
printf("Send ALPN protocol : %s (%d)\n",
protocol_name, protocol_nameSz);
else if (err == SSL_ALPN_NOT_FOUND)
printf("Not send ALPN response (no match with server)\n");
else
printf("Getting ALPN protocol name failed\n");
}
#endif

View File

@ -889,7 +889,7 @@ int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name)
#ifdef HAVE_ALPN
int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
word32 protocol_name_listSz)
word32 protocol_name_listSz, byte options)
{
char *list, *ptr, *token[10];
word16 len;
@ -904,10 +904,17 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER *
WOLFSSL_MAX_ALPN_PROTO_NAME_LEN +
WOLFSSL_MAX_ALPN_NUMBER)) {
WOLFSSL_MSG("Invalid arguments, procolt name list too long");
WOLFSSL_MSG("Invalid arguments, protocol name list too long");
return BAD_FUNC_ARG;
}
if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) &&
!(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) {
WOLFSSL_MSG("Invalid arguments, options not supported");
return BAD_FUNC_ARG;
}
list = (char *)XMALLOC(protocol_name_listSz+1, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (list == NULL) {
@ -927,7 +934,7 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
while ((idx--) > 0) {
len = (word16)XSTRLEN(token[idx]);
ret = TLSX_UseALPN(&ssl->extensions, token[idx], len);
ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options);
if (ret != SSL_SUCCESS) {
WOLFSSL_MSG("TLSX_UseALPN failure");
break;

View File

@ -867,6 +867,8 @@ static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz)
}
alpn->next = NULL;
alpn->negociated = 0;
alpn->options = 0;
alpn->protocol_name = XMALLOC(protocol_nameSz + 1, 0, DYNAMIC_TYPE_TLSX);
if (alpn->protocol_name == NULL) {
@ -977,6 +979,8 @@ static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size)
return MEMORY_E;
}
alpn->negociated = 1;
ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn);
if (ret != 0) {
TLSX_ALPN_Free(alpn);
@ -995,7 +999,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
word16 offset = 0;
int r = BUFFER_ERROR;
TLSX *extension;
ALPN *alpn = NULL;
ALPN *alpn = NULL, *list;
extension = TLSX_Find(ssl->extensions, WOLFSSL_ALPN);
if (extension == NULL)
@ -1017,14 +1021,15 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
if (length != OPAQUE16_LEN + size)
return BUFFER_ERROR;
list = (ALPN*)extension->data;
for (size = 0; offset < length; offset += size) {
size = input[offset++];
if (offset + size > length)
return BUFFER_ERROR;
alpn = TLSX_ALPN_Find((ALPN*)extension->data,
(char*)input + offset, size);
alpn = TLSX_ALPN_Find(list, (char*)input + offset, size);
if (alpn != NULL) {
WOLFSSL_MSG("ALPN protocol match");
break;
@ -1034,13 +1039,21 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
if (alpn == NULL) {
WOLFSSL_MSG("No ALPN protocol match");
/* do nothing if no protocol match between client and server and option
is set to continue (like OpenSSL) */
if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
WOLFSSL_MSG("Continue on mismatch");
return 0;
}
SendAlert(ssl, alert_fatal, no_application_protocol);
return UNKNOWN_ALPN_PROTOCOL_NAME_E;
}
/* set the matching negociated protocol */
r = TLSX_SetALPN(&ssl->extensions,
alpn->protocol_name, (word16)XSTRLEN(alpn->protocol_name));
alpn->protocol_name,
(word16)XSTRLEN(alpn->protocol_name));
if (r != SSL_SUCCESS) {
WOLFSSL_MSG("TLSX_UseALPN failed");
return BUFFER_ERROR;
@ -1057,7 +1070,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
}
/** Add a protocol name to the list of accepted usable ones */
int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size)
int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options)
{
ALPN *alpn;
TLSX *extension;
@ -1072,6 +1085,9 @@ int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size)
return MEMORY_E;
}
/* Set Options of ALPN */
alpn->options = options;
extension = TLSX_Find(*extensions, WOLFSSL_ALPN);
if (extension == NULL) {
ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn);
@ -1101,13 +1117,28 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
extension = TLSX_Find(extensions, WOLFSSL_ALPN);
if (extension == NULL) {
WOLFSSL_MSG("TLS extension not found");
return SSL_FATAL_ERROR;
return SSL_ALPN_NOT_FOUND;
}
alpn = (ALPN *)extension->data;
if (alpn == NULL) {
WOLFSSL_MSG("ALPN extension not found");
return WOLFSSL_ALPN_NO_MATCH;
*data = NULL;
*dataSz = 0;
return SSL_FATAL_ERROR;
}
if (alpn->negociated != 1) {
/* consider as an error */
if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) {
WOLFSSL_MSG("No protocol match with peer -> Failed");
return SSL_FATAL_ERROR;
}
/* continue without negociated protocol */
WOLFSSL_MSG("No protocol match with peer -> Continue");
return SSL_ALPN_NOT_FOUND;
}
if (alpn->next != NULL) {

View File

@ -1215,7 +1215,19 @@ static void use_ALPN_all(WOLFSSL* ssl)
0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c,
0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c,
0x73, 0x70, 0x64, 0x79, 0x2f, 0x33};
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list)));
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list),
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
}
static void use_ALPN_all_continue(WOLFSSL* ssl)
{
/* http/1.1,spdy/1,spdy/2,spdy/3 */
char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c,
0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c,
0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c,
0x73, 0x70, 0x64, 0x79, 0x2f, 0x33};
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list),
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH));
}
static void use_ALPN_one(WOLFSSL* ssl)
@ -1223,7 +1235,8 @@ static void use_ALPN_one(WOLFSSL* ssl)
/* spdy/2 */
char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32};
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto)));
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto),
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
}
static void use_ALPN_unknown(WOLFSSL* ssl)
@ -1231,7 +1244,17 @@ static void use_ALPN_unknown(WOLFSSL* ssl)
/* http/2.0 */
char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30};
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto)));
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto),
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
}
static void use_ALPN_unknown_continue(WOLFSSL* ssl)
{
/* http/2.0 */
char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30};
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto),
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH));
}
static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
@ -1242,9 +1265,6 @@ static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
char *proto;
word16 protoSz = 0;
printf("verify_ALPN_not_matching GetProtocol(ssl) = %d\n",
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
/* check value */
@ -1252,6 +1272,19 @@ static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl)
AssertIntNE(0, XMEMCMP(nego_proto, proto, sizeof(nego_proto)));
}
static void verify_ALPN_not_matching_continue(WOLFSSL* ssl)
{
char *proto = NULL;
word16 protoSz = 0;
AssertIntEQ(SSL_ALPN_NOT_FOUND,
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
/* check value */
AssertIntEQ(1, 0 == protoSz);
AssertIntEQ(1, NULL == proto);
}
static void verify_ALPN_matching_http1(WOLFSSL* ssl)
{
/* http/1.1 */
@ -1259,9 +1292,6 @@ static void verify_ALPN_matching_http1(WOLFSSL* ssl)
char *proto;
word16 protoSz = 0;
printf("verify_ALPN_matching GetProtocol(ssl) = %d\n",
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
/* check value */
@ -1276,9 +1306,6 @@ static void verify_ALPN_matching_spdy2(WOLFSSL* ssl)
char *proto;
word16 protoSz = 0;
printf("verify_ALPN_matching GetProtocol(ssl) = %d\n",
wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
AssertIntEQ(SSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz));
/* check value */
@ -1286,7 +1313,6 @@ static void verify_ALPN_matching_spdy2(WOLFSSL* ssl)
AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz));
}
static void test_wolfSSL_UseALPN_connection(void)
{
unsigned long i;
@ -1307,6 +1333,10 @@ static void test_wolfSSL_UseALPN_connection(void)
{0, 0, 0, 0},
{0, 0, use_ALPN_all, 0},
/* success case missmatch behavior but option 'continue' set */
{0, 0, use_ALPN_all_continue, verify_ALPN_not_matching_continue},
{0, 0, use_ALPN_unknown_continue, 0},
/* missmatch behavior with same list
* the first and only this one must be taken */
{0, 0, use_ALPN_all, 0},
@ -1345,13 +1375,16 @@ static void test_wolfSSL_UseALPN_params(void)
/* error cases */
AssertIntNE(SSL_SUCCESS,
wolfSSL_UseALPN(NULL, http1, sizeof(http1)));
AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0));
wolfSSL_UseALPN(NULL, http1, sizeof(http1),
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0,
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
/* success case */
/* http1 only */
AssertIntEQ(SSL_SUCCESS,
wolfSSL_UseALPN(ssl, http1, sizeof(http1)));
wolfSSL_UseALPN(ssl, http1, sizeof(http1),
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
/* http1, spdy1 */
memcpy(buff, http1, sizeof(http1));
@ -1359,7 +1392,8 @@ static void test_wolfSSL_UseALPN_params(void)
buff[idx++] = ',';
memcpy(buff+idx, spdy1, sizeof(spdy1));
idx += sizeof(spdy1);
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx));
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx,
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
/* http1, spdy2, spdy1 */
memcpy(buff, http1, sizeof(http1));
@ -1370,7 +1404,8 @@ static void test_wolfSSL_UseALPN_params(void)
buff[idx++] = ',';
memcpy(buff+idx, spdy1, sizeof(spdy1));
idx += sizeof(spdy1);
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx));
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx,
WOLFSSL_ALPN_FAILED_ON_MISMATCH));
/* spdy3, http1, spdy2, spdy1 */
memcpy(buff, spdy3, sizeof(spdy3));
@ -1384,7 +1419,8 @@ static void test_wolfSSL_UseALPN_params(void)
buff[idx++] = ',';
memcpy(buff+idx, spdy1, sizeof(spdy1));
idx += sizeof(spdy1);
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx));
AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx,
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH));
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);

View File

@ -1540,13 +1540,17 @@ WOLFSSL_LOCAL int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
typedef struct ALPN {
char* protocol_name; /* ALPN protocol name */
struct ALPN* next; /* List Behavior */
byte options; /* Behaviour options */
byte negociated; /* ALPN protocol negociated or not */
} ALPN;
WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions,
void** data, word16 *dataSz);
WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data,
word16 size);
word16 size, byte options);
WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option);
#endif /* HAVE_ALPN */
/* Maximum Fragment Length */

View File

@ -674,6 +674,7 @@ enum { /* ssl Constants */
SSL_SUCCESS = 1,
SSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */
SSL_ALPN_NOT_FOUND = -9,
SSL_BAD_CERTTYPE = -8,
SSL_BAD_STAT = -7,
SSL_BAD_PATH = -6,
@ -1354,7 +1355,9 @@ WOLFSSL_API int wolfSSL_SNI_GetFromBuffer(
/* ALPN status code */
enum {
WOLFSSL_ALPN_NO_MATCH = 0,
WOLFSSL_ALPN_MATCH = 1
WOLFSSL_ALPN_MATCH = 1,
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2,
WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4,
};
enum {
@ -1363,7 +1366,8 @@ enum {
};
WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
unsigned int protocol_name_listSz);
unsigned int protocol_name_listSz,
unsigned char options);
WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name,
unsigned short *size);