mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-04 21:24:43 +02:00
dtls13: record number encryption and decryption
This commit is contained in:
committed by
David Garske
parent
60834ba516
commit
de04973051
189
src/dtls13.c
189
src/dtls13.c
@@ -27,8 +27,17 @@
|
|||||||
|
|
||||||
#ifdef WOLFSSL_DTLS13
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
|
||||||
#include <wolfssl/ssl.h>
|
#include <wolfssl/error-ssl.h>
|
||||||
#include <wolfssl/internal.h>
|
#include <wolfssl/internal.h>
|
||||||
|
#include <wolfssl/ssl.h>
|
||||||
|
#include <wolfssl/wolfcrypt/aes.h>
|
||||||
|
|
||||||
|
#ifdef NO_INLINE
|
||||||
|
#include <wolfssl/wolfcrypt/misc.h>
|
||||||
|
#else
|
||||||
|
#define WOLFSSL_MISC_INCLUDED
|
||||||
|
#include <wolfcrypt/src/misc.c>
|
||||||
|
#endif
|
||||||
|
|
||||||
WOLFSSL_METHOD* wolfDTLSv1_3_client_method_ex(void* heap)
|
WOLFSSL_METHOD* wolfDTLSv1_3_client_method_ex(void* heap)
|
||||||
{
|
{
|
||||||
@@ -70,4 +79,182 @@ WOLFSSL_METHOD* wolfDTLSv1_3_server_method(void)
|
|||||||
return wolfDTLSv1_3_server_method_ex(NULL);
|
return wolfDTLSv1_3_server_method_ex(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SN_LABEL_SZ 2
|
||||||
|
static const byte snLabel[SN_LABEL_SZ + 1] = "sn";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dtls13DeriveSnKeys() - derive the key used to encrypt the record number
|
||||||
|
* @ssl: ssl object
|
||||||
|
* @provision: which side (CLIENT or SERVER) to provision
|
||||||
|
*/
|
||||||
|
int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision)
|
||||||
|
{
|
||||||
|
byte key_dig[MAX_PRF_DIG];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (provision & PROVISION_CLIENT) {
|
||||||
|
WOLFSSL_MSG("Derive SN Client key");
|
||||||
|
ret = Tls13DeriveKey(ssl, key_dig, ssl->specs.key_size,
|
||||||
|
ssl->clientSecret, snLabel, SN_LABEL_SZ, ssl->specs.mac_algorithm,
|
||||||
|
0);
|
||||||
|
if (ret != 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
XMEMCPY(ssl->keys.client_sn_key, key_dig, ssl->specs.key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provision & PROVISION_SERVER) {
|
||||||
|
WOLFSSL_MSG("Derive SN Server key");
|
||||||
|
ret = Tls13DeriveKey(ssl, key_dig, ssl->specs.key_size,
|
||||||
|
ssl->serverSecret, snLabel, SN_LABEL_SZ, ssl->specs.mac_algorithm,
|
||||||
|
0);
|
||||||
|
if (ret != 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
XMEMCPY(ssl->keys.server_sn_key, key_dig, ssl->specs.key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
ForceZero(key_dig, MAX_PRF_DIG);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Dtls13InitAesCipher(WOLFSSL* ssl, RecordNumberCiphers* cipher,
|
||||||
|
const byte* key, word16 keySize)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
if (cipher->aes == NULL) {
|
||||||
|
cipher->aes =
|
||||||
|
(Aes*)XMALLOC(sizeof(Aes), ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
|
if (cipher->aes == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wc_AesFree(cipher->aes);
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMSET(cipher->aes, 0, sizeof(*cipher->aes));
|
||||||
|
|
||||||
|
ret = wc_AesInit(cipher->aes, ssl->heap, INVALID_DEVID);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return wc_AesSetKey(cipher->aes, key, keySize, NULL, AES_ENCRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CHACHA
|
||||||
|
static int Dtls13InitChaChaCipher(RecordNumberCiphers* c, byte* key,
|
||||||
|
word16 keySize, void* heap)
|
||||||
|
{
|
||||||
|
(void)heap;
|
||||||
|
|
||||||
|
if (c->chacha == NULL) {
|
||||||
|
c->chacha = (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
|
||||||
|
|
||||||
|
if (c->chacha == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wc_Chacha_SetKey(c->chacha, key, keySize);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_CHACHA */
|
||||||
|
|
||||||
|
int Dtls13SetRecordNumberKeys(WOLFSSL* ssl, enum encrypt_side side)
|
||||||
|
{
|
||||||
|
RecordNumberCiphers* enc = NULL;
|
||||||
|
RecordNumberCiphers* dec = NULL;
|
||||||
|
byte *encKey, *decKey;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (ssl == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (side) {
|
||||||
|
case ENCRYPT_SIDE_ONLY:
|
||||||
|
enc = &ssl->dtlsRecordNumberEncrypt;
|
||||||
|
break;
|
||||||
|
case DECRYPT_SIDE_ONLY:
|
||||||
|
dec = &ssl->dtlsRecordNumberDecrypt;
|
||||||
|
break;
|
||||||
|
case ENCRYPT_AND_DECRYPT_SIDE:
|
||||||
|
enc = &ssl->dtlsRecordNumberEncrypt;
|
||||||
|
dec = &ssl->dtlsRecordNumberDecrypt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enc) {
|
||||||
|
if (ssl->options.side == WOLFSSL_CLIENT_END)
|
||||||
|
encKey = ssl->keys.client_sn_key;
|
||||||
|
else
|
||||||
|
encKey = ssl->keys.server_sn_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dec) {
|
||||||
|
if (ssl->options.side == WOLFSSL_CLIENT_END)
|
||||||
|
decKey = ssl->keys.server_sn_key;
|
||||||
|
else
|
||||||
|
decKey = ssl->keys.client_sn_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DTLSv1.3 supports only AEAD algorithm. */
|
||||||
|
#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
|
||||||
|
if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm ||
|
||||||
|
ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm) {
|
||||||
|
|
||||||
|
if (enc) {
|
||||||
|
ret = Dtls13InitAesCipher(ssl, enc, encKey, ssl->specs.key_size);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Provisioning AES Record Number enc key:");
|
||||||
|
WOLFSSL_BUFFER(encKey, ssl->specs.key_size);
|
||||||
|
#endif /* WOLFSSL_DEBUG_TLS */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dec) {
|
||||||
|
ret = Dtls13InitAesCipher(ssl, dec, decKey, ssl->specs.key_size);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Provisioning AES Record Number dec key:");
|
||||||
|
WOLFSSL_BUFFER(decKey, ssl->specs.key_size);
|
||||||
|
#endif /* WOLFSSL_DEBUG_TLS */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* BUILD_AESGCM || HAVE_AESCCM */
|
||||||
|
|
||||||
|
#ifdef HAVE_CHACHA
|
||||||
|
if (ssl->specs.bulk_cipher_algorithm == wolfssl_chacha) {
|
||||||
|
if (enc) {
|
||||||
|
ret = Dtls13InitChaChaCipher(enc, encKey, ssl->specs.key_size,
|
||||||
|
ssl->heap);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Provisioning CHACHA Record Number enc key:");
|
||||||
|
WOLFSSL_BUFFER(encKey, ssl->specs.key_size);
|
||||||
|
#endif /* WOLFSSL_DEBUG_TLS */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dec) {
|
||||||
|
ret = Dtls13InitChaChaCipher(dec, decKey, ssl->specs.key_size,
|
||||||
|
ssl->heap);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#ifdef WOLFSSL_DEBUG_TLS
|
||||||
|
WOLFSSL_MSG("Provisioning CHACHA Record Number dec key:");
|
||||||
|
WOLFSSL_BUFFER(decKey, ssl->specs.key_size);
|
||||||
|
#endif /* WOLFSSL_DEBUG_TLS */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_CHACHA */
|
||||||
|
|
||||||
|
return NOT_COMPILED_IN;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
@@ -2589,6 +2589,14 @@ void InitCiphers(WOLFSSL* ssl)
|
|||||||
#ifdef HAVE_ONE_TIME_AUTH
|
#ifdef HAVE_ONE_TIME_AUTH
|
||||||
ssl->auth.setup = 0;
|
ssl->auth.setup = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
XMEMSET(&ssl->dtlsRecordNumberEncrypt, 0,
|
||||||
|
sizeof(ssl->dtlsRecordNumberEncrypt));
|
||||||
|
XMEMSET(&ssl->dtlsRecordNumberDecrypt, 0,
|
||||||
|
sizeof(ssl->dtlsRecordNumberEncrypt));
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2642,6 +2650,29 @@ void FreeCiphers(WOLFSSL* ssl)
|
|||||||
XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
#ifdef BUILD_AES
|
||||||
|
if (ssl->dtlsRecordNumberEncrypt.aes != NULL) {
|
||||||
|
wc_AesFree(ssl->dtlsRecordNumberEncrypt.aes);
|
||||||
|
XFREE(ssl->dtlsRecordNumberEncrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
|
ssl->dtlsRecordNumberEncrypt.aes = NULL;
|
||||||
|
}
|
||||||
|
if (ssl->dtlsRecordNumberDecrypt.aes != NULL) {
|
||||||
|
wc_AesFree(ssl->dtlsRecordNumberDecrypt.aes);
|
||||||
|
XFREE(ssl->dtlsRecordNumberDecrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
|
ssl->dtlsRecordNumberDecrypt.aes = NULL;
|
||||||
|
}
|
||||||
|
#endif /* BUILD_AES */
|
||||||
|
#ifdef HAVE_CHACHA
|
||||||
|
XFREE(ssl->dtlsRecordNumberEncrypt.chacha,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
|
XFREE(ssl->dtlsRecordNumberDecrypt.chacha,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||||
|
ssl->dtlsRecordNumberEncrypt.chacha = NULL;
|
||||||
|
ssl->dtlsRecordNumberDecrypt.chacha = NULL;
|
||||||
|
#endif /* HAVE_CHACHA */
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2959,6 +2959,11 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
|
|||||||
ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3);
|
ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
if (ret == 0 && ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
|
||||||
|
ret = Dtls13SetRecordNumberKeys(ssl, side);
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
#ifdef HAVE_SECURE_RENEGOTIATION
|
#ifdef HAVE_SECURE_RENEGOTIATION
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
if (ret == 0 && ssl->options.dtls) {
|
if (ret == 0 && ssl->options.dtls) {
|
||||||
|
33
src/tls13.c
33
src/tls13.c
@@ -153,6 +153,11 @@
|
|||||||
/* The protocol label for TLS v1.3. */
|
/* The protocol label for TLS v1.3. */
|
||||||
static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
|
static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
#define DTLS13_PROTOCOL_LABEL_SZ 6
|
||||||
|
static const byte dtls13ProtocolLabel[DTLS13_PROTOCOL_LABEL_SZ + 1] = "dtls13";
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
/* Derive a key from a message.
|
/* Derive a key from a message.
|
||||||
*
|
*
|
||||||
* ssl The SSL/TLS object.
|
* ssl The SSL/TLS object.
|
||||||
@@ -234,7 +239,15 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
|
|||||||
protocol = tls13ProtocolLabel;
|
protocol = tls13ProtocolLabel;
|
||||||
protocolLen = TLS13_PROTOCOL_LABEL_SZ;
|
protocolLen = TLS13_PROTOCOL_LABEL_SZ;
|
||||||
break;
|
break;
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
case DTLSv1_3_MINOR:
|
||||||
|
if (!ssl->options.dtls)
|
||||||
|
return VERSION_ERROR;
|
||||||
|
|
||||||
|
protocol = dtls13ProtocolLabel;
|
||||||
|
protocolLen = DTLS13_PROTOCOL_LABEL_SZ;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
default:
|
default:
|
||||||
return VERSION_ERROR;
|
return VERSION_ERROR;
|
||||||
}
|
}
|
||||||
@@ -308,10 +321,16 @@ int Tls13DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Only one protocol version defined at this time. */
|
|
||||||
protocol = tls13ProtocolLabel;
|
protocol = tls13ProtocolLabel;
|
||||||
protocolLen = TLS13_PROTOCOL_LABEL_SZ;
|
protocolLen = TLS13_PROTOCOL_LABEL_SZ;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
if (ssl->options.dtls) {
|
||||||
|
protocol = dtls13ProtocolLabel;
|
||||||
|
protocolLen = DTLS13_PROTOCOL_LABEL_SZ;
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
if (outputLen == -1)
|
if (outputLen == -1)
|
||||||
outputLen = hashSz;
|
outputLen = hashSz;
|
||||||
if (includeMsgs)
|
if (includeMsgs)
|
||||||
@@ -1263,6 +1282,18 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
|
|||||||
/* Store keys and IVs but don't activate them. */
|
/* Store keys and IVs but don't activate them. */
|
||||||
ret = StoreKeys(ssl, key_dig, provision);
|
ret = StoreKeys(ssl, key_dig, provision);
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
if (ret != 0)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (ssl->options.dtls) {
|
||||||
|
ret = Dtls13DeriveSnKeys(ssl, provision);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
end:
|
end:
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
|
XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
|
||||||
|
@@ -2242,6 +2242,11 @@ typedef struct Keys {
|
|||||||
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
|
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
byte client_sn_key[MAX_SYM_KEY_SIZE];
|
||||||
|
byte server_sn_key[MAX_SYM_KEY_SIZE];
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
word32 peer_sequence_number_hi;
|
word32 peer_sequence_number_hi;
|
||||||
word32 peer_sequence_number_lo;
|
word32 peer_sequence_number_lo;
|
||||||
word32 sequence_number_hi;
|
word32 sequence_number_hi;
|
||||||
@@ -3314,6 +3319,16 @@ typedef struct Ciphers {
|
|||||||
#endif
|
#endif
|
||||||
} Ciphers;
|
} Ciphers;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
typedef struct RecordNumberCiphers {
|
||||||
|
#if defined(BUILD_AES) || defined(BUILD_AESGCM)
|
||||||
|
Aes *aes;
|
||||||
|
#endif /* BUILD_AES || BUILD_AESGCM */
|
||||||
|
#ifdef HAVE_CHACHA
|
||||||
|
ChaCha *chacha;
|
||||||
|
#endif
|
||||||
|
} RecordNumberCiphers;
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
#ifdef HAVE_ONE_TIME_AUTH
|
#ifdef HAVE_ONE_TIME_AUTH
|
||||||
/* Ciphers for one time authentication such as poly1305 */
|
/* Ciphers for one time authentication such as poly1305 */
|
||||||
@@ -4496,6 +4511,11 @@ struct WOLFSSL {
|
|||||||
* (selected profiles - up to 16) */
|
* (selected profiles - up to 16) */
|
||||||
word16 dtlsSrtpId; /* DTLS-with-SRTP profile ID selected */
|
word16 dtlsSrtpId; /* DTLS-with-SRTP profile ID selected */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
RecordNumberCiphers dtlsRecordNumberEncrypt;
|
||||||
|
RecordNumberCiphers dtlsRecordNumberDecrypt;
|
||||||
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
#endif /* WOLFSSL_DTLS */
|
#endif /* WOLFSSL_DTLS */
|
||||||
#ifdef WOLFSSL_CALLBACKS
|
#ifdef WOLFSSL_CALLBACKS
|
||||||
TimeoutInfo timeoutInfo; /* info saved during handshake */
|
TimeoutInfo timeoutInfo; /* info saved during handshake */
|
||||||
@@ -5240,6 +5260,10 @@ WOLFSSL_LOCAL word32 nid2oid(int nid, int grp);
|
|||||||
|
|
||||||
#ifdef WOLFSSL_DTLS13
|
#ifdef WOLFSSL_DTLS13
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision);
|
||||||
|
WOLFSSL_LOCAL int Dtls13SetRecordNumberKeys(WOLFSSL* ssl,
|
||||||
|
enum encrypt_side side);
|
||||||
|
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
#ifdef WOLFSSL_STATIC_EPHEMERAL
|
#ifdef WOLFSSL_STATIC_EPHEMERAL
|
||||||
WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr);
|
WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr);
|
||||||
|
Reference in New Issue
Block a user