add useratomic DecryptVerify Callbacks, example
This commit is contained in:
parent
442886a207
commit
54a2f8b9aa
@ -1261,7 +1261,8 @@ struct CYASSL_CTX {
|
||||
TLSX* extensions; /* RFC 6066 TLS Extensions data */
|
||||
#endif
|
||||
#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
|
||||
};
|
||||
|
||||
@ -1403,6 +1404,7 @@ typedef struct Keys {
|
||||
#endif
|
||||
|
||||
word32 encryptSz; /* last size of encrypted data */
|
||||
word32 padSz; /* how much to advance after decrypt part */
|
||||
byte encryptionOn; /* true after change cipher spec */
|
||||
byte decryptedCur; /* only decrypt current record once */
|
||||
} Keys;
|
||||
@ -1826,7 +1828,8 @@ struct CYASSL {
|
||||
#endif
|
||||
CYASSL_ALERT_HISTORY alert_history;
|
||||
#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
|
||||
};
|
||||
|
||||
|
15
cyassl/ssl.h
15
cyassl/ssl.h
@ -948,6 +948,14 @@ CYASSL_API void CyaSSL_CTX_SetMacEncryptCb(CYASSL_CTX*, CallbackMacEncrypt);
|
||||
CYASSL_API void CyaSSL_SetMacEncryptCtx(CYASSL* ssl, void *ctx);
|
||||
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_GetClientWriteKey(CYASSL*);
|
||||
@ -956,9 +964,13 @@ CYASSL_API const unsigned char* CyaSSL_GetServerWriteKey(CYASSL*);
|
||||
CYASSL_API const unsigned char* CyaSSL_GetServerWriteIV(CYASSL*);
|
||||
CYASSL_API int CyaSSL_GetKeySize(CYASSL*);
|
||||
CYASSL_API int CyaSSL_GetSide(CYASSL*);
|
||||
CYASSL_API int CyaSSL_IsTLSv1_1(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_GetHmacType(CYASSL*);
|
||||
CYASSL_API int CyaSSL_GetCipherType(CYASSL*);
|
||||
CYASSL_API int CyaSSL_SetTlsHmacInner(CYASSL*, unsigned char*,
|
||||
unsigned int, int, int);
|
||||
|
||||
@ -966,6 +978,9 @@ CYASSL_API int CyaSSL_SetTlsHmacInner(CYASSL*, unsigned char*,
|
||||
enum {
|
||||
CYASSL_SERVER_END = 0,
|
||||
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 */
|
||||
};
|
||||
|
||||
|
109
cyassl/test.h
109
cyassl/test.h
@ -1301,6 +1301,13 @@ typedef struct 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,
|
||||
const unsigned char* macIn, unsigned int macInSz, int macContent,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
AtomicEncCtx* encCtx;
|
||||
AtomicDecCtx* decCtx;
|
||||
|
||||
encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx));
|
||||
if (encCtx == NULL)
|
||||
err_sys("AtomicEncCtx malloc failed");
|
||||
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_SetMacEncryptCtx(ssl, encCtx);
|
||||
|
||||
CyaSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb);
|
||||
CyaSSL_SetDecryptVerifyCtx(ssl, decCtx);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void FreeAtomicUser(CYASSL* ssl)
|
||||
{
|
||||
AtomicEncCtx* encCtx = CyaSSL_GetMacEncryptCtx(ssl);
|
||||
AtomicDecCtx* decCtx = CyaSSL_GetDecryptVerifyCtx(ssl);
|
||||
|
||||
free(decCtx);
|
||||
free(encCtx);
|
||||
}
|
||||
|
||||
|
248
src/internal.c
248
src/internal.c
@ -429,7 +429,8 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
|
||||
ctx->extensions = NULL;
|
||||
#endif
|
||||
#ifdef ATOMIC_USER
|
||||
ctx->MacEncryptCb = NULL;
|
||||
ctx->MacEncryptCb = NULL;
|
||||
ctx->DecryptVerifyCb = NULL;
|
||||
#endif
|
||||
|
||||
if (InitMutex(&ctx->countMutex) < 0) {
|
||||
@ -1379,6 +1380,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
||||
ssl->dtls_msg_list = NULL;
|
||||
#endif
|
||||
ssl->keys.encryptSz = 0;
|
||||
ssl->keys.padSz = 0;
|
||||
ssl->keys.encryptionOn = 0; /* initially off */
|
||||
ssl->keys.decryptedCur = 0; /* initially off */
|
||||
ssl->options.sessionCacheOff = ctx->sessionCacheOff;
|
||||
@ -1479,7 +1481,8 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
||||
InitCiphers(ssl);
|
||||
InitCipherSpecs(&ssl->specs);
|
||||
#ifdef ATOMIC_USER
|
||||
ssl->MacEncryptCtx = NULL;
|
||||
ssl->MacEncryptCtx = NULL;
|
||||
ssl->DecryptVerifyCtx = NULL;
|
||||
#endif
|
||||
/* 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 finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
|
||||
int headerSz = HANDSHAKE_HEADER_SZ;
|
||||
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
|
||||
word32 idx = *inOutIdx;
|
||||
|
||||
#ifdef CYASSL_CALLBACKS
|
||||
if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
|
||||
@ -3391,32 +3381,9 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff)
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
idx += finishedSz;
|
||||
idx += ssl->keys.padSz;
|
||||
|
||||
if (ssl->options.side == CYASSL_CLIENT_END) {
|
||||
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
|
||||
if (!ssl->options.resuming) {
|
||||
@ -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,
|
||||
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
|
||||
|
||||
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 */
|
||||
static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
||||
int pLen)
|
||||
int pLen, int content)
|
||||
{
|
||||
byte verify[MAX_DIGEST_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) {
|
||||
CYASSL_MSG("Plain Len not long enough for pad/mac");
|
||||
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);
|
||||
|
||||
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) {
|
||||
CYASSL_MSG("PadCheck failed");
|
||||
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);
|
||||
|
||||
return VERIFY_MAC_ERROR;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -4326,17 +4268,13 @@ static int TimingPadVerify(CYASSL* ssl, const byte* input, int padLen, int t,
|
||||
int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||
{
|
||||
word32 msgSz = ssl->keys.encryptSz;
|
||||
word32 pad = 0,
|
||||
padByte = 0,
|
||||
idx = *inOutIdx,
|
||||
digestSz = ssl->specs.hash_size;
|
||||
int dataSz, ret;
|
||||
word32 idx = *inOutIdx;
|
||||
int dataSz;
|
||||
int ivExtra = 0;
|
||||
byte* rawData = input + idx; /* keep current for hmac */
|
||||
#ifdef HAVE_LIBZ
|
||||
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
|
||||
#endif
|
||||
byte verify[MAX_DIGEST_SIZE];
|
||||
|
||||
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
|
||||
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->options.tls1_1)
|
||||
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) {
|
||||
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) {
|
||||
CYASSL_MSG("App data buffer error, malicious input?");
|
||||
return BUFFER_ERROR;
|
||||
@ -4397,10 +4312,7 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
|
||||
ssl->buffers.clearOutputBuffer.length = dataSz;
|
||||
}
|
||||
|
||||
idx += digestSz;
|
||||
idx += pad;
|
||||
if (padByte)
|
||||
idx++;
|
||||
idx += ssl->keys.padSz;
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
/* 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);
|
||||
|
||||
if (ssl->keys.encryptionOn) {
|
||||
if (ssl->specs.cipher_type != aead) {
|
||||
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;
|
||||
}
|
||||
*inOutIdx += ssl->keys.padSz;
|
||||
}
|
||||
|
||||
return level;
|
||||
@ -4533,11 +4425,61 @@ static int GetInputData(CYASSL *ssl, word32 size)
|
||||
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
|
||||
negative number is error */
|
||||
int ProcessReply(CYASSL* ssl)
|
||||
{
|
||||
int ret = 0, type, readSz;
|
||||
int atomicUser = 0;
|
||||
word32 startIdx = 0;
|
||||
#ifndef NO_CYASSL_SERVER
|
||||
byte b0, b1;
|
||||
@ -4546,6 +4488,11 @@ int ProcessReply(CYASSL* ssl)
|
||||
int used;
|
||||
#endif
|
||||
|
||||
#ifdef ATOMIC_USER
|
||||
if (ssl->ctx->DecryptVerifyCb)
|
||||
atomicUser = 1;
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
switch ((processReply)ssl->options.processReply) {
|
||||
|
||||
@ -4676,14 +4623,53 @@ int ProcessReply(CYASSL* ssl)
|
||||
case runProcessingOneMessage:
|
||||
|
||||
if (ssl->keys.encryptionOn && ssl->keys.decryptedCur == 0) {
|
||||
ret = DecryptMessage(ssl, ssl->buffers.inputBuffer.buffer +
|
||||
ssl->buffers.inputBuffer.idx,
|
||||
ssl->curSize,
|
||||
&ssl->buffers.inputBuffer.idx);
|
||||
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.buffer +
|
||||
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) {
|
||||
CYASSL_ERROR(ret);
|
||||
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");
|
||||
|
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (ssl)
|
||||
|
Loading…
Reference in New Issue
Block a user