forked from wolfSSL/wolfssl
Merge branch 'master' of github.com:cyassl/cyassl
This commit is contained in:
@@ -1261,7 +1261,8 @@ struct CYASSL_CTX {
|
|||||||
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
||||||
#endif
|
#endif
|
||||||
#ifdef ATOMIC_USER
|
#ifdef ATOMIC_USER
|
||||||
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Callback */
|
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */
|
||||||
|
CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1403,6 +1404,7 @@ typedef struct Keys {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
word32 encryptSz; /* last size of encrypted data */
|
word32 encryptSz; /* last size of encrypted data */
|
||||||
|
word32 padSz; /* how much to advance after decrypt part */
|
||||||
byte encryptionOn; /* true after change cipher spec */
|
byte encryptionOn; /* true after change cipher spec */
|
||||||
byte decryptedCur; /* only decrypt current record once */
|
byte decryptedCur; /* only decrypt current record once */
|
||||||
} Keys;
|
} Keys;
|
||||||
@@ -1827,6 +1829,7 @@ struct CYASSL {
|
|||||||
CYASSL_ALERT_HISTORY alert_history;
|
CYASSL_ALERT_HISTORY alert_history;
|
||||||
#ifdef ATOMIC_USER
|
#ifdef ATOMIC_USER
|
||||||
void* MacEncryptCtx; /* Atomic User Mac/Encrypt Callback Context */
|
void* MacEncryptCtx; /* Atomic User Mac/Encrypt Callback Context */
|
||||||
|
void* DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
15
cyassl/ssl.h
15
cyassl/ssl.h
@@ -951,6 +951,14 @@ CYASSL_API void CyaSSL_CTX_SetMacEncryptCb(CYASSL_CTX*, CallbackMacEncrypt);
|
|||||||
CYASSL_API void CyaSSL_SetMacEncryptCtx(CYASSL* ssl, void *ctx);
|
CYASSL_API void CyaSSL_SetMacEncryptCtx(CYASSL* ssl, void *ctx);
|
||||||
CYASSL_API void* CyaSSL_GetMacEncryptCtx(CYASSL* ssl);
|
CYASSL_API void* CyaSSL_GetMacEncryptCtx(CYASSL* ssl);
|
||||||
|
|
||||||
|
typedef int (*CallbackDecryptVerify)(CYASSL* ssl,
|
||||||
|
unsigned char* decOut, const unsigned char* decIn,
|
||||||
|
unsigned int decSz, int content, int verify, unsigned int* padSz,
|
||||||
|
void* ctx);
|
||||||
|
CYASSL_API void CyaSSL_CTX_SetDecryptVerifyCb(CYASSL_CTX*,
|
||||||
|
CallbackDecryptVerify);
|
||||||
|
CYASSL_API void CyaSSL_SetDecryptVerifyCtx(CYASSL* ssl, void *ctx);
|
||||||
|
CYASSL_API void* CyaSSL_GetDecryptVerifyCtx(CYASSL* ssl);
|
||||||
|
|
||||||
CYASSL_API const unsigned char* CyaSSL_GetMacSecret(CYASSL*, int);
|
CYASSL_API const unsigned char* CyaSSL_GetMacSecret(CYASSL*, int);
|
||||||
CYASSL_API const unsigned char* CyaSSL_GetClientWriteKey(CYASSL*);
|
CYASSL_API const unsigned char* CyaSSL_GetClientWriteKey(CYASSL*);
|
||||||
@@ -959,9 +967,13 @@ CYASSL_API const unsigned char* CyaSSL_GetServerWriteKey(CYASSL*);
|
|||||||
CYASSL_API const unsigned char* CyaSSL_GetServerWriteIV(CYASSL*);
|
CYASSL_API const unsigned char* CyaSSL_GetServerWriteIV(CYASSL*);
|
||||||
CYASSL_API int CyaSSL_GetKeySize(CYASSL*);
|
CYASSL_API int CyaSSL_GetKeySize(CYASSL*);
|
||||||
CYASSL_API int CyaSSL_GetSide(CYASSL*);
|
CYASSL_API int CyaSSL_GetSide(CYASSL*);
|
||||||
|
CYASSL_API int CyaSSL_IsTLSv1_1(CYASSL*);
|
||||||
CYASSL_API int CyaSSL_GetBulkCipher(CYASSL*);
|
CYASSL_API int CyaSSL_GetBulkCipher(CYASSL*);
|
||||||
|
CYASSL_API int CyaSSL_GetCipherBlockSize(CYASSL*);
|
||||||
|
CYASSL_API int CyaSSL_GetAeadMacSize(CYASSL*);
|
||||||
CYASSL_API int CyaSSL_GetHmacSize(CYASSL*);
|
CYASSL_API int CyaSSL_GetHmacSize(CYASSL*);
|
||||||
CYASSL_API int CyaSSL_GetHmacType(CYASSL*);
|
CYASSL_API int CyaSSL_GetHmacType(CYASSL*);
|
||||||
|
CYASSL_API int CyaSSL_GetCipherType(CYASSL*);
|
||||||
CYASSL_API int CyaSSL_SetTlsHmacInner(CYASSL*, unsigned char*,
|
CYASSL_API int CyaSSL_SetTlsHmacInner(CYASSL*, unsigned char*,
|
||||||
unsigned int, int, int);
|
unsigned int, int, int);
|
||||||
|
|
||||||
@@ -969,6 +981,9 @@ CYASSL_API int CyaSSL_SetTlsHmacInner(CYASSL*, unsigned char*,
|
|||||||
enum {
|
enum {
|
||||||
CYASSL_SERVER_END = 0,
|
CYASSL_SERVER_END = 0,
|
||||||
CYASSL_CLIENT_END = 1,
|
CYASSL_CLIENT_END = 1,
|
||||||
|
CYASSL_BLOCK_TYPE = 2,
|
||||||
|
CYASSL_STREAM_TYPE = 3,
|
||||||
|
CYASSL_AEAD_TYPE = 4,
|
||||||
CYASSL_TLS_HMAC_INNER_SZ = 13 /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */
|
CYASSL_TLS_HMAC_INNER_SZ = 13 /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
109
cyassl/test.h
109
cyassl/test.h
@@ -1301,6 +1301,13 @@ typedef struct AtomicEncCtx {
|
|||||||
} AtomicEncCtx;
|
} AtomicEncCtx;
|
||||||
|
|
||||||
|
|
||||||
|
/* Atomic Decrypt Context example */
|
||||||
|
typedef struct AtomicDecCtx {
|
||||||
|
int keySetup; /* have we done key setup yet */
|
||||||
|
Aes aes; /* for aes example */
|
||||||
|
} AtomicDecCtx;
|
||||||
|
|
||||||
|
|
||||||
static INLINE int myMacEncryptCb(CYASSL* ssl, unsigned char* macOut,
|
static INLINE int myMacEncryptCb(CYASSL* ssl, unsigned char* macOut,
|
||||||
const unsigned char* macIn, unsigned int macInSz, int macContent,
|
const unsigned char* macIn, unsigned int macInSz, int macContent,
|
||||||
int macVerify, unsigned char* encOut, const unsigned char* encIn,
|
int macVerify, unsigned char* encOut, const unsigned char* encIn,
|
||||||
@@ -1360,24 +1367,126 @@ static INLINE int myMacEncryptCb(CYASSL* ssl, unsigned char* macOut,
|
|||||||
return AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz);
|
return AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static INLINE int myDecryptVerifyCb(CYASSL* ssl,
|
||||||
|
unsigned char* decOut, const unsigned char* decIn,
|
||||||
|
unsigned int decSz, int macContent, int macVerify,
|
||||||
|
unsigned int* padSz, void* ctx)
|
||||||
|
{
|
||||||
|
AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx;
|
||||||
|
int ret = 0;
|
||||||
|
int macInSz = 0;
|
||||||
|
int ivExtra = 0;
|
||||||
|
int digestSz = CyaSSL_GetHmacSize(ssl);
|
||||||
|
unsigned int pad = 0;
|
||||||
|
unsigned int padByte = 0;
|
||||||
|
Hmac hmac;
|
||||||
|
byte myInner[CYASSL_TLS_HMAC_INNER_SZ];
|
||||||
|
byte verify[INNER_HASH_SIZE];
|
||||||
|
const char* tlsStr = "TLS";
|
||||||
|
|
||||||
|
/* example supports (d)tls aes */
|
||||||
|
if (CyaSSL_GetBulkCipher(ssl) != cyassl_aes) {
|
||||||
|
printf("myMacEncryptCb not using AES\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(CyaSSL_get_version(ssl), tlsStr) == NULL) {
|
||||||
|
printf("myMacEncryptCb not using (D)TLS\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*decrypt */
|
||||||
|
if (decCtx->keySetup == 0) {
|
||||||
|
int keyLen = CyaSSL_GetKeySize(ssl);
|
||||||
|
const byte* key;
|
||||||
|
const byte* iv;
|
||||||
|
|
||||||
|
/* decrypt is from other side (peer) */
|
||||||
|
if (CyaSSL_GetSide(ssl) == CYASSL_SERVER_END) {
|
||||||
|
key = CyaSSL_GetClientWriteKey(ssl);
|
||||||
|
iv = CyaSSL_GetClientWriteIV(ssl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
key = CyaSSL_GetServerWriteKey(ssl);
|
||||||
|
iv = CyaSSL_GetServerWriteIV(ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION);
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("AesSetKey failed in myDecryptVerifyCb\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
decCtx->keySetup = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decrypt */
|
||||||
|
ret = AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz);
|
||||||
|
|
||||||
|
if (CyaSSL_GetCipherType(ssl) == CYASSL_AEAD_TYPE) {
|
||||||
|
*padSz = CyaSSL_GetAeadMacSize(ssl);
|
||||||
|
return 0; /* hmac, not needed if aead mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CyaSSL_GetCipherType(ssl) == CYASSL_BLOCK_TYPE) {
|
||||||
|
pad = *(decOut + decSz - 1);
|
||||||
|
padByte = 1;
|
||||||
|
if (CyaSSL_IsTLSv1_1(ssl))
|
||||||
|
ivExtra = CyaSSL_GetCipherBlockSize(ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
*padSz = CyaSSL_GetHmacSize(ssl) + pad + padByte;
|
||||||
|
macInSz = decSz - ivExtra - digestSz - pad - padByte;
|
||||||
|
|
||||||
|
CyaSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
|
||||||
|
|
||||||
|
HmacSetKey(&hmac, CyaSSL_GetHmacType(ssl),
|
||||||
|
CyaSSL_GetMacSecret(ssl, macVerify), digestSz);
|
||||||
|
HmacUpdate(&hmac, myInner, sizeof(myInner));
|
||||||
|
HmacUpdate(&hmac, decOut + ivExtra, macInSz);
|
||||||
|
HmacFinal(&hmac, verify);
|
||||||
|
|
||||||
|
if (memcmp(verify, decOut + decSz - digestSz - pad - padByte,
|
||||||
|
digestSz) != 0) {
|
||||||
|
printf("myDecryptVerify verify failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static INLINE void SetupAtomicUser(CYASSL_CTX* ctx, CYASSL* ssl)
|
static INLINE void SetupAtomicUser(CYASSL_CTX* ctx, CYASSL* ssl)
|
||||||
{
|
{
|
||||||
AtomicEncCtx* encCtx;
|
AtomicEncCtx* encCtx;
|
||||||
|
AtomicDecCtx* decCtx;
|
||||||
|
|
||||||
encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx));
|
encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx));
|
||||||
if (encCtx == NULL)
|
if (encCtx == NULL)
|
||||||
err_sys("AtomicEncCtx malloc failed");
|
err_sys("AtomicEncCtx malloc failed");
|
||||||
memset(encCtx, 0, sizeof(AtomicEncCtx));
|
memset(encCtx, 0, sizeof(AtomicEncCtx));
|
||||||
|
|
||||||
|
decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx));
|
||||||
|
if (decCtx == NULL) {
|
||||||
|
free(encCtx);
|
||||||
|
err_sys("AtomicDecCtx malloc failed");
|
||||||
|
}
|
||||||
|
memset(decCtx, 0, sizeof(AtomicDecCtx));
|
||||||
|
|
||||||
CyaSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb);
|
CyaSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb);
|
||||||
CyaSSL_SetMacEncryptCtx(ssl, encCtx);
|
CyaSSL_SetMacEncryptCtx(ssl, encCtx);
|
||||||
|
|
||||||
|
CyaSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb);
|
||||||
|
CyaSSL_SetDecryptVerifyCtx(ssl, decCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static INLINE void FreeAtomicUser(CYASSL* ssl)
|
static INLINE void FreeAtomicUser(CYASSL* ssl)
|
||||||
{
|
{
|
||||||
AtomicEncCtx* encCtx = CyaSSL_GetMacEncryptCtx(ssl);
|
AtomicEncCtx* encCtx = CyaSSL_GetMacEncryptCtx(ssl);
|
||||||
|
AtomicDecCtx* decCtx = CyaSSL_GetDecryptVerifyCtx(ssl);
|
||||||
|
|
||||||
|
free(decCtx);
|
||||||
free(encCtx);
|
free(encCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
238
src/internal.c
238
src/internal.c
@@ -430,6 +430,7 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef ATOMIC_USER
|
#ifdef ATOMIC_USER
|
||||||
ctx->MacEncryptCb = NULL;
|
ctx->MacEncryptCb = NULL;
|
||||||
|
ctx->DecryptVerifyCb = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (InitMutex(&ctx->countMutex) < 0) {
|
if (InitMutex(&ctx->countMutex) < 0) {
|
||||||
@@ -1379,6 +1380,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
|||||||
ssl->dtls_msg_list = NULL;
|
ssl->dtls_msg_list = NULL;
|
||||||
#endif
|
#endif
|
||||||
ssl->keys.encryptSz = 0;
|
ssl->keys.encryptSz = 0;
|
||||||
|
ssl->keys.padSz = 0;
|
||||||
ssl->keys.encryptionOn = 0; /* initially off */
|
ssl->keys.encryptionOn = 0; /* initially off */
|
||||||
ssl->keys.decryptedCur = 0; /* initially off */
|
ssl->keys.decryptedCur = 0; /* initially off */
|
||||||
ssl->options.sessionCacheOff = ctx->sessionCacheOff;
|
ssl->options.sessionCacheOff = ctx->sessionCacheOff;
|
||||||
@@ -1480,6 +1482,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
|||||||
InitCipherSpecs(&ssl->specs);
|
InitCipherSpecs(&ssl->specs);
|
||||||
#ifdef ATOMIC_USER
|
#ifdef ATOMIC_USER
|
||||||
ssl->MacEncryptCtx = NULL;
|
ssl->MacEncryptCtx = NULL;
|
||||||
|
ssl->DecryptVerifyCtx = NULL;
|
||||||
#endif
|
#endif
|
||||||
/* all done with init, now can return errors, call other stuff */
|
/* all done with init, now can return errors, call other stuff */
|
||||||
|
|
||||||
@@ -3366,20 +3369,7 @@ static int DoHelloRequest(CYASSL* ssl, const byte* input, word32* inOutIdx)
|
|||||||
int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
|
int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
|
||||||
{
|
{
|
||||||
int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
|
int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
|
||||||
int headerSz = HANDSHAKE_HEADER_SZ;
|
word32 idx = *inOutIdx;
|
||||||
word32 macSz = finishedSz + HANDSHAKE_HEADER_SZ,
|
|
||||||
idx = *inOutIdx,
|
|
||||||
padSz = ssl->keys.encryptSz - HANDSHAKE_HEADER_SZ - finishedSz -
|
|
||||||
ssl->specs.hash_size;
|
|
||||||
const byte* mac;
|
|
||||||
|
|
||||||
#ifdef CYASSL_DTLS
|
|
||||||
if (ssl->options.dtls) {
|
|
||||||
headerSz += DTLS_HANDSHAKE_EXTRA;
|
|
||||||
macSz += DTLS_HANDSHAKE_EXTRA;
|
|
||||||
padSz -= DTLS_HANDSHAKE_EXTRA;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CYASSL_CALLBACKS
|
#ifdef CYASSL_CALLBACKS
|
||||||
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
|
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
|
||||||
@@ -3391,31 +3381,8 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
|
|||||||
return VERIFY_FINISHED_ERROR;
|
return VERIFY_FINISHED_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl->specs.cipher_type != aead) {
|
|
||||||
byte verifyMAC[MAX_DIGEST_SIZE];
|
|
||||||
ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
|
|
||||||
handshake, 1);
|
|
||||||
idx += finishedSz;
|
idx += finishedSz;
|
||||||
|
idx += ssl->keys.padSz;
|
||||||
/* read mac and fill */
|
|
||||||
mac = input + idx;
|
|
||||||
idx += ssl->specs.hash_size;
|
|
||||||
|
|
||||||
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
|
|
||||||
padSz -= ssl->specs.block_size;
|
|
||||||
|
|
||||||
idx += padSz;
|
|
||||||
|
|
||||||
/* verify mac */
|
|
||||||
if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size) != 0) {
|
|
||||||
CYASSL_MSG("Verify finished error on mac");
|
|
||||||
return VERIFY_MAC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
idx += (finishedSz + ssl->specs.aead_mac_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ssl->options.side == CYASSL_CLIENT_END) {
|
if (ssl->options.side == CYASSL_CLIENT_END) {
|
||||||
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
|
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
|
||||||
@@ -3865,6 +3832,7 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
|
static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
|
||||||
word32 sz)
|
word32 sz)
|
||||||
{
|
{
|
||||||
@@ -4035,32 +4003,6 @@ static int SanityCheckCipherText(CYASSL* ssl, word32 encryptSz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* decrypt input message in place */
|
|
||||||
static int DecryptMessage(CYASSL* ssl, byte* input, word32 sz, word32* idx)
|
|
||||||
{
|
|
||||||
int decryptResult;
|
|
||||||
int sanityResult = SanityCheckCipherText(ssl, sz);
|
|
||||||
|
|
||||||
if (sanityResult != 0)
|
|
||||||
return sanityResult;
|
|
||||||
|
|
||||||
decryptResult = Decrypt(ssl, input, input, sz);
|
|
||||||
|
|
||||||
if (decryptResult == 0)
|
|
||||||
{
|
|
||||||
ssl->keys.encryptSz = sz;
|
|
||||||
ssl->keys.decryptedCur = 1;
|
|
||||||
|
|
||||||
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
|
|
||||||
*idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
|
|
||||||
if (ssl->specs.cipher_type == aead)
|
|
||||||
*idx += AEAD_EXP_IV_SZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return decryptResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_OLD_TLS
|
#ifndef NO_OLD_TLS
|
||||||
|
|
||||||
static INLINE void Md5Rounds(int rounds, const byte* data, int sz)
|
static INLINE void Md5Rounds(int rounds, const byte* data, int sz)
|
||||||
@@ -4284,7 +4226,7 @@ static INLINE int GetRounds(int pLen, int padLen, int t)
|
|||||||
|
|
||||||
/* timing resistant pad/verify check, return 0 on success */
|
/* timing resistant pad/verify check, return 0 on success */
|
||||||
static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
||||||
int pLen)
|
int pLen, int content)
|
||||||
{
|
{
|
||||||
byte verify[MAX_DIGEST_SIZE];
|
byte verify[MAX_DIGEST_SIZE];
|
||||||
byte dummy[MAX_PAD_SIZE];
|
byte dummy[MAX_PAD_SIZE];
|
||||||
@@ -4294,7 +4236,7 @@ static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
|||||||
if ( (t + padLen + 1) > pLen) {
|
if ( (t + padLen + 1) > pLen) {
|
||||||
CYASSL_MSG("Plain Len not long enough for pad/mac");
|
CYASSL_MSG("Plain Len not long enough for pad/mac");
|
||||||
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE);
|
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE);
|
||||||
ssl->hmac(ssl, verify, input, pLen - t, application_data, 1);
|
ssl->hmac(ssl, verify, input, pLen - t, content, 1);
|
||||||
ConstantCompare(verify, input + pLen - t, t);
|
ConstantCompare(verify, input + pLen - t, t);
|
||||||
|
|
||||||
return VERIFY_MAC_ERROR;
|
return VERIFY_MAC_ERROR;
|
||||||
@@ -4303,14 +4245,14 @@ static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
|||||||
if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) {
|
if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) {
|
||||||
CYASSL_MSG("PadCheck failed");
|
CYASSL_MSG("PadCheck failed");
|
||||||
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
|
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
|
||||||
ssl->hmac(ssl, verify, input, pLen - t, application_data, 1);
|
ssl->hmac(ssl, verify, input, pLen - t, content, 1);
|
||||||
ConstantCompare(verify, input + pLen - t, t);
|
ConstantCompare(verify, input + pLen - t, t);
|
||||||
|
|
||||||
return VERIFY_MAC_ERROR;
|
return VERIFY_MAC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
|
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
|
||||||
ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, application_data, 1);
|
ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, content, 1);
|
||||||
|
|
||||||
CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy);
|
CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy);
|
||||||
|
|
||||||
@@ -4326,17 +4268,13 @@ static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
|||||||
int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||||
{
|
{
|
||||||
word32 msgSz = ssl->keys.encryptSz;
|
word32 msgSz = ssl->keys.encryptSz;
|
||||||
word32 pad = 0,
|
word32 idx = *inOutIdx;
|
||||||
padByte = 0,
|
int dataSz;
|
||||||
idx = *inOutIdx,
|
|
||||||
digestSz = ssl->specs.hash_size;
|
|
||||||
int dataSz, ret;
|
|
||||||
int ivExtra = 0;
|
int ivExtra = 0;
|
||||||
byte* rawData = input + idx; /* keep current for hmac */
|
byte* rawData = input + idx; /* keep current for hmac */
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
|
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
|
||||||
#endif
|
#endif
|
||||||
byte verify[MAX_DIGEST_SIZE];
|
|
||||||
|
|
||||||
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
|
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
|
||||||
CYASSL_MSG("Received App data before handshake complete");
|
CYASSL_MSG("Received App data before handshake complete");
|
||||||
@@ -4347,35 +4285,12 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
|||||||
if (ssl->specs.cipher_type == block) {
|
if (ssl->specs.cipher_type == block) {
|
||||||
if (ssl->options.tls1_1)
|
if (ssl->options.tls1_1)
|
||||||
ivExtra = ssl->specs.block_size;
|
ivExtra = ssl->specs.block_size;
|
||||||
pad = *(input + idx + msgSz - ivExtra - 1);
|
|
||||||
padByte = 1;
|
|
||||||
|
|
||||||
if (ssl->options.tls) {
|
|
||||||
ret = TimingPadVerify(ssl, input + idx, pad, digestSz,
|
|
||||||
msgSz - ivExtra);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else { /* sslv3, some implementations have bad padding */
|
|
||||||
ssl->hmac(ssl, verify, rawData, msgSz - digestSz - pad - 1,
|
|
||||||
application_data, 1);
|
|
||||||
if (ConstantCompare(verify, rawData + msgSz - digestSz - pad - 1,
|
|
||||||
digestSz) != 0)
|
|
||||||
return VERIFY_MAC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ssl->specs.cipher_type == stream) {
|
|
||||||
ssl->hmac(ssl, verify, rawData, msgSz - digestSz, application_data, 1);
|
|
||||||
if (ConstantCompare(verify, rawData + msgSz - digestSz, digestSz) != 0){
|
|
||||||
return VERIFY_MAC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (ssl->specs.cipher_type == aead) {
|
else if (ssl->specs.cipher_type == aead) {
|
||||||
ivExtra = AEAD_EXP_IV_SZ;
|
ivExtra = AEAD_EXP_IV_SZ;
|
||||||
digestSz = ssl->specs.aead_mac_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dataSz = msgSz - ivExtra - digestSz - pad - padByte;
|
dataSz = msgSz - ivExtra - ssl->keys.padSz;
|
||||||
if (dataSz < 0) {
|
if (dataSz < 0) {
|
||||||
CYASSL_MSG("App data buffer error, malicious input?");
|
CYASSL_MSG("App data buffer error, malicious input?");
|
||||||
return BUFFER_ERROR;
|
return BUFFER_ERROR;
|
||||||
@@ -4397,10 +4312,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
|||||||
ssl->buffers.clearOutputBuffer.length = dataSz;
|
ssl->buffers.clearOutputBuffer.length = dataSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx += digestSz;
|
idx += ssl->keys.padSz;
|
||||||
idx += pad;
|
|
||||||
if (padByte)
|
|
||||||
idx++;
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
/* decompress could be bigger, overwrite after verify */
|
/* decompress could be bigger, overwrite after verify */
|
||||||
@@ -4444,27 +4356,7 @@ static int DoAlert(CYASSL* ssl, byte* input, word32* inOutIdx, int* type)
|
|||||||
CYASSL_ERROR(*type);
|
CYASSL_ERROR(*type);
|
||||||
|
|
||||||
if (ssl->keys.encryptionOn) {
|
if (ssl->keys.encryptionOn) {
|
||||||
if (ssl->specs.cipher_type != aead) {
|
*inOutIdx += ssl->keys.padSz;
|
||||||
int aSz = ALERT_SIZE;
|
|
||||||
const byte* mac;
|
|
||||||
byte verify[MAX_DIGEST_SIZE];
|
|
||||||
int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
|
|
||||||
|
|
||||||
ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
|
|
||||||
|
|
||||||
/* read mac and fill */
|
|
||||||
mac = input + *inOutIdx;
|
|
||||||
*inOutIdx += (ssl->specs.hash_size + padSz);
|
|
||||||
|
|
||||||
/* verify */
|
|
||||||
if (XMEMCMP(mac, verify, ssl->specs.hash_size) != 0) {
|
|
||||||
CYASSL_MSG(" alert verify mac error");
|
|
||||||
return VERIFY_MAC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*inOutIdx += ssl->specs.aead_mac_size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
@@ -4533,11 +4425,61 @@ static int GetInputData(CYASSL *ssl, word32 size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static INLINE int VerifyMac(CYASSL* ssl, const byte* input, word32 msgSz,
|
||||||
|
int content, word32* padSz)
|
||||||
|
{
|
||||||
|
int ivExtra = 0;
|
||||||
|
int ret;
|
||||||
|
word32 pad = 0;
|
||||||
|
word32 padByte = 0;
|
||||||
|
word32 digestSz = ssl->specs.hash_size;
|
||||||
|
byte verify[MAX_DIGEST_SIZE];
|
||||||
|
|
||||||
|
if (ssl->specs.cipher_type == block) {
|
||||||
|
if (ssl->options.tls1_1)
|
||||||
|
ivExtra = ssl->specs.block_size;
|
||||||
|
pad = *(input + msgSz - ivExtra - 1);
|
||||||
|
padByte = 1;
|
||||||
|
|
||||||
|
if (ssl->options.tls) {
|
||||||
|
ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra,
|
||||||
|
content);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else { /* sslv3, some implementations have bad padding */
|
||||||
|
ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1,
|
||||||
|
content, 1);
|
||||||
|
if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
|
||||||
|
digestSz) != 0)
|
||||||
|
return VERIFY_MAC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ssl->specs.cipher_type == stream) {
|
||||||
|
ssl->hmac(ssl, verify, input, msgSz - digestSz, content, 1);
|
||||||
|
if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
|
||||||
|
return VERIFY_MAC_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl->specs.cipher_type == aead) {
|
||||||
|
*padSz = ssl->specs.aead_mac_size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*padSz = digestSz + pad + padByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* process input requests, return 0 is done, 1 is call again to complete, and
|
/* process input requests, return 0 is done, 1 is call again to complete, and
|
||||||
negative number is error */
|
negative number is error */
|
||||||
int ProcessReply(CYASSL* ssl)
|
int ProcessReply(CYASSL* ssl)
|
||||||
{
|
{
|
||||||
int ret = 0, type, readSz;
|
int ret = 0, type, readSz;
|
||||||
|
int atomicUser = 0;
|
||||||
word32 startIdx = 0;
|
word32 startIdx = 0;
|
||||||
#ifndef NO_CYASSL_SERVER
|
#ifndef NO_CYASSL_SERVER
|
||||||
byte b0, b1;
|
byte b0, b1;
|
||||||
@@ -4546,6 +4488,11 @@ int ProcessReply(CYASSL* ssl)
|
|||||||
int used;
|
int used;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ATOMIC_USER
|
||||||
|
if (ssl->ctx->DecryptVerifyCb)
|
||||||
|
atomicUser = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch ((processReply)ssl->options.processReply) {
|
switch ((processReply)ssl->options.processReply) {
|
||||||
|
|
||||||
@@ -4676,14 +4623,53 @@ int ProcessReply(CYASSL* ssl)
|
|||||||
case runProcessingOneMessage:
|
case runProcessingOneMessage:
|
||||||
|
|
||||||
if (ssl->keys.encryptionOn && ssl->keys.decryptedCur == 0) {
|
if (ssl->keys.encryptionOn && ssl->keys.decryptedCur == 0) {
|
||||||
ret = DecryptMessage(ssl, ssl->buffers.inputBuffer.buffer +
|
ret = SanityCheckCipherText(ssl, ssl->curSize);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (atomicUser) {
|
||||||
|
#ifdef ATOMIC_USER
|
||||||
|
ret = ssl->ctx->DecryptVerifyCb(ssl,
|
||||||
|
ssl->buffers.inputBuffer.buffer +
|
||||||
ssl->buffers.inputBuffer.idx,
|
ssl->buffers.inputBuffer.idx,
|
||||||
ssl->curSize,
|
ssl->buffers.inputBuffer.buffer +
|
||||||
&ssl->buffers.inputBuffer.idx);
|
ssl->buffers.inputBuffer.idx,
|
||||||
|
ssl->curSize, ssl->curRL.type, 1,
|
||||||
|
&ssl->keys.padSz, ssl->DecryptVerifyCtx);
|
||||||
|
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
|
||||||
|
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
|
||||||
|
/* go past TLSv1.1 IV */
|
||||||
|
if (ssl->specs.cipher_type == aead)
|
||||||
|
ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
|
||||||
|
#endif /* ATOMIC_USER */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer +
|
||||||
|
ssl->buffers.inputBuffer.idx,
|
||||||
|
ssl->buffers.inputBuffer.buffer +
|
||||||
|
ssl->buffers.inputBuffer.idx,
|
||||||
|
ssl->curSize);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
CYASSL_ERROR(ret);
|
CYASSL_ERROR(ret);
|
||||||
return DECRYPT_ERROR;
|
return DECRYPT_ERROR;
|
||||||
}
|
}
|
||||||
|
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
|
||||||
|
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
|
||||||
|
/* go past TLSv1.1 IV */
|
||||||
|
if (ssl->specs.cipher_type == aead)
|
||||||
|
ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
|
||||||
|
|
||||||
|
ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
|
||||||
|
ssl->buffers.inputBuffer.idx,
|
||||||
|
ssl->curSize, ssl->curRL.type,
|
||||||
|
&ssl->keys.padSz);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
CYASSL_ERROR(ret);
|
||||||
|
return DECRYPT_ERROR;
|
||||||
|
}
|
||||||
|
ssl->keys.encryptSz = ssl->curSize;
|
||||||
|
ssl->keys.decryptedCur = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CYASSL_MSG("received record layer msg");
|
CYASSL_MSG("received record layer msg");
|
||||||
|
69
src/ssl.c
69
src/ssl.c
@@ -830,6 +830,29 @@ void* CyaSSL_GetMacEncryptCtx(CYASSL* ssl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CyaSSL_CTX_SetDecryptVerifyCb(CYASSL_CTX* ctx, CallbackDecryptVerify cb)
|
||||||
|
{
|
||||||
|
if (ctx)
|
||||||
|
ctx->DecryptVerifyCb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CyaSSL_SetDecryptVerifyCtx(CYASSL* ssl, void *ctx)
|
||||||
|
{
|
||||||
|
if (ssl)
|
||||||
|
ssl->DecryptVerifyCtx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* CyaSSL_GetDecryptVerifyCtx(CYASSL* ssl)
|
||||||
|
{
|
||||||
|
if (ssl)
|
||||||
|
return ssl->DecryptVerifyCtx;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const byte* CyaSSL_GetClientWriteKey(CYASSL* ssl)
|
const byte* CyaSSL_GetClientWriteKey(CYASSL* ssl)
|
||||||
{
|
{
|
||||||
if (ssl)
|
if (ssl)
|
||||||
@@ -884,6 +907,52 @@ int CyaSSL_GetBulkCipher(CYASSL* ssl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CyaSSL_GetCipherType(CYASSL* ssl)
|
||||||
|
{
|
||||||
|
if (ssl == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
if (ssl->specs.cipher_type == block)
|
||||||
|
return CYASSL_BLOCK_TYPE;
|
||||||
|
if (ssl->specs.cipher_type == stream)
|
||||||
|
return CYASSL_STREAM_TYPE;
|
||||||
|
if (ssl->specs.cipher_type == aead)
|
||||||
|
return CYASSL_AEAD_TYPE;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CyaSSL_GetCipherBlockSize(CYASSL* ssl)
|
||||||
|
{
|
||||||
|
if (ssl == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
return ssl->specs.block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CyaSSL_GetAeadMacSize(CYASSL* ssl)
|
||||||
|
{
|
||||||
|
if (ssl == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
return ssl->specs.aead_mac_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CyaSSL_IsTLSv1_1(CYASSL* ssl)
|
||||||
|
{
|
||||||
|
if (ssl == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
if (ssl->options.tls1_1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int CyaSSL_GetSide(CYASSL* ssl)
|
int CyaSSL_GetSide(CYASSL* ssl)
|
||||||
{
|
{
|
||||||
if (ssl)
|
if (ssl)
|
||||||
|
Reference in New Issue
Block a user