Merge branch 'master' of github.com:cyassl/cyassl

This commit is contained in:
John Safranek
2013-08-21 22:42:15 -07:00
5 changed files with 315 additions and 133 deletions

View File

@@ -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
}; };

View File

@@ -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 */
}; };

View File

@@ -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);
} }

View File

@@ -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");

View File

@@ -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)