diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index 059726b614ad..51384099d170 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -75,7 +75,6 @@ typedef enum EFunctionType { FUNCTION_TYPE_DTW_PATH, FUNCTION_TYPE_TLCC, - // math function FUNCTION_TYPE_ABS = 1000, FUNCTION_TYPE_LOG, @@ -126,7 +125,10 @@ typedef enum EFunctionType { FUNCTION_TYPE_FIND_IN_SET, FUNCTION_TYPE_LIKE_IN_SET, FUNCTION_TYPE_REGEXP_IN_SET, - + FUNCTION_TYPE_FROM_BASE64, + FUNCTION_TYPE_SHA1, + FUNCTION_TYPE_SHA2, + FUNCTION_TYPE_MASK_FULL, // conversion function FUNCTION_TYPE_CAST = 2000, @@ -178,19 +180,19 @@ typedef enum EFunctionType { FUNCTION_TYPE_IROWTS_ORIGIN, FUNCTION_TYPE_GROUP_ID, FUNCTION_TYPE_IS_WINDOW_FILLED, - FUNCTION_TYPE_TPREV_TS, // _tprev_ts - FUNCTION_TYPE_TCURRENT_TS, // _tcurrent_ts - FUNCTION_TYPE_TNEXT_TS, // _tnext_ts - FUNCTION_TYPE_TWSTART, // _twstart - FUNCTION_TYPE_TWEND, // _twend - FUNCTION_TYPE_TWDURATION, // _twduration - FUNCTION_TYPE_TWROWNUM, // _twrownum - FUNCTION_TYPE_TPREV_LOCALTIME, // _tprev_localtime - FUNCTION_TYPE_TNEXT_LOCALTIME, // _tnext_localtime - FUNCTION_TYPE_TLOCALTIME, // _tlocaltime - FUNCTION_TYPE_TGRPID, // _tgrpid - FUNCTION_TYPE_PLACEHOLDER_COLUMN, // %%n - FUNCTION_TYPE_PLACEHOLDER_TBNAME, // %%tbname + FUNCTION_TYPE_TPREV_TS, // _tprev_ts + FUNCTION_TYPE_TCURRENT_TS, // _tcurrent_ts + FUNCTION_TYPE_TNEXT_TS, // _tnext_ts + FUNCTION_TYPE_TWSTART, // _twstart + FUNCTION_TYPE_TWEND, // _twend + FUNCTION_TYPE_TWDURATION, // _twduration + FUNCTION_TYPE_TWROWNUM, // _twrownum + FUNCTION_TYPE_TPREV_LOCALTIME, // _tprev_localtime + FUNCTION_TYPE_TNEXT_LOCALTIME, // _tnext_localtime + FUNCTION_TYPE_TLOCALTIME, // _tlocaltime + FUNCTION_TYPE_TGRPID, // _tgrpid + FUNCTION_TYPE_PLACEHOLDER_COLUMN, // %%n + FUNCTION_TYPE_PLACEHOLDER_TBNAME, // %%tbname FUNCTION_TYPE_IMPUTATION_ROWTS, FUNCTION_TYPE_IMPUTATION_MARK, FUNCTION_TYPE_ANOMALY_MARK, @@ -399,9 +401,10 @@ int32_t fmGetStreamPesudoFuncEnv(int32_t funcId, SNodeList* pParamNodes, SFuncEx const void* fmGetStreamPesudoFuncVal(int32_t funcId, const SStreamRuntimeFuncInfo* pStreamRuntimeFuncInfo); -void fmGetStreamPesudoFuncValTbname(int32_t funcId, const SStreamRuntimeFuncInfo* pStreamRuntimeFuncInfo, void** data, int32_t* dataLen); -int32_t fmSetStreamPseudoFuncParamVal(int32_t funcId, SNodeList* pParamNodes, const SStreamRuntimeFuncInfo* pStreamRuntimeInfo); - +void fmGetStreamPesudoFuncValTbname(int32_t funcId, const SStreamRuntimeFuncInfo* pStreamRuntimeFuncInfo, void** data, + int32_t* dataLen); +int32_t fmSetStreamPseudoFuncParamVal(int32_t funcId, SNodeList* pParamNodes, + const SStreamRuntimeFuncInfo* pStreamRuntimeInfo); #ifdef __cplusplus } diff --git a/include/libs/scalar/scalar.h b/include/libs/scalar/scalar.h index b06d12c86c94..b6cfbeb842d3 100644 --- a/include/libs/scalar/scalar.h +++ b/include/libs/scalar/scalar.h @@ -38,18 +38,22 @@ int32_t scalarConvertOpValueNodeTs(SOperatorNode *node); /* pDst need to freed in caller */ -int32_t scalarCalculate(SNode *pNode, SArray *pBlockList, SScalarParam *pDst, const void* pExtraParam, void* streamTsRange); -int32_t scalarCalculateInRange(SNode *pNode, SArray *pBlockList, SScalarParam *pDst, int32_t rowStartIdx, int32_t rowEndIdx, const void* pExtraParam, void* streamTsRange); -void sclFreeParam(SScalarParam* param); -int32_t scalarAssignPlaceHolderRes(SColumnInfoData* pResColData, int64_t offset, int64_t rows, int16_t funcId, const void* pExtraParams); +int32_t scalarCalculate(SNode *pNode, SArray *pBlockList, SScalarParam *pDst, const void *pExtraParam, + void *streamTsRange); +int32_t scalarCalculateInRange(SNode *pNode, SArray *pBlockList, SScalarParam *pDst, int32_t rowStartIdx, + int32_t rowEndIdx, const void *pExtraParam, void *streamTsRange); +void sclFreeParam(SScalarParam *param); +int32_t scalarAssignPlaceHolderRes(SColumnInfoData *pResColData, int64_t offset, int64_t rows, int16_t funcId, + const void *pExtraParams); int32_t scalarGetOperatorParamNum(EOperatorType type); int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type, STypeMod typeMod, int8_t processType); -int32_t vectorGetConvertType(int32_t type1, int32_t type2); -int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow, int32_t startIndex, int32_t numOfRows); -int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_t type, STypeMod typeMod, int32_t startIndex, int32_t numOfRows); +int32_t vectorGetConvertType(int32_t type1, int32_t type2); +int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow, int32_t startIndex, + int32_t numOfRows); +int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_t type, STypeMod typeMod, + int32_t startIndex, int32_t numOfRows); STypeMod getConvertTypeMod(int32_t type, const SColumnInfo *pCol1, const SColumnInfo *pCol2); -uint32_t base64BufSize(size_t inputLenBytes); /* Math functions */ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); @@ -90,7 +94,10 @@ int32_t upperFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOut int32_t ltrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t rtrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); -int32_t md5Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput); +int32_t md5Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t shaFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t sha2Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t maskFullFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t charFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t asciiFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t positionFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); @@ -98,11 +105,12 @@ int32_t trimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp int32_t replaceFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t repeatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); int32_t substrIdxFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); -int32_t base64Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput); -int32_t crc32Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput); -int32_t findInSetFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput); -int32_t likeInSetFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput); -int32_t regexpInSetFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput); +int32_t base64Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t base64FunctionFrom(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t crc32Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t findInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t likeInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); +int32_t regexpInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); /* Conversion functions */ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); @@ -170,7 +178,8 @@ int32_t modeScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam // stream pseudo functions int32_t streamPseudoScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); -int32_t streamCalcCurrWinTimeRange(STimeRangeNode* node, void* pStRtFuncInfo, STimeWindow* pWinRange, bool* winRangeValid, int32_t type); +int32_t streamCalcCurrWinTimeRange(STimeRangeNode *node, void *pStRtFuncInfo, STimeWindow *pWinRange, + bool *winRangeValid, int32_t type); int32_t scalarCalculateExtWinsTimeRange(STimeRangeNode *pNode, const void *pExtraParam, SExtWinTimeWindow *pWins); #ifdef __cplusplus diff --git a/include/util/tbase64.h b/include/util/tbase64.h index e342e6a0fab8..d85fea372a08 100644 --- a/include/util/tbase64.h +++ b/include/util/tbase64.h @@ -17,6 +17,7 @@ #define _TD_UTIL_BASE64_H_ #include "os.h" +#include "types.h" #ifdef __cplusplus extern "C" { @@ -25,8 +26,13 @@ extern "C" { int32_t base64_decode(const char *value, int32_t inlen, int32_t *outlen, uint8_t **result); int32_t base64_encode(const uint8_t *value, int32_t vlen, char **result); +void tbase64_encode(uint8_t *out, const uint8_t *input, size_t in_len, VarDataLenT out_len); +int32_t tbase64_decode(uint8_t *out, const uint8_t *input, size_t in_len, VarDataLenT out_len); +uint32_t tbase64_encode_len(size_t in_len); +uint32_t tbase64_decode_len(size_t in_len); + #ifdef __cplusplus } #endif -#endif /*_TD_UTIL_BASE64_H_*/ \ No newline at end of file +#endif /*_TD_UTIL_BASE64_H_*/ diff --git a/include/util/tsha.h b/include/util/tsha.h new file mode 100644 index 000000000000..2cc8b87c8463 --- /dev/null +++ b/include/util/tsha.h @@ -0,0 +1,83 @@ +#ifndef _TD_UTIL_SHA_H +#define _TD_UTIL_SHA_H + +#include "os.h" + +#define SHA1_OUTPUT_LEN 40 +#define SHA2_OUTPUT_LEN 128 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} T_SHA1_CTX; + +void tSHA1Transform(uint32_t state[5], const unsigned char buffer[64]); +void tSHA1Init(T_SHA1_CTX *context); +void tSHA1Update(T_SHA1_CTX *context, const unsigned char *data, uint32_t len); +void tSHA1Final(unsigned char digest[20], T_SHA1_CTX *context); +void tSHA1(char *hash_out, const char *str, uint32_t len); + +#define SHA224_DIGEST_SIZE (224 / 8) +#define SHA256_DIGEST_SIZE (256 / 8) +#define SHA384_DIGEST_SIZE (384 / 8) +#define SHA512_DIGEST_SIZE (512 / 8) + +#define SHA256_BLOCK_SIZE (512 / 8) +#define SHA512_BLOCK_SIZE (1024 / 8) +#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE +#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE + +#ifndef SHA2_TYPES +#define SHA2_TYPES +typedef unsigned char uint8; +typedef unsigned int uint32; +typedef unsigned long long uint64; +#endif + +typedef struct { + uint64 tot_len; + uint64 len; + uint8 block[2 * SHA256_BLOCK_SIZE]; + uint32 h[8]; +} sha256_ctx; + +typedef struct { + uint64 tot_len; + uint64 len; + uint8 block[2 * SHA512_BLOCK_SIZE]; + uint64 h[8]; +} sha512_ctx; + +typedef sha512_ctx sha384_ctx; +typedef sha256_ctx sha224_ctx; + +void sha224_init(sha224_ctx *ctx); +void sha224_update(sha224_ctx *ctx, const uint8 *message, uint64 len); +void sha224_final(sha224_ctx *ctx, uint8 *digest); +void sha224(const uint8 *message, uint64 len, uint8 *digest); + +void sha256_init(sha256_ctx *ctx); +void sha256_update(sha256_ctx *ctx, const uint8 *message, uint64 len); +void sha256_final(sha256_ctx *ctx, uint8 *digest); +void sha256(const uint8 *message, uint64 len, uint8 *digest); + +void sha384_init(sha384_ctx *ctx); +void sha384_update(sha384_ctx *ctx, const uint8 *message, uint64 len); +void sha384_final(sha384_ctx *ctx, uint8 *digest); +void sha384(const uint8 *message, uint64 len, uint8 *digest); + +void sha512_init(sha512_ctx *ctx); +void sha512_update(sha512_ctx *ctx, const uint8 *message, uint64 len); +void sha512_final(sha512_ctx *ctx, uint8 *digest); +void sha512(const uint8 *message, uint64 len, uint8 *digest); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_UTIL_SHA_H*/ diff --git a/include/util/tutil.h b/include/util/tutil.h index f308c24cd80a..ae58453fc2be 100644 --- a/include/util/tutil.h +++ b/include/util/tutil.h @@ -20,6 +20,7 @@ #include "tdef.h" #include "thash.h" #include "tmd5.h" +#include "tsha.h" #ifdef __cplusplus extern "C" { @@ -215,17 +216,82 @@ static FORCE_INLINE int32_t taosHashBinary(char *pBuf, int32_t len) { static FORCE_INLINE int32_t taosCreateMD5Hash(char *pBuf, int32_t len) { T_MD5_CTX ctx; + tMD5Init(&ctx); tMD5Update(&ctx, (uint8_t *)pBuf, len); tMD5Final(&ctx); - char *p = pBuf; - int32_t resLen = 0; + return sprintf(pBuf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", ctx.digest[0], ctx.digest[1], ctx.digest[2], ctx.digest[3], ctx.digest[4], ctx.digest[5], ctx.digest[6], ctx.digest[7], ctx.digest[8], ctx.digest[9], ctx.digest[10], ctx.digest[11], ctx.digest[12], ctx.digest[13], ctx.digest[14], ctx.digest[15]); } +static FORCE_INLINE int32_t taosCreateSHA1Hash(char *pBuf, int32_t len) { + uint8_t result[21] = {0}; + + tSHA1((char *)result, pBuf, len); + + return sprintf(pBuf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", result[0], + result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], + result[10], result[11], result[12], result[13], result[14], result[15], result[16], result[17], + result[18], result[19]); +} + +static FORCE_INLINE int32_t taosCreateSHA2Hash(char *pBuf, int32_t len, uint32_t digestSize) { + uint8_t result[2 * SHA512_DIGEST_SIZE + 1] = {0}; + + switch (digestSize / 8) { + case SHA224_DIGEST_SIZE: + sha224((const uint8_t *)pBuf, len, result); + return sprintf(pBuf, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%" + "02x%02x%02x%02x", + result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], + result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], + result[17], result[18], result[19], result[20], result[21], result[22], result[23], result[24], + result[25], result[26], result[27]); + case SHA256_DIGEST_SIZE: + sha256((const uint8_t *)pBuf, len, result); + return sprintf(pBuf, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%" + "02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], + result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], + result[17], result[18], result[19], result[20], result[21], result[22], result[23], result[24], + result[25], result[26], result[27], result[28], result[29], result[30], result[31]); + case SHA384_DIGEST_SIZE: + sha384((const uint8_t *)pBuf, len, result); + return sprintf(pBuf, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%" + "02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], + result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], + result[17], result[18], result[19], result[20], result[21], result[22], result[23], result[24], + result[25], result[26], result[27], result[28], result[29], result[30], result[31], result[32], + result[33], result[34], result[35], result[36], result[37], result[38], result[39], result[40], + result[41], result[42], result[43], result[44], result[45], result[46], result[47]); + case SHA512_DIGEST_SIZE: + sha512((const uint8_t *)pBuf, len, result); + return sprintf(pBuf, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%" + "02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%" + "02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], + result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], + result[17], result[18], result[19], result[20], result[21], result[22], result[23], result[24], + result[25], result[26], result[27], result[28], result[29], result[30], result[31], result[32], + result[33], result[34], result[35], result[36], result[37], result[38], result[39], result[40], + result[41], result[42], result[43], result[44], result[45], result[46], result[47], result[48], + result[49], result[50], result[51], result[52], result[53], result[54], result[55], result[56], + result[57], result[58], result[59], result[60], result[61], result[62], result[63]); + default: + break; + } + + return 0; +} + static FORCE_INLINE int32_t taosGetTbHashVal(const char *tbname, int32_t tblen, int32_t method, int32_t prefix, int32_t suffix) { if ((prefix == 0 && suffix == 0) || (tblen <= (prefix + suffix)) || (tblen <= -1 * (prefix + suffix)) || @@ -301,7 +367,7 @@ static FORCE_INLINE int32_t taosGetTbHashVal(const char *tbname, int32_t tblen, #define VND_CHECK_CODE(CODE, LINO, LABEL) TSDB_CHECK_CODE(CODE, LINO, LABEL) -#define TCONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) +#define TCONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr)-offsetof(type, member))) #define TAOS_GET_TERRNO(code) (terrno == 0 ? code : terrno) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 21562fc1d1a3..ddf983cc0f4f 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -23,6 +23,7 @@ #include "scalar.h" #include "tanalytics.h" #include "taoserror.h" +#include "tbase64.h" #include "tglobal.h" #include "ttypes.h" @@ -1024,7 +1025,17 @@ static int32_t translateBase64(SFunctionNode* pFunc, char* pErrBuf, int32_t len) FUNC_ERR_RET(validateParam(pFunc, pErrBuf, len)); SDataType* pRestType1 = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0)); - int32_t outputLength = base64BufSize(pRestType1->bytes); + int32_t outputLength = tbase64_encode_len(pRestType1->bytes); + + pFunc->node.resType = (SDataType){.bytes = outputLength, .type = TSDB_DATA_TYPE_VARCHAR}; + return TSDB_CODE_SUCCESS; +} + +static int32_t translateBase64From(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + FUNC_ERR_RET(validateParam(pFunc, pErrBuf, len)); + + SDataType* pRestType1 = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0)); + int32_t outputLength = tbase64_decode_len(pRestType1->bytes); pFunc->node.resType = (SDataType){.bytes = outputLength, .type = TSDB_DATA_TYPE_VARCHAR}; return TSDB_CODE_SUCCESS; @@ -1661,6 +1672,25 @@ static int32_t translateReplace(SFunctionNode* pFunc, char* pErrBuf, int32_t len return TSDB_CODE_SUCCESS; } +static int32_t translateMaskFull(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + FUNC_ERR_RET(validateParam(pFunc, pErrBuf, len)); + + uint8_t orgType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type; + uint8_t maskType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 1))->type; + int32_t orgLen = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->bytes; + int32_t maskLen = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 1))->bytes; + + if (orgType == TSDB_DATA_TYPE_NCHAR && maskType != orgType) { + maskLen = maskLen * TSDB_NCHAR_SIZE; + } + + int32_t resLen = TMAX(orgLen, maskLen); + + pFunc->node.resType = (SDataType){.bytes = resLen, .type = orgType}; + + return TSDB_CODE_SUCCESS; +} + static int32_t translateRepeat(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { FUNC_ERR_RET(validateParam(pFunc, pErrBuf, len)); @@ -1888,6 +1918,12 @@ static int32_t translateOutVarchar(SFunctionNode* pFunc, char* pErrBuf, int32_t case FUNCTION_TYPE_MD5: bytes = MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE; break; + case FUNCTION_TYPE_SHA1: + bytes = SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE; + break; + case FUNCTION_TYPE_SHA2: + bytes = SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE; + break; case FUNCTION_TYPE_USER: case FUNCTION_TYPE_CURRENT_USER: bytes = TSDB_USER_LEN; @@ -6750,6 +6786,118 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .sprocessFunc = NULL, .finalizeFunc = NULL }, + { + .name = "from_base64", + .type = FUNCTION_TYPE_FROM_BASE64, + .classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC, + .parameters = {.minParamNum = 1, + .maxParamNum = 1, + .paramInfoPattern = 1, + .inputParaInfo[0][0] = {.isLastParam = true, + .startParam = 1, + .endParam = 1, + .validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE | FUNC_PARAM_SUPPORT_NCHAR_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE, + .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, + .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, + .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE}}, + .translateFunc = translateBase64From, + .getEnvFunc = NULL, + .initFunc = NULL, + .sprocessFunc = base64FunctionFrom, + .finalizeFunc = NULL + }, + { + .name = "sha", + .type = FUNCTION_TYPE_SHA1, + .classification = FUNC_MGT_SCALAR_FUNC, + .parameters = {.minParamNum = 1, + .maxParamNum = 1, + .paramInfoPattern = 1, + .inputParaInfo[0][0] = {.isLastParam = true, + .startParam = 1, + .endParam = 1, + .validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE, + .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, + .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, + .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE}}, + .translateFunc = translateOutVarchar, + .getEnvFunc = NULL, + .initFunc = NULL, + .sprocessFunc = shaFunction, + .finalizeFunc = NULL + }, + { + .name = "sha1", + .type = FUNCTION_TYPE_SHA1, + .classification = FUNC_MGT_SCALAR_FUNC, + .parameters = {.minParamNum = 1, + .maxParamNum = 1, + .paramInfoPattern = 1, + .inputParaInfo[0][0] = {.isLastParam = true, + .startParam = 1, + .endParam = 1, + .validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE, + .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, + .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, + .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE}}, + .translateFunc = translateOutVarchar, + .getEnvFunc = NULL, + .initFunc = NULL, + .sprocessFunc = shaFunction, + .finalizeFunc = NULL + }, + { + .name = "sha2", + .type = FUNCTION_TYPE_SHA2, + .classification = FUNC_MGT_SCALAR_FUNC, + .parameters = {.minParamNum = 2, + .maxParamNum = 2, + .paramInfoPattern = 1, + .inputParaInfo[0][0] = {.isLastParam = false, + .startParam = 1, + .endParam = 1, + .validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE, + .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, + .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, + .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, + .inputParaInfo[0][1] = {.isLastParam = true, + .startParam = 2, + .endParam = 2, + .validDataType = FUNC_PARAM_SUPPORT_INTEGER_TYPE, + .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, + .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, + .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE}}, + .translateFunc = translateOutVarchar, + .getEnvFunc = NULL, + .initFunc = NULL, + .sprocessFunc = sha2Function, + .finalizeFunc = NULL + }, + { + .name = "mask_full", + .type = FUNCTION_TYPE_MASK_FULL, + .classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC, + .parameters = {.minParamNum = 2, + .maxParamNum = 2, + .paramInfoPattern = 1, + .inputParaInfo[0][0] = {.isLastParam = true, + .startParam = 1, + .endParam = 2, + .validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE | FUNC_PARAM_SUPPORT_NCHAR_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE, + .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, + .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, + .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_VARCHAR_TYPE | FUNC_PARAM_SUPPORT_NCHAR_TYPE}}, + .translateFunc = translateMaskFull, + .getEnvFunc = NULL, + .initFunc = NULL, + .sprocessFunc = maskFullFunction, + .finalizeFunc = NULL + }, }; // clang-format on diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 081e9f2062d7..ce40c99e2b90 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -19,6 +19,7 @@ #include "parToken.h" #include "query.h" #include "scalar.h" +#include "tbase64.h" #include "tglobal.h" #include "ttime.h" @@ -56,8 +57,8 @@ typedef struct SInsertParseContext { bool needTableTagVal; bool needRequest; // whether or not request server // bool isStmtBind; // whether is stmt bind - uint8_t stmtTbNameFlag; - SArray* pParsedValues; // for stmt bind col + uint8_t stmtTbNameFlag; + SArray* pParsedValues; // for stmt bind col } SInsertParseContext; typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param); @@ -72,7 +73,6 @@ static int32_t csvParserReadLine(SCsvParser* parser); static void destroySavedCsvParser(SVnodeModifyOpStmt* pStmt); static int32_t csvParserExpandLineBuffer(SCsvParser* parser, size_t requiredLen); - static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE; static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE; @@ -507,6 +507,252 @@ static int parseGeometry(SToken* pToken, unsigned char** output, size_t* size) { #endif } +static int32_t parseBinary(SInsertParseContext* pCxt, const char** ppSql, SToken* pToken, SColVal* pVal, + SSchema* pSchema) { + int32_t bytes = pSchema->bytes; + uint8_t** pData = &pVal->value.pData; + uint32_t* nData = &pVal->value.nData; + + if (TK_NK_ID == pToken->type) { + char* input = NULL; + int32_t inputBytes = 0; + char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW]; + + if (0 == strncasecmp(pToken->z, "from_base64(", 12)) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_LP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z); + } + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NULL == pToken->type) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP == pToken->type) { + pVal->flag = CV_FLAG_NULL; + + return TSDB_CODE_SUCCESS; + } + } else if (TK_NK_STRING != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z); + } + + inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); + input = tmpTokenBuf; + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z); + } + + int32_t outputBytes = tbase64_decode_len(inputBytes); + if (outputBytes + VARSTR_HEADER_SIZE > bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + *pData = taosMemoryMalloc(outputBytes); + if (NULL == *pData) { + return terrno; + } + + if (TSDB_CODE_SUCCESS != tbase64_decode(*pData, (const uint8_t*)input, inputBytes, outputBytes)) { + taosMemoryFree(*pData); + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_INVALID_DATA_FMT); + } + *nData = outputBytes; + } else if (0 == strncasecmp(pToken->z, "to_base64(", 10)) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_LP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z); + } + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NULL == pToken->type) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP == pToken->type) { + pVal->flag = CV_FLAG_NULL; + + return TSDB_CODE_SUCCESS; + } + } else if (TK_NK_STRING != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z); + } + + inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); + input = tmpTokenBuf; + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z); + } + + int32_t outputBytes = tbase64_encode_len(inputBytes); + if (outputBytes + VARSTR_HEADER_SIZE > bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + *pData = taosMemoryMalloc(outputBytes); + if (NULL == *pData) { + return terrno; + } + + tbase64_encode(*pData, input, inputBytes, outputBytes); + *nData = outputBytes; + } else if (0 == strncasecmp(pToken->z, "md5(", 4)) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_LP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z); + } + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NULL == pToken->type) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP == pToken->type) { + pVal->flag = CV_FLAG_NULL; + + return TSDB_CODE_SUCCESS; + } + } else if (TK_NK_STRING != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z); + } + + inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); + input = tmpTokenBuf; + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z); + } + + if (MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + int32_t bufLen = TMAX(MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, inputBytes); + *pData = taosMemoryMalloc(bufLen); + if (NULL == *pData) { + return terrno; + } + + (void)memcpy(*pData, input, inputBytes); + int32_t len = taosCreateMD5Hash(*pData, inputBytes); + *nData = len; + } else if (0 == strncasecmp(pToken->z, "sha2(", 5)) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_LP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z); + } + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NULL == pToken->type) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP == pToken->type) { + pVal->flag = CV_FLAG_NULL; + + return TSDB_CODE_SUCCESS; + } + } else if (TK_NK_STRING != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z); + } + + inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); + input = tmpTokenBuf; + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_COMMA != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, ", expected", pToken->z); + } + + int64_t digestLen = 224; + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_INTEGER != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "integer [224, 256, 384, 512] expected", pToken->z); + } else { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &digestLen)) { + return buildSyntaxErrMsg(&pCxt->msg, "invalid integer format", pToken->z); + } + + if (224 != digestLen && 256 != digestLen && 384 != digestLen && 512 != digestLen) { + return buildSyntaxErrMsg(&pCxt->msg, "sha2 digest length must be one of 224, 256, 384, 512", pToken->z); + } + } + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z); + } + + if (SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + int32_t bufLen = TMAX(SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, inputBytes); + *pData = taosMemoryMalloc(bufLen); + if (NULL == *pData) { + return terrno; + } + + (void)memcpy(*pData, input, inputBytes); + int32_t len = taosCreateSHA2Hash(*pData, inputBytes, digestLen); + *nData = len; + } else if (0 == strncasecmp(pToken->z, "sha(", 4) || 0 == strncasecmp(pToken->z, "sha1(", 5)) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_LP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "( expected", pToken->z); + } + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NULL == pToken->type) { + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP == pToken->type) { + pVal->flag = CV_FLAG_NULL; + + return TSDB_CODE_SUCCESS; + } + } else if (TK_NK_STRING != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, "string expected", pToken->z); + } + + inputBytes = trimString(pToken->z, pToken->n, tmpTokenBuf, TSDB_MAX_BYTES_PER_ROW); + input = tmpTokenBuf; + + NEXT_VALID_TOKEN(*ppSql, *pToken); + if (TK_NK_RP != pToken->type) { + return buildSyntaxErrMsg(&pCxt->msg, ") expected", pToken->z); + } + + if (SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE > bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + int32_t bufLen = TMAX(SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, inputBytes); + *pData = taosMemoryMalloc(bufLen); + if (NULL == *pData) { + return terrno; + } + + (void)memcpy(*pData, input, inputBytes); + int32_t len = taosCreateSHA1Hash(*pData, inputBytes); + *nData = len; + } else { + return buildSyntaxErrMsg(&pCxt->msg, "invalid identifier", pToken->z); + } + } else { + if (pToken->n + VARSTR_HEADER_SIZE > bytes) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + + *pData = taosMemoryMalloc(pToken->n); + if (NULL == *pData) { + return terrno; + } + memcpy(*pData, pToken->z, pToken->n); + *nData = pToken->n; + } + + pVal->flag = CV_FLAG_VALUE; + return TSDB_CODE_SUCCESS; +} + static int32_t parseVarbinary(SToken* pToken, uint8_t** pData, uint32_t* nData, int32_t bytes) { if (pToken->type != TK_NK_STRING) { return TSDB_CODE_PAR_INVALID_VARBINARY; @@ -897,7 +1143,7 @@ int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf, i if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER && pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL && pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN && - pToken->type != TK_NK_VARIABLE) || + pToken->type != TK_NK_VARIABLE && pToken->type != TK_NK_ID) || (pToken->n == 0) || (pToken->type == TK_NK_RP)) { return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); } @@ -1066,8 +1312,8 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt SToken token; bool isJson = false; STag* pTag = NULL; - uint8_t* pTagsIndex; - int32_t numOfTags = 0; + uint8_t* pTagsIndex; + int32_t numOfTags = 0; if (pCxt->pComCxt->stmtBindVersion == 2) { // only support stmt2 pTagsIndex = taosMemoryCalloc(pCxt->tags.numOfBound, sizeof(uint8_t)); @@ -1837,17 +2083,7 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, break; } case TSDB_DATA_TYPE_BINARY: { - // Too long values will raise the invalid sql error message - if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { - return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); - } - pVal->value.pData = taosMemoryMalloc(pToken->n); - if (NULL == pVal->value.pData) { - return terrno; - } - memcpy(pVal->value.pData, pToken->z, pToken->n); - pVal->value.nData = pToken->n; - break; + return parseBinary(pCxt, pSql, pToken, pVal, pSchema); } case TSDB_DATA_TYPE_VARBINARY: { int32_t code = parseVarbinary(pToken, &pVal->value.pData, &pVal->value.nData, pSchema->bytes); @@ -2247,29 +2483,29 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* if (code == TSDB_CODE_SUCCESS && TK_NK_VARIABLE == pToken->type) { code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value"); } - if (code == TSDB_CODE_SUCCESS) { - code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, - pCxt->tags.parseredTags->STagNames, pCxt->tags.parseredTags->pTagVals, - &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt); - } + if (code == TSDB_CODE_SUCCESS) { + code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, + pCxt->tags.parseredTags->STagNames, pCxt->tags.parseredTags->pTagVals, + &pStbRowsCxt->pTag, pCxt->pComCxt->timezone, pCxt->pComCxt->charsetCxt); + } - pCxt->tags.parseredTags->pTagIndex[pCxt->tags.parseredTags->numOfTags++] = pCols->pColIndex[i] - numOfCols; + pCxt->tags.parseredTags->pTagIndex[pCxt->tags.parseredTags->numOfTags++] = pCols->pColIndex[i] - numOfCols; - if (pCxt->tags.pColIndex == NULL) { - pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t)); - if (NULL == pCxt->tags.pColIndex) { - return terrno; - } - } - if (!(tag_index < numOfTags)) { - return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags"); + if (pCxt->tags.pColIndex == NULL) { + pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t)); + if (NULL == pCxt->tags.pColIndex) { + return terrno; } - pStmt->usingTableProcessing = true; - pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols; - pCxt->tags.mixTagsCols = true; - pCxt->tags.numOfBound++; - pCxt->tags.numOfCols++; - // } + } + if (!(tag_index < numOfTags)) { + return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags"); + } + pStmt->usingTableProcessing = true; + pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols; + pCxt->tags.mixTagsCols = true; + pCxt->tags.numOfBound++; + pCxt->tags.numOfCols++; + // } } else if (pCols->pColIndex[i] == tbnameIdx) { return buildInvalidOperationMsg(&pCxt->msg, "STMT tbname in bound cols should not be a fixed value"); } @@ -3297,9 +3533,9 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS code = parseInsertTableClause(pCxt, pStmt, &token); } - if( TSDB_CODE_SUCCESS == code && pStmt->pTableMeta && + if (TSDB_CODE_SUCCESS == code && pStmt->pTableMeta && (((pStmt->pTableMeta->virtualStb == 1) && (pStmt->pTableMeta->tableType == TSDB_SUPER_TABLE)) || - (pStmt->pTableMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE || + (pStmt->pTableMeta->tableType == TSDB_VIRTUAL_NORMAL_TABLE || pStmt->pTableMeta->tableType == TSDB_VIRTUAL_CHILD_TABLE))) { code = buildInvalidOperationMsg(&pCxt->msg, "Virtual table can not be written"); } diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 00ee2386d164..eb31043c6fe7 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -6,11 +6,12 @@ #include "scalar.h" #include "sclInt.h" #include "sclvector.h" +#include "tbase64.h" +#include "tcompare.h" #include "tdatablock.h" #include "tdef.h" #include "tjson.h" #include "ttime.h" -#include "tcompare.h" typedef float (*_float_fn)(float); typedef float (*_float_fn_2)(float, float); @@ -1301,15 +1302,15 @@ int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu return code; } - -static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, bool (*compare)(const char*, int32_t, const char*, int32_t)) { - int32_t code = TSDB_CODE_SUCCESS; +static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, + bool (*compare)(const char *, int32_t, const char *, int32_t)) { + int32_t code = TSDB_CODE_SUCCESS; SColumnInfoData *pats = pInput[0].columnData, *sets = pInput[1].columnData, *seps = NULL; - char *patstr = NULL, *setstr = NULL, *sepstr = ","; // "," is the default seperator - int32_t patLen = 0, setLen = 0, sepLen = 1; - int32_t patNum = pInput[0].numOfRows, setNum = pInput[1].numOfRows, sepNum = 0; - bool needFreePat = false, needFreeSep = false; + char *patstr = NULL, *setstr = NULL, *sepstr = ","; // "," is the default seperator + int32_t patLen = 0, setLen = 0, sepLen = 1; + int32_t patNum = pInput[0].numOfRows, setNum = pInput[1].numOfRows, sepNum = 0; + bool needFreePat = false, needFreeSep = false; if (inputNum == 3) { sepNum = pInput[2].numOfRows; @@ -1319,10 +1320,8 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala int32_t setType = GET_PARAM_TYPE(&pInput[1]); - if ((IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) - || IS_NULL_TYPE(setType)) - || (patNum == 1 && colDataIsNull_s(pats, 0)) - || (setNum == 1 && colDataIsNull_s(sets, 0))) { + if ((IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(setType)) || + (patNum == 1 && colDataIsNull_s(pats, 0)) || (setNum == 1 && colDataIsNull_s(sets, 0))) { colDataSetNNULL(pOutput->columnData, 0, numOfRows); pOutput->numOfRows = numOfRows; return code; @@ -1333,7 +1332,7 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala patLen = varDataLen(colDataGetData(pats, 0)); patstr = varDataVal(colDataGetData(pats, 0)); if (GET_PARAM_TYPE(&pInput[0]) != setType) { - SCL_ERR_JRET(convBetweenNcharAndVarchar(patstr, &patstr, patLen, &patLen, setType, pInput[0].charsetCxt)); + SCL_ERR_JRET(convBetweenNcharAndVarchar(patstr, &patstr, patLen, &patLen, setType, pInput[0].charsetCxt)); needFreePat = true; } } @@ -1346,8 +1345,8 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala if (sepNum == 0) { // use default seperator if was not provided, but we may need to convert it to nchar. if (setType == TSDB_DATA_TYPE_NCHAR) { - SCL_ERR_RET(convVarcharToNchar(sepstr, &sepstr, 1, &sepLen, NULL)); - needFreeSep = true; + SCL_ERR_RET(convVarcharToNchar(sepstr, &sepstr, 1, &sepLen, NULL)); + needFreeSep = true; } } else if (sepNum > 1) { // do nothing in this case @@ -1391,7 +1390,7 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala patstr = varDataVal(colDataGetData(pats, i)); patLen = varDataLen(colDataGetData(pats, i)); if (patLen > 0 && GET_PARAM_TYPE(&pInput[0]) != setType) { - SCL_ERR_JRET(convBetweenNcharAndVarchar(patstr, &patstr, patLen, &patLen, setType, pInput[0].charsetCxt)); + SCL_ERR_JRET(convBetweenNcharAndVarchar(patstr, &patstr, patLen, &patLen, setType, pInput[0].charsetCxt)); needFreePat = true; } } @@ -1425,7 +1424,7 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala char *start = setstr; for (int32_t j = 0; start < setstr + setLen; j++) { - char* end = start; + char *end = start; while (true) { // set [end] to the end of [setstr] if not enough characters for a seperator @@ -1441,7 +1440,8 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala if (setType == TSDB_DATA_TYPE_NCHAR) { end += TSDB_NCHAR_SIZE; } else if (utf8) { - for (end++; end - setstr < setLen && ((*end & 0xC0) == 0x80); end++); + for (end++; end - setstr < setLen && ((*end & 0xC0) == 0x80); end++) + ; } else { end++; } @@ -1471,7 +1471,7 @@ static int32_t matchInSetFunction(SScalarParam *pInput, int32_t inputNum, SScala return code; } -static bool findInSetCompare(const char* a, int32_t aLen, const char* b, int32_t bLen) { +static bool findInSetCompare(const char *a, int32_t aLen, const char *b, int32_t bLen) { return (aLen == bLen) && (memcmp(a, b, aLen) == 0); } @@ -1479,14 +1479,15 @@ int32_t findInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam * return matchInSetFunction(pInput, inputNum, pOutput, findInSetCompare); } -static bool likeInSetCompare(const char* a, int32_t aLen, const char* b, int32_t bLen) { +static bool likeInSetCompare(const char *a, int32_t aLen, const char *b, int32_t bLen) { SPatternCompareInfo pInfo = PATTERN_COMPARE_INFO_INITIALIZER; return patternMatch(a, aLen, b, bLen, &pInfo) == TSDB_PATTERN_MATCH; } -static bool wcsLikeInSetCompare(const char* a, int32_t aLen, const char* b, int32_t bLen) { +static bool wcsLikeInSetCompare(const char *a, int32_t aLen, const char *b, int32_t bLen) { SPatternCompareInfo pInfo = PATTERN_COMPARE_INFO_INITIALIZER; - return wcsPatternMatch((TdUcs4*)a, aLen/TSDB_NCHAR_SIZE, (TdUcs4*)b, bLen/TSDB_NCHAR_SIZE, &pInfo) == TSDB_PATTERN_MATCH; + return wcsPatternMatch((TdUcs4 *)a, aLen / TSDB_NCHAR_SIZE, (TdUcs4 *)b, bLen / TSDB_NCHAR_SIZE, &pInfo) == + TSDB_PATTERN_MATCH; } int32_t likeInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { @@ -1500,10 +1501,10 @@ int32_t likeInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam * // find_in_set & like_in_set. int32_t threadGetRegComp(regex_t **regex, const char *pPattern); -static bool regexpInSetCompare(const char* a, int32_t aLen, const char* b, int32_t bLen) { +static bool regexpInSetCompare(const char *a, int32_t aLen, const char *b, int32_t bLen) { char patBuf[256], strBuf[256], msgbuf[256]; - char *pattern = patBuf, *str = strBuf; + char *pattern = patBuf, *str = strBuf; if (aLen >= sizeof(patBuf)) { pattern = taosMemoryMalloc(aLen + 1); if (NULL == pattern) { @@ -1526,7 +1527,7 @@ static bool regexpInSetCompare(const char* a, int32_t aLen, const char* b, int32 str[bLen] = 0; regex_t *regex = NULL; - int32_t ret = threadGetRegComp(®ex, pattern); + int32_t ret = threadGetRegComp(®ex, pattern); if (ret != 0) { goto _return; } @@ -1543,7 +1544,7 @@ static bool regexpInSetCompare(const char* a, int32_t aLen, const char* b, int32 if (str != strBuf) { taosMemoryFree(str); } - if( pattern != patBuf) { + if (pattern != patBuf) { taosMemoryFree(pattern); } @@ -1551,13 +1552,13 @@ static bool regexpInSetCompare(const char* a, int32_t aLen, const char* b, int32 } int32_t regexpInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - int32_t code = TSDB_CODE_SUCCESS; + int32_t code = TSDB_CODE_SUCCESS; SColumnInfoData *pats = pInput[0].columnData, *sets = pInput[1].columnData, *seps = NULL; - char *patstr = NULL, *setstr = NULL, *sepstr = ","; // "," is the default seperator - int32_t patLen = 0, setLen = 0, sepLen = 1; - int32_t patNum = pInput[0].numOfRows, setNum = pInput[1].numOfRows, sepNum = 0; - bool needFreePat = false, needFreeSet = false, needFreeSep = false; + char *patstr = NULL, *setstr = NULL, *sepstr = ","; // "," is the default seperator + int32_t patLen = 0, setLen = 0, sepLen = 1; + int32_t patNum = pInput[0].numOfRows, setNum = pInput[1].numOfRows, sepNum = 0; + bool needFreePat = false, needFreeSet = false, needFreeSep = false; if (inputNum == 3) { sepNum = pInput[2].numOfRows; @@ -1565,10 +1566,8 @@ int32_t regexpInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam } int32_t numOfRows = TMAX(TMAX(patNum, setNum), sepNum); - if ((IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) - || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])) - || (patNum == 1 && colDataIsNull_s(pats, 0)) - || (setNum == 1 && colDataIsNull_s(sets, 0)))) { + if ((IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])) || + (patNum == 1 && colDataIsNull_s(pats, 0)) || (setNum == 1 && colDataIsNull_s(sets, 0)))) { colDataSetNNULL(pOutput->columnData, 0, numOfRows); pOutput->numOfRows = numOfRows; return code; @@ -1676,7 +1675,7 @@ int32_t regexpInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam char *start = setstr; for (int32_t j = 0; start < setstr + setLen; j++) { - char* end = start; + char *end = start; while (true) { // set [end] to the end of [setstr] if not enough characters for a seperator @@ -1690,7 +1689,8 @@ int32_t regexpInSetFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam } // not a seperator, advance one character if (utf8) { - for (end++; end - setstr < setLen && ((*end & 0xC0) == 0x80); end++); + for (end++; end - setstr < setLen && ((*end & 0xC0) == 0x80); end++) + ; } else { end++; } @@ -1761,68 +1761,125 @@ int32_t md5Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu return TSDB_CODE_SUCCESS; } +int32_t shaFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { + SColumnInfoData *pInputData = pInput->columnData; + SColumnInfoData *pOutputData = pOutput->columnData; + int32_t bufLen = TMAX(SHA1_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, pInputData->info.bytes); + char *pOutputBuf = taosMemoryMalloc(bufLen); + if (!pOutputBuf) { + qError("sha function alloc memory failed"); + return terrno; + } + for (int32_t i = 0; i < pInput->numOfRows; ++i) { + if (colDataIsNull_s(pInputData, i)) { + colDataSetNULL(pOutputData, i); + continue; + } + char *input = colDataGetData(pInput[0].columnData, i); + if (bufLen < varDataLen(input) + VARSTR_HEADER_SIZE) { + bufLen = varDataLen(input) + VARSTR_HEADER_SIZE; + pOutputBuf = taosMemoryRealloc(pOutputBuf, bufLen); + if (!pOutputBuf) { + qError("sha function alloc memory failed"); + return terrno; + } + } + char *output = pOutputBuf; + (void)memcpy(varDataVal(output), varDataVal(input), varDataLen(input)); + int32_t len = taosCreateSHA1Hash(varDataVal(output), varDataLen(input)); + varDataSetLen(output, len); + int32_t code = colDataSetVal(pOutputData, i, output, false); + if (TSDB_CODE_SUCCESS != code) { + taosMemoryFree(pOutputBuf); + SCL_ERR_RET(code); + } + } + pOutput->numOfRows = pInput->numOfRows; + taosMemoryFree(pOutputBuf); + return TSDB_CODE_SUCCESS; +} + +int32_t sha2Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { + SColumnInfoData *pInputData = pInput->columnData; + SColumnInfoData *pOutputData = pOutput->columnData; + int32_t bufLen = TMAX(SHA2_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, pInputData->info.bytes); + char *pOutputBuf = taosMemoryMalloc(bufLen); + if (!pOutputBuf) { + qError("sha2 function alloc memory failed"); + return terrno; + } + for (int32_t i = 0; i < pInput->numOfRows; ++i) { + if (colDataIsNull_s(pInputData, i)) { + colDataSetNULL(pOutputData, i); + continue; + } + char *input = colDataGetData(pInput[0].columnData, i); + if (bufLen < varDataLen(input) + VARSTR_HEADER_SIZE) { + bufLen = varDataLen(input) + VARSTR_HEADER_SIZE; + pOutputBuf = taosMemoryRealloc(pOutputBuf, bufLen); + if (!pOutputBuf) { + qError("sha2 function alloc memory failed"); + return terrno; + } + } + char *output = pOutputBuf; + (void)memcpy(varDataVal(output), varDataVal(input), varDataLen(input)); + + uint32_t digestLen = SHA512_DIGEST_SIZE; + GET_TYPED_DATA(digestLen, uint32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i), + typeGetTypeModFromColInfo(&pInput[1].columnData->info)); + + int32_t len = taosCreateSHA2Hash(varDataVal(output), varDataLen(input), digestLen); + varDataSetLen(output, len); + int32_t code = colDataSetVal(pOutputData, i, output, false); + if (TSDB_CODE_SUCCESS != code) { + taosMemoryFree(pOutputBuf); + SCL_ERR_RET(code); + } + } + pOutput->numOfRows = pInput->numOfRows; + taosMemoryFree(pOutputBuf); + return TSDB_CODE_SUCCESS; +} + /* pre-calculated table for 32-bit CRC */ static uint32_t crc32_table[] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, - 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, - 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, - 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, - 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, - 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, - 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, - 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, - 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, - 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, - 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, - 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, - 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, - 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, - 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, - 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, - 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, - 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, - 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, - 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, - 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, - 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, - 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, - 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, - 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, - 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, - 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, - 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, - 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, - 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, - 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, - 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, - 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, - 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, - 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, - 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, - 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, - 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, - 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, - 0x2D02EF8D -}; + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}; #define CRC32_TRUE 2212294583U #define CRC32_FALSE 4108050209U static uint32_t crc32(const uint8_t *data, size_t length) { const uint8_t *p = data; - uint32_t crc = 0xFFFFFFFF; + uint32_t crc = 0xFFFFFFFF; while (length--) { crc = crc32_table[(crc ^ (*p++)) & 0xFF] ^ (crc >> 8); @@ -1831,15 +1888,15 @@ static uint32_t crc32(const uint8_t *data, size_t length) { return crc ^ 0xFFFFFFFF; } -int32_t crc32Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) { +int32_t crc32Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { SColumnInfoData *pInputData = pInput->columnData; SColumnInfoData *pOutputData = pOutput->columnData; - int16_t inputType = GET_PARAM_TYPE(&pInput[0]); - uint32_t *out = (uint32_t *) pOutputData->pData; + int16_t inputType = GET_PARAM_TYPE(&pInput[0]); + uint32_t *out = (uint32_t *)pOutputData->pData; int32_t code = TSDB_CODE_SUCCESS; int32_t bufLen = TMAX(MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, pInputData->info.bytes); - char* pOutputBuf = taosMemoryMalloc(bufLen); + char *pOutputBuf = taosMemoryMalloc(bufLen); if (!pOutputBuf) { qError("crc32 function alloc memory failed"); SCL_ERR_JRET(terrno); @@ -1868,7 +1925,7 @@ int32_t crc32Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOut out[i] = crc32(pOutputBuf, strnlen(pOutputBuf, bufLen)); } else if (inputType == TSDB_DATA_TYPE_TIMESTAMP) { /* The format used by MySQL in the conversion from timestamp to string */ - char *format = "yyyy-mm-dd hh24:mi:ss"; + char *format = "yyyy-mm-dd hh24:mi:ss"; SArray *formats = NULL; SCL_ERR_JRET(taosTs2Char(format, &formats, *(int64_t *)input, 0, pOutputBuf, bufLen, pInput->tz)); out[i] = crc32(pOutputBuf, strlen(pOutputBuf)); @@ -2206,6 +2263,81 @@ int32_t replaceFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pO return code; } +int32_t maskFullFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { + int32_t code = TSDB_CODE_SUCCESS; + int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows); + SColumnInfoData *pOutputData = pOutput[0].columnData; + SColumnInfoData *pInputData[2]; + + pInputData[0] = pInput[0].columnData; + pInputData[1] = pInput[1].columnData; + int8_t orgType = pInputData[0]->info.type; + int8_t maskType = pInputData[1]->info.type; + int32_t orgLength = pInputData[0]->info.bytes - VARSTR_HEADER_SIZE; + int32_t maskLen = pInputData[1]->info.bytes - VARSTR_HEADER_SIZE; + + if (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NULL || GET_PARAM_TYPE(&pInput[1]) == TSDB_DATA_TYPE_NULL || + (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) || + (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0))) { + colDataSetNNULL(pOutputData, 0, numOfRows); + pOutput->numOfRows = numOfRows; + return TSDB_CODE_SUCCESS; + } + + if (orgType == TSDB_DATA_TYPE_NCHAR && maskType != orgType) { + maskLen = maskLen * TSDB_NCHAR_SIZE; + } + + int32_t outputLen = !maskLen ? orgLength : TMIN(TSDB_MAX_FIELD_LEN, TMAX(orgLength, maskLen)); + char *outputBuf = taosMemoryCalloc(outputLen + VARSTR_HEADER_SIZE, 1); + if (NULL == outputBuf) { + SCL_ERR_RET(terrno); + } + + for (int32_t i = 0; i < numOfRows; ++i) { + int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i; + int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i; + + if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2)) { + colDataSetNULL(pOutputData, i); + continue; + } + + char *output = outputBuf + VARSTR_HEADER_SIZE; + char *orgStr = varDataVal(colDataGetData(pInputData[0], colIdx1)); + int32_t orgLen = varDataLen(colDataGetData(pInputData[0], colIdx1)); + char *fromStr = varDataVal(colDataGetData(pInputData[1], colIdx2)); + int32_t fromLen = varDataLen(colDataGetData(pInputData[1], colIdx2)); + bool needFreeFrom = false; + + if (fromLen == 0 || orgLen == 0) { + (void)memcpy(output, fromStr, fromLen); + varDataSetLen(outputBuf, fromLen); + SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false)); + continue; + } + + if (GET_PARAM_TYPE(&pInput[1]) != GET_PARAM_TYPE(&pInput[0])) { + SCL_ERR_JRET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[1], colIdx2)), &fromStr, + varDataLen(colDataGetData(pInputData[1], colIdx2)), &fromLen, + GET_PARAM_TYPE(&pInput[0]), pInput->charsetCxt)); + needFreeFrom = true; + } + + (void)memcpy(output, fromStr, fromLen); + + if (needFreeFrom) { + taosMemoryFree(fromStr); + } + varDataSetLen(outputBuf, fromLen); + SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false)); + } + pOutput->numOfRows = numOfRows; +_return: + taosMemoryFree(outputBuf); + return code; +} + int32_t substrIdxFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { int32_t code = TSDB_CODE_SUCCESS; SColumnInfoData *pInputData[3]; @@ -2299,56 +2431,64 @@ int32_t substrIdxFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam * return code; } -static char base64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; +int32_t base64Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { + int32_t code = TSDB_CODE_SUCCESS; + SColumnInfoData *pInputData = pInput->columnData; + SColumnInfoData *pOutputData = pOutput->columnData; + char *outputBuf = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE); + if (outputBuf == NULL) { + SCL_ERR_RET(terrno); + } -static void base64Impl(uint8_t *base64Out, const uint8_t *inputBytes, size_t inputLen, VarDataLenT outputLen) { - for (size_t i = 0, j = 0; i < inputLen;) { - unsigned int octet_a = i < inputLen ? inputBytes[i++] : 0; - unsigned int octet_b = i < inputLen ? inputBytes[i++] : 0; - unsigned int octet_c = i < inputLen ? inputBytes[i++] : 0; + for (int32_t i = 0; i < pInput->numOfRows; ++i) { + if (colDataIsNull_s(pInputData, i)) { + colDataSetNULL(pOutputData, i); + continue; + } - unsigned int triple = (octet_a << 16) | (octet_b << 8) | octet_c; + char *input = colDataGetData(pInputData, i); + size_t inputLen = varDataLen(colDataGetData(pInputData, i)); + char *out = outputBuf + VARSTR_HEADER_SIZE; + VarDataLenT outputLength = tbase64_encode_len(inputLen); - base64Out[j++] = base64Table[(triple >> 18) & 0x3F]; - base64Out[j++] = base64Table[(triple >> 12) & 0x3F]; - base64Out[j++] = base64Table[(triple >> 6) & 0x3F]; - base64Out[j++] = base64Table[triple & 0x3F]; - } + tbase64_encode(out, (const uint8_t *)varDataVal(input), inputLen, outputLength); + varDataSetLen(outputBuf, outputLength); - for (int k = 0; k < (3 - (inputLen % 3)) % 3; k++) { - base64Out[outputLen - k - 1] = '='; + SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false)); } - base64Out[outputLen] = 0; -} - -uint32_t base64BufSize(size_t inputLenBytes) { - return 4 * ((inputLenBytes + 2) / 3); + pOutput->numOfRows = pInput->numOfRows; +_return: + taosMemoryFree(outputBuf); + return code; } -int32_t base64Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) { - int32_t code = TSDB_CODE_SUCCESS; +int32_t base64FunctionFrom(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { + int32_t code = TSDB_CODE_SUCCESS; SColumnInfoData *pInputData = pInput->columnData; SColumnInfoData *pOutputData = pOutput->columnData; - char *outputBuf = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE); + char *outputBuf = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE); if (outputBuf == NULL) { SCL_ERR_RET(terrno); } - + for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { colDataSetNULL(pOutputData, i); continue; } - char *input = colDataGetData(pInputData, i); - size_t inputLen = varDataLen(colDataGetData(pInputData, i)); - char *out = outputBuf + VARSTR_HEADER_SIZE; - VarDataLenT outputLength = base64BufSize(inputLen); - base64Impl(out, varDataVal(input), inputLen, outputLength); + char *input = colDataGetData(pInputData, i); + size_t inputLen = varDataLen(colDataGetData(pInputData, i)); + char *out = outputBuf + VARSTR_HEADER_SIZE; + VarDataLenT outputLength = tbase64_decode_len(inputLen); + + if (TSDB_CODE_SUCCESS != tbase64_decode(out, varDataVal(input), inputLen, outputLength)) { + colDataSetNULL(pOutputData, i); + continue; + } varDataSetLen(outputBuf, outputLength); + SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false)); } @@ -3106,17 +3246,17 @@ int32_t toTimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam return code; } -int32_t dateFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) { +int32_t dateFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { int32_t code = 0; - char* format = "yyyy-mm-dd"; - char* out = taosMemoryCalloc(1, TS_FORMAT_MAX_LEN + VARSTR_HEADER_SIZE); + char *format = "yyyy-mm-dd"; + char *out = taosMemoryCalloc(1, TS_FORMAT_MAX_LEN + VARSTR_HEADER_SIZE); SArray *formats = NULL; if (out == NULL) { SCL_ERR_JRET(terrno); } int64_t precision = 0; GET_TYPED_DATA(precision, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData, - typeGetTypeModFromColInfo(&pInput[1].columnData->info)); + typeGetTypeModFromColInfo(&pInput[1].columnData->info)); for (int32_t rowIdx = 0; rowIdx < pInput[0].numOfRows; ++rowIdx) { if (colDataIsNull_s(pInput[0].columnData, rowIdx)) { @@ -3125,9 +3265,9 @@ int32_t dateFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutp } int32_t type = GET_PARAM_TYPE(&pInput[0]); - char *data = colDataGetData(pInput[0].columnData, rowIdx); + char *data = colDataGetData(pInput[0].columnData, rowIdx); int64_t ts = 0; - if (IS_VAR_DATA_TYPE(type)) { // datetime format strings + if (IS_VAR_DATA_TYPE(type)) { // datetime format strings int32_t ret = convertStringToTimestamp(type, data, precision, &ts, pInput->tz, pInput->charsetCxt); if (ret != TSDB_CODE_SUCCESS) { colDataSetNULL(pOutput->columnData, rowIdx); @@ -3151,9 +3291,9 @@ int32_t dateFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutp return code; } -int32_t toCharFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) { - char * format = taosMemoryMalloc(TS_FORMAT_MAX_LEN); - char * out = taosMemoryCalloc(1, TS_FORMAT_MAX_LEN + VARSTR_HEADER_SIZE); +int32_t toCharFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { + char *format = taosMemoryMalloc(TS_FORMAT_MAX_LEN); + char *out = taosMemoryCalloc(1, TS_FORMAT_MAX_LEN + VARSTR_HEADER_SIZE); int32_t len; SArray *formats = NULL; int32_t code = 0; @@ -3874,7 +4014,7 @@ int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p } int32_t anomalyCheckMarkFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - int32_t p = *(int64_t*) colDataGetData(pInput->columnData, 5); + int32_t p = *(int64_t *)colDataGetData(pInput->columnData, 5); colDataSetInt32(pOutput->columnData, pOutput->numOfRows, (int32_t *)&p); return TSDB_CODE_SUCCESS; } @@ -4267,7 +4407,7 @@ int32_t stdScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam * SColumnInfoData *pOutputData = pOutput->columnData; int32_t type = GET_PARAM_TYPE(pInput); - bool hasNull = false; + bool hasNull = false; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { @@ -4293,7 +4433,7 @@ int32_t corrScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam SColumnInfoData *pOutputData = pOutput->columnData; int32_t type = GET_PARAM_TYPE(pInput); - bool hasNull = false; + bool hasNull = false; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_f(pInputData1, i) || colDataIsNull_f(pInputData2, i)) { @@ -4313,7 +4453,6 @@ int32_t corrScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam return TSDB_CODE_SUCCESS; } - #define LEASTSQR_CAL(p, x, y, index, step) \ do { \ (p)[0][0] += (double)(x) * (x); \ @@ -5334,15 +5473,16 @@ int32_t streamPseudoScalarFunction(SScalarParam *pInput, int32_t inputNum, SScal return 0; } -int32_t streamCalcCurrWinTimeRange(STimeRangeNode *node, void *pStRtFuncInfo, STimeWindow *pWinRange, bool *winRangeValid, int32_t type) { +int32_t streamCalcCurrWinTimeRange(STimeRangeNode *node, void *pStRtFuncInfo, STimeWindow *pWinRange, + bool *winRangeValid, int32_t type) { SStreamTSRangeParas timeStartParas = {.eType = SCL_VALUE_TYPE_START, .timeValue = INT64_MIN}; SStreamTSRangeParas timeEndParas = {.eType = SCL_VALUE_TYPE_END, .timeValue = INT64_MAX}; - int32_t code = 0, lino = 0; + int32_t code = 0, lino = 0; if ((type & 0x1) && node->pStart) { TAOS_CHECK_EXIT(scalarCalculate(node->pStart, NULL, NULL, pStRtFuncInfo, &timeStartParas)); - + if (timeStartParas.opType == OP_TYPE_GREATER_THAN) { - // For greater than or lower than, used different param, rigth or left. + // For greater than or lower than, used different param, rigth or left. pWinRange->skey = timeStartParas.timeValue + 1; } else if (timeStartParas.opType == OP_TYPE_GREATER_EQUAL) { pWinRange->skey = timeStartParas.timeValue; @@ -5353,10 +5493,10 @@ int32_t streamCalcCurrWinTimeRange(STimeRangeNode *node, void *pStRtFuncInfo, ST } else { pWinRange->skey = INT64_MIN; } - + if ((type & 0x2) && node->pEnd) { TAOS_CHECK_EXIT(scalarCalculate(node->pEnd, NULL, NULL, pStRtFuncInfo, &timeEndParas)); - + if (timeEndParas.opType == OP_TYPE_LOWER_THAN) { pWinRange->ekey = timeEndParas.timeValue; } else if (timeEndParas.opType == OP_TYPE_LOWER_EQUAL) { @@ -5368,12 +5508,12 @@ int32_t streamCalcCurrWinTimeRange(STimeRangeNode *node, void *pStRtFuncInfo, ST } else { pWinRange->ekey = INT64_MAX; } - + qDebug("%s, stream curr win calc range, skey:%" PRId64 ", ekey:%" PRId64, __func__, pWinRange->skey, pWinRange->ekey); if (winRangeValid) { *winRangeValid = true; } - + _exit: if (code) { @@ -5382,5 +5522,3 @@ int32_t streamCalcCurrWinTimeRange(STimeRangeNode *node, void *pStRtFuncInfo, ST return code; } - - diff --git a/source/util/src/tbase64.c b/source/util/src/tbase64.c index f623d34a2fe5..e49ed39f7388 100644 --- a/source/util/src/tbase64.c +++ b/source/util/src/tbase64.c @@ -105,3 +105,67 @@ int32_t base64_decode(const char *value, int32_t inlen, int32_t *outlen, uint8_t return TSDB_CODE_INVALID_DATA_FMT; } + +static char tbase64_encoding_table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +void tbase64_encode(uint8_t *out, const uint8_t *input, size_t in_len, VarDataLenT out_len) { + for (size_t i = 0, j = 0; i < in_len;) { + unsigned int octet_a = i < in_len ? input[i++] : 0; + unsigned int octet_b = i < in_len ? input[i++] : 0; + unsigned int octet_c = i < in_len ? input[i++] : 0; + + unsigned int triple = (octet_a << 16) | (octet_b << 8) | octet_c; + + out[j++] = tbase64_encoding_table[(triple >> 18) & 0x3F]; + out[j++] = tbase64_encoding_table[(triple >> 12) & 0x3F]; + out[j++] = tbase64_encoding_table[(triple >> 6) & 0x3F]; + out[j++] = tbase64_encoding_table[triple & 0x3F]; + } + + for (int k = 0; k < (3 - (in_len % 3)) % 3; k++) { + out[out_len - k - 1] = '='; + } +} + +static TdThreadOnce tbase64_decoding_table_building = PTHREAD_ONCE_INIT; + +static char tbase64_decoding_table[256] = {0}; + +static void tbase64_build_decoding_table() { + for (int i = 0; i < 64; i++) { + tbase64_decoding_table[(unsigned char)tbase64_encoding_table[i]] = i; + } +} + +int32_t tbase64_decode(uint8_t *out, const uint8_t *input, size_t in_len, VarDataLenT out_len) { + (void)taosThreadOnce(&tbase64_decoding_table_building, tbase64_build_decoding_table); + + if (in_len % 4 != 0) { + return TSDB_CODE_INVALID_DATA_FMT; + } + + if (input[in_len - 1] == '=') out_len--; + if (input[in_len - 2] == '=') out_len--; + + for (int i = 0, j = 0; i < in_len;) { + uint32_t sextet_a = input[i] == '=' ? 0 & i++ : tbase64_decoding_table[input[i++]]; + uint32_t sextet_b = input[i] == '=' ? 0 & i++ : tbase64_decoding_table[input[i++]]; + uint32_t sextet_c = input[i] == '=' ? 0 & i++ : tbase64_decoding_table[input[i++]]; + uint32_t sextet_d = input[i] == '=' ? 0 & i++ : tbase64_decoding_table[input[i++]]; + + uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); + + if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF; + if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF; + if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF; + } + + return TSDB_CODE_SUCCESS; +} + +uint32_t tbase64_encode_len(size_t in_len) { return 4 * ((in_len + 2) / 3); } + +uint32_t tbase64_decode_len(size_t in_len) { return in_len / 4 * 3; } diff --git a/source/util/src/tsha.c b/source/util/src/tsha.c new file mode 100644 index 000000000000..6f24f77ebf07 --- /dev/null +++ b/source/util/src/tsha.c @@ -0,0 +1,1435 @@ +#define _DEFAULT_SOURCE +#include "tsha.h" + +#define SHA1HANDSOFF + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0_le(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF)) +#define blk0_be(i) block->l[i] +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) blk0_le(i) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) blk0_be(i) +#else +/* Fall back to a runtime endian check */ +const union { + long l; + char c; +} sha1_endian = {1}; +#define blk0(i) (sha1_endian.c == 0 ? blk0_be(i) : blk0_le(i)) +#endif + +#define blk(i) \ + (block->l[i & 15] = \ + rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R1(v, w, x, y, z, i) \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R2(v, w, x, y, z, i) \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ + w = rol(w, 30); +#define R3(v, w, x, y, z, i) \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); +#define R4(v, w, x, y, z, i) \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w = rol(w, 30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +void tSHA1Transform(uint32_t state[5], const unsigned char buffer[64]) { + uint32_t a, b, c, d, e; + + typedef union { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ + CHAR64LONG16 *block = (const CHAR64LONG16 *)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + +/* SHA1Init - Initialize new context */ + +void tSHA1Init(T_SHA1_CTX *context) { + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + +/* Run your data through this. */ + +void tSHA1Update(T_SHA1_CTX *context, const unsigned char *data, uint32_t len) { + uint32_t i; + + uint32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) context->count[1]++; + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64 - j)); + tSHA1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) { + tSHA1Transform(context->state, &data[i]); + } + j = 0; + } else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + +/* Add padding and return the message digest. */ + +void tSHA1Final(unsigned char digest[20], T_SHA1_CTX *context) { + unsigned i; + + unsigned char finalcount[8]; + + unsigned char c; + +#if 0 + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t} +#else + for (i = 0; i < 8; i++) { + finalcount[i] = + (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } +#endif + c = 0200; + tSHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) { + c = 0000; + tSHA1Update(context, &c, 1); + } + tSHA1Update(context, finalcount, 8); /* Should cause a tSHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +void tSHA1(char *hash_out, const char *str, uint32_t len) { + T_SHA1_CTX ctx; + unsigned int ii; + + tSHA1Init(&ctx); + for (ii = 0; ii < len; ii += 1) tSHA1Update(&ctx, (const unsigned char *)str + ii, 1); + tSHA1Final((unsigned char *)hash_out, &ctx); +} + +/* SHA2 algos */ + +#if 0 +#define UNROLL_LOOPS /* Enable loops unrolling */ +#endif + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) +#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) + +#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7)) +#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6)) + +#define UNPACK32(x, str) \ + { \ + *((str) + 3) = (uint8)((x)); \ + *((str) + 2) = (uint8)((x) >> 8); \ + *((str) + 1) = (uint8)((x) >> 16); \ + *((str) + 0) = (uint8)((x) >> 24); \ + } + +#define PACK32(str, x) \ + { \ + *(x) = ((uint32) * ((str) + 3)) | ((uint32) * ((str) + 2) << 8) | ((uint32) * ((str) + 1) << 16) | \ + ((uint32) * ((str) + 0) << 24); \ + } + +#define UNPACK64(x, str) \ + { \ + *((str) + 7) = (uint8)((x)); \ + *((str) + 6) = (uint8)((x) >> 8); \ + *((str) + 5) = (uint8)((x) >> 16); \ + *((str) + 4) = (uint8)((x) >> 24); \ + *((str) + 3) = (uint8)((x) >> 32); \ + *((str) + 2) = (uint8)((x) >> 40); \ + *((str) + 1) = (uint8)((x) >> 48); \ + *((str) + 0) = (uint8)((x) >> 56); \ + } + +#define PACK64(str, x) \ + { \ + *(x) = ((uint64) * ((str) + 7)) | ((uint64) * ((str) + 6) << 8) | ((uint64) * ((str) + 5) << 16) | \ + ((uint64) * ((str) + 4) << 24) | ((uint64) * ((str) + 3) << 32) | ((uint64) * ((str) + 2) << 40) | \ + ((uint64) * ((str) + 1) << 48) | ((uint64) * ((str) + 0) << 56); \ + } + +/* Macros used for loops unrolling */ + +#define SHA256_SCR(i) \ + { w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16]; } + +#define SHA512_SCR(i) \ + { w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16]; } + +#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \ + { \ + t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha256_k[j] + w[j]; \ + t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ + } + +#define SHA512_EXP(a, b, c, d, e, f, g, h, j) \ + { \ + t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) + sha512_k[j] + w[j]; \ + t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ + } + +static const uint32 sha224_h0[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; + +static const uint32 sha256_h0[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +static const uint64 sha384_h0[8] = {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}; + +static const uint64 sha512_h0[8] = {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}; + +static const uint32 sha256_k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +static const uint64 sha512_k[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, + 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, + 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, + 0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, + 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, + 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL}; + +/* SHA-2 internal function */ + +static void sha256_transf(sha256_ctx *ctx, const uint8 *message, uint64 block_nb) { + uint32 w[64]; + uint32 wv[8]; + uint32 t1, t2; + const uint8 *sub_block; + uint64 i; + +#ifndef UNROLL_LOOPS + int j; +#endif + + for (i = 0; i < block_nb; i++) { + sub_block = message + (i << 6); + +#ifndef UNROLL_LOOPS + for (j = 0; j < 16; j++) { + PACK32(&sub_block[j << 2], &w[j]); + } + + for (j = 16; j < 64; j++) { + SHA256_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 64; j++) { + t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j]; + t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } +#else + PACK32(&sub_block[0], &w[0]); + PACK32(&sub_block[4], &w[1]); + PACK32(&sub_block[8], &w[2]); + PACK32(&sub_block[12], &w[3]); + PACK32(&sub_block[16], &w[4]); + PACK32(&sub_block[20], &w[5]); + PACK32(&sub_block[24], &w[6]); + PACK32(&sub_block[28], &w[7]); + PACK32(&sub_block[32], &w[8]); + PACK32(&sub_block[36], &w[9]); + PACK32(&sub_block[40], &w[10]); + PACK32(&sub_block[44], &w[11]); + PACK32(&sub_block[48], &w[12]); + PACK32(&sub_block[52], &w[13]); + PACK32(&sub_block[56], &w[14]); + PACK32(&sub_block[60], &w[15]); + + SHA256_SCR(16); + SHA256_SCR(17); + SHA256_SCR(18); + SHA256_SCR(19); + SHA256_SCR(20); + SHA256_SCR(21); + SHA256_SCR(22); + SHA256_SCR(23); + SHA256_SCR(24); + SHA256_SCR(25); + SHA256_SCR(26); + SHA256_SCR(27); + SHA256_SCR(28); + SHA256_SCR(29); + SHA256_SCR(30); + SHA256_SCR(31); + SHA256_SCR(32); + SHA256_SCR(33); + SHA256_SCR(34); + SHA256_SCR(35); + SHA256_SCR(36); + SHA256_SCR(37); + SHA256_SCR(38); + SHA256_SCR(39); + SHA256_SCR(40); + SHA256_SCR(41); + SHA256_SCR(42); + SHA256_SCR(43); + SHA256_SCR(44); + SHA256_SCR(45); + SHA256_SCR(46); + SHA256_SCR(47); + SHA256_SCR(48); + SHA256_SCR(49); + SHA256_SCR(50); + SHA256_SCR(51); + SHA256_SCR(52); + SHA256_SCR(53); + SHA256_SCR(54); + SHA256_SCR(55); + SHA256_SCR(56); + SHA256_SCR(57); + SHA256_SCR(58); + SHA256_SCR(59); + SHA256_SCR(60); + SHA256_SCR(61); + SHA256_SCR(62); + SHA256_SCR(63); + + wv[0] = ctx->h[0]; + wv[1] = ctx->h[1]; + wv[2] = ctx->h[2]; + wv[3] = ctx->h[3]; + wv[4] = ctx->h[4]; + wv[5] = ctx->h[5]; + wv[6] = ctx->h[6]; + wv[7] = ctx->h[7]; + + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63); + + ctx->h[0] += wv[0]; + ctx->h[1] += wv[1]; + ctx->h[2] += wv[2]; + ctx->h[3] += wv[3]; + ctx->h[4] += wv[4]; + ctx->h[5] += wv[5]; + ctx->h[6] += wv[6]; + ctx->h[7] += wv[7]; +#endif /* !UNROLL_LOOPS */ + } +} + +static void sha512_transf(sha512_ctx *ctx, const uint8 *message, uint64 block_nb) { + uint64 w[80]; + uint64 wv[8]; + uint64 t1, t2; + const uint8 *sub_block; + uint64 i; + int j; + + for (i = 0; i < block_nb; i++) { + sub_block = message + (i << 7); + +#ifndef UNROLL_LOOPS + for (j = 0; j < 16; j++) { + PACK64(&sub_block[j << 3], &w[j]); + } + + for (j = 16; j < 80; j++) { + SHA512_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 80; j++) { + t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha512_k[j] + w[j]; + t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } +#else + PACK64(&sub_block[0], &w[0]); + PACK64(&sub_block[8], &w[1]); + PACK64(&sub_block[16], &w[2]); + PACK64(&sub_block[24], &w[3]); + PACK64(&sub_block[32], &w[4]); + PACK64(&sub_block[40], &w[5]); + PACK64(&sub_block[48], &w[6]); + PACK64(&sub_block[56], &w[7]); + PACK64(&sub_block[64], &w[8]); + PACK64(&sub_block[72], &w[9]); + PACK64(&sub_block[80], &w[10]); + PACK64(&sub_block[88], &w[11]); + PACK64(&sub_block[96], &w[12]); + PACK64(&sub_block[104], &w[13]); + PACK64(&sub_block[112], &w[14]); + PACK64(&sub_block[120], &w[15]); + + SHA512_SCR(16); + SHA512_SCR(17); + SHA512_SCR(18); + SHA512_SCR(19); + SHA512_SCR(20); + SHA512_SCR(21); + SHA512_SCR(22); + SHA512_SCR(23); + SHA512_SCR(24); + SHA512_SCR(25); + SHA512_SCR(26); + SHA512_SCR(27); + SHA512_SCR(28); + SHA512_SCR(29); + SHA512_SCR(30); + SHA512_SCR(31); + SHA512_SCR(32); + SHA512_SCR(33); + SHA512_SCR(34); + SHA512_SCR(35); + SHA512_SCR(36); + SHA512_SCR(37); + SHA512_SCR(38); + SHA512_SCR(39); + SHA512_SCR(40); + SHA512_SCR(41); + SHA512_SCR(42); + SHA512_SCR(43); + SHA512_SCR(44); + SHA512_SCR(45); + SHA512_SCR(46); + SHA512_SCR(47); + SHA512_SCR(48); + SHA512_SCR(49); + SHA512_SCR(50); + SHA512_SCR(51); + SHA512_SCR(52); + SHA512_SCR(53); + SHA512_SCR(54); + SHA512_SCR(55); + SHA512_SCR(56); + SHA512_SCR(57); + SHA512_SCR(58); + SHA512_SCR(59); + SHA512_SCR(60); + SHA512_SCR(61); + SHA512_SCR(62); + SHA512_SCR(63); + SHA512_SCR(64); + SHA512_SCR(65); + SHA512_SCR(66); + SHA512_SCR(67); + SHA512_SCR(68); + SHA512_SCR(69); + SHA512_SCR(70); + SHA512_SCR(71); + SHA512_SCR(72); + SHA512_SCR(73); + SHA512_SCR(74); + SHA512_SCR(75); + SHA512_SCR(76); + SHA512_SCR(77); + SHA512_SCR(78); + SHA512_SCR(79); + + wv[0] = ctx->h[0]; + wv[1] = ctx->h[1]; + wv[2] = ctx->h[2]; + wv[3] = ctx->h[3]; + wv[4] = ctx->h[4]; + wv[5] = ctx->h[5]; + wv[6] = ctx->h[6]; + wv[7] = ctx->h[7]; + + j = 0; + + do { + SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j); + j++; + SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j); + j++; + SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j); + j++; + SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j); + j++; + SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j); + j++; + SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j); + j++; + SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j); + j++; + SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j); + j++; + } while (j < 80); + + ctx->h[0] += wv[0]; + ctx->h[1] += wv[1]; + ctx->h[2] += wv[2]; + ctx->h[3] += wv[3]; + ctx->h[4] += wv[4]; + ctx->h[5] += wv[5]; + ctx->h[6] += wv[6]; + ctx->h[7] += wv[7]; +#endif /* !UNROLL_LOOPS */ + } +} + +/* SHA-224 functions */ + +void sha224(const uint8 *message, uint64 len, uint8 *digest) { + sha224_ctx ctx; + + sha224_init(&ctx); + sha224_update(&ctx, message, len); + sha224_final(&ctx, digest); +} + +void sha224_init(sha224_ctx *ctx) { +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha224_h0[i]; + } +#else + ctx->h[0] = sha224_h0[0]; + ctx->h[1] = sha224_h0[1]; + ctx->h[2] = sha224_h0[2]; + ctx->h[3] = sha224_h0[3]; + ctx->h[4] = sha224_h0[4]; + ctx->h[5] = sha224_h0[5]; + ctx->h[6] = sha224_h0[6]; + ctx->h[7] = sha224_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha224_update(sha224_ctx *ctx, const uint8 *message, uint64 len) { + uint64 block_nb; + uint64 new_len, rem_len, tmp_len; + const uint8 *shifted_message; + + tmp_len = SHA224_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA224_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA224_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA224_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha224_final(sha224_ctx *ctx, uint8 *digest) { + uint64 block_nb; + uint64 pm_len; + uint64 len_b; + uint64 tot_len; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = (1 + ((SHA224_BLOCK_SIZE - 9) < (ctx->len % SHA224_BLOCK_SIZE))); + + tot_len = ctx->tot_len + ctx->len; + ctx->tot_len = tot_len; + + len_b = tot_len << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK64(len_b, ctx->block + pm_len - 8); + + sha256_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0; i < 7; i++) { + UNPACK32(ctx->h[i], &digest[i << 2]); + } +#else + UNPACK32(ctx->h[0], &digest[0]); + UNPACK32(ctx->h[1], &digest[4]); + UNPACK32(ctx->h[2], &digest[8]); + UNPACK32(ctx->h[3], &digest[12]); + UNPACK32(ctx->h[4], &digest[16]); + UNPACK32(ctx->h[5], &digest[20]); + UNPACK32(ctx->h[6], &digest[24]); +#endif /* !UNROLL_LOOPS */ +} + +/* SHA-256 functions */ + +void sha256(const uint8 *message, uint64 len, uint8 *digest) { + sha256_ctx ctx; + + sha256_init(&ctx); + sha256_update(&ctx, message, len); + sha256_final(&ctx, digest); +} + +void sha256_init(sha256_ctx *ctx) { +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha256_h0[i]; + } +#else + ctx->h[0] = sha256_h0[0]; + ctx->h[1] = sha256_h0[1]; + ctx->h[2] = sha256_h0[2]; + ctx->h[3] = sha256_h0[3]; + ctx->h[4] = sha256_h0[4]; + ctx->h[5] = sha256_h0[5]; + ctx->h[6] = sha256_h0[6]; + ctx->h[7] = sha256_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha256_update(sha256_ctx *ctx, const uint8 *message, uint64 len) { + uint64 block_nb; + uint64 new_len, rem_len, tmp_len; + const uint8 *shifted_message; + + tmp_len = SHA256_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA256_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA256_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA256_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha256_final(sha256_ctx *ctx, uint8 *digest) { + uint64 block_nb; + uint64 pm_len; + uint64 len_b; + uint64 tot_len; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE))); + + tot_len = ctx->tot_len + ctx->len; + ctx->tot_len = tot_len; + + len_b = tot_len << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK64(len_b, ctx->block + pm_len - 8); + + sha256_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0; i < 8; i++) { + UNPACK32(ctx->h[i], &digest[i << 2]); + } +#else + UNPACK32(ctx->h[0], &digest[0]); + UNPACK32(ctx->h[1], &digest[4]); + UNPACK32(ctx->h[2], &digest[8]); + UNPACK32(ctx->h[3], &digest[12]); + UNPACK32(ctx->h[4], &digest[16]); + UNPACK32(ctx->h[5], &digest[20]); + UNPACK32(ctx->h[6], &digest[24]); + UNPACK32(ctx->h[7], &digest[28]); +#endif /* !UNROLL_LOOPS */ +} + +/* SHA-384 functions */ + +void sha384(const uint8 *message, uint64 len, uint8 *digest) { + sha384_ctx ctx; + + sha384_init(&ctx); + sha384_update(&ctx, message, len); + sha384_final(&ctx, digest); +} + +void sha384_init(sha384_ctx *ctx) { +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha384_h0[i]; + } +#else + ctx->h[0] = sha384_h0[0]; + ctx->h[1] = sha384_h0[1]; + ctx->h[2] = sha384_h0[2]; + ctx->h[3] = sha384_h0[3]; + ctx->h[4] = sha384_h0[4]; + ctx->h[5] = sha384_h0[5]; + ctx->h[6] = sha384_h0[6]; + ctx->h[7] = sha384_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha384_update(sha384_ctx *ctx, const uint8 *message, uint64 len) { + uint64 block_nb; + uint64 new_len, rem_len, tmp_len; + const uint8 *shifted_message; + + tmp_len = SHA384_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA384_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA384_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha512_transf(ctx, ctx->block, 1); + sha512_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA384_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void sha384_final(sha384_ctx *ctx, uint8 *digest) { + uint64 block_nb; + uint64 pm_len; + uint64 len_b; + uint64 tot_len; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = (1 + ((SHA384_BLOCK_SIZE - 17) < (ctx->len % SHA384_BLOCK_SIZE))); + + tot_len = ctx->tot_len + ctx->len; + ctx->tot_len = tot_len; + + len_b = tot_len << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK64(len_b, ctx->block + pm_len - 8); + + sha512_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0; i < 6; i++) { + UNPACK64(ctx->h[i], &digest[i << 3]); + } +#else + UNPACK64(ctx->h[0], &digest[0]); + UNPACK64(ctx->h[1], &digest[8]); + UNPACK64(ctx->h[2], &digest[16]); + UNPACK64(ctx->h[3], &digest[24]); + UNPACK64(ctx->h[4], &digest[32]); + UNPACK64(ctx->h[5], &digest[40]); +#endif /* !UNROLL_LOOPS */ +} + +/* SHA-512 functions */ + +void sha512(const uint8 *message, uint64 len, uint8 *digest) { + sha512_ctx ctx; + + sha512_init(&ctx); + sha512_update(&ctx, message, len); + sha512_final(&ctx, digest); +} + +void sha512_init(sha512_ctx *ctx) { +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha512_h0[i]; + } +#else + ctx->h[0] = sha512_h0[0]; + ctx->h[1] = sha512_h0[1]; + ctx->h[2] = sha512_h0[2]; + ctx->h[3] = sha512_h0[3]; + ctx->h[4] = sha512_h0[4]; + ctx->h[5] = sha512_h0[5]; + ctx->h[6] = sha512_h0[6]; + ctx->h[7] = sha512_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha512_update(sha512_ctx *ctx, const uint8 *message, uint64 len) { + uint64 block_nb; + uint64 new_len, rem_len, tmp_len; + const uint8 *shifted_message; + + tmp_len = SHA512_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA512_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA512_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha512_transf(ctx, ctx->block, 1); + sha512_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA512_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void sha512_final(sha512_ctx *ctx, uint8 *digest) { + uint64 block_nb; + uint64 pm_len; + uint64 len_b; + uint64 tot_len; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = 1 + ((SHA512_BLOCK_SIZE - 17) < (ctx->len % SHA512_BLOCK_SIZE)); + + tot_len = ctx->tot_len + ctx->len; + ctx->tot_len = tot_len; + + len_b = tot_len << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK64(len_b, ctx->block + pm_len - 8); + + sha512_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0; i < 8; i++) { + UNPACK64(ctx->h[i], &digest[i << 3]); + } +#else + UNPACK64(ctx->h[0], &digest[0]); + UNPACK64(ctx->h[1], &digest[8]); + UNPACK64(ctx->h[2], &digest[16]); + UNPACK64(ctx->h[3], &digest[24]); + UNPACK64(ctx->h[4], &digest[32]); + UNPACK64(ctx->h[5], &digest[40]); + UNPACK64(ctx->h[6], &digest[48]); + UNPACK64(ctx->h[7], &digest[56]); +#endif /* !UNROLL_LOOPS */ +} + +#ifdef TEST_VECTORS + +/* FIPS 180-2 Validation tests */ + +#include +#include + +void test(const char *vector, uint8 *digest, uint32 digest_size) { + char output[2 * SHA512_DIGEST_SIZE + 1]; + int i; + + output[2 * digest_size] = '\0'; + + for (i = 0; i < (int)digest_size; i++) { + sprintf(output + 2 * i, "%02x", digest[i]); + } + + printf("H: %s\n", output); + if (strcmp(vector, output)) { + fprintf(stderr, "Test failed.\n"); + exit(EXIT_FAILURE); + } +} + +static void test_sha224_message4(uint8 *digest) { + /* Message of 929271 bytes */ + + sha224_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha224_init(&ctx); + for (i = 0; i < 929; i++) { + sha224_update(&ctx, message, sizeof(message)); + } + sha224_update(&ctx, message, 271); + + sha224_final(&ctx, digest); +} + +static void test_sha256_message4(uint8 *digest) { + /* Message of 929271 bytes */ + + sha256_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha256_init(&ctx); + for (i = 0; i < 929; i++) { + sha256_update(&ctx, message, sizeof(message)); + } + sha256_update(&ctx, message, 271); + + sha256_final(&ctx, digest); +} + +static void test_sha384_message4(uint8 *digest) { + /* Message of 929271 bytes */ + + sha384_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha384_init(&ctx); + for (i = 0; i < 929; i++) { + sha384_update(&ctx, message, sizeof(message)); + } + sha384_update(&ctx, message, 271); + + sha384_final(&ctx, digest); +} + +static void test_sha512_message4(uint8 *digest) { + /* Message of 929271 bytes */ + + sha512_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha512_init(&ctx); + for (i = 0; i < 929; i++) { + sha512_update(&ctx, message, sizeof(message)); + } + sha512_update(&ctx, message, 271); + + sha512_final(&ctx, digest); +} + +#ifdef TEST_VECTORS_LONG + +/* Validation tests with a message of 10 GB */ + +static void test_sha224_long_message(uint8 *digest) { + sha224_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha224_init(&ctx); + for (i = 0; i < 10000000; i++) { + sha224_update(&ctx, message, sizeof(message)); + } + sha224_final(&ctx, digest); +} + +static void test_sha256_long_message(uint8 *digest) { + sha256_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha256_init(&ctx); + for (i = 0; i < 10000000; i++) { + sha256_update(&ctx, message, sizeof(message)); + } + sha256_final(&ctx, digest); +} + +static void test_sha384_long_message(uint8 *digest) { + sha384_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha384_init(&ctx); + for (i = 0; i < 10000000; i++) { + sha384_update(&ctx, message, sizeof(message)); + } + sha384_final(&ctx, digest); +} + +static void test_sha512_long_message(uint8 *digest) { + sha512_ctx ctx; + uint8 message[1000]; + int i; + + memset(message, 'a', sizeof(message)); + + sha512_init(&ctx); + for (i = 0; i < 10000000; i++) { + sha512_update(&ctx, message, sizeof(message)); + } + sha512_final(&ctx, digest); +} + +#endif /* TEST_VECTORS_LONG */ + +int main(void) { + static const char *vectors[4][5] = {/* SHA-224 */ + { + "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", + "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525", + "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67", + "c84cf4761583afa849ffd562c52a2e2a5104f1a4071dab6c53560d4f", + "b7bdc6c1f4f789f1456e68a005779a6c1f6199211008bee2801baf0d", + }, + /* SHA-256 */ + { + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", + "8c14f43ad81026351e9b60025b5420e6072ff617f5c72145b179599211514947", + "53748286337dbe36f5df22e7ef1af3ad71530398cf569adc7eb5fefa7af7003c", + }, + /* SHA-384 */ + { + "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" + "8086072ba1e7cc2358baeca134c825a7", + "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" + "fcc7c71a557e2db966c3e9fa91746039", + "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b" + "07b8b3dc38ecc4ebae97ddd87f3d8985", + "3de4a44dba8627278c376148b6d45be0a3a410337330ef3e1d9ca34c4593ecfc" + "8ce7a8415aefaca6b39d1112078cc3e0", + "073de8e641532032b2922c4af165baa88dfe5fdafb09575657406894b4b94996" + "8975eef50c1ef5be59ca0ecdaa996496", + }, + /* SHA-512 */ + {"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909", + "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" + "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b", + "a7e464bfd1f27201d7d0575c1a302cecef0004828e923e4255c8de6bae958a01" + "9294e3f851bf9a03013963cd1268687c549916438e465433957d4480bcaa8572", + "922637075a3ee5d87a7ce3ae7e04083d6daea7b541f264512290157ce3f81f9b" + "afcd3f9dc2d4fe0a6248a071709b96d0128d96c48220b2ab919b99187cb16fbf"}}; + + static const char message1[] = "abc"; + static const char message2a[] = + "abcdbcdecdefdefgefghfghighijhi" + "jkijkljklmklmnlmnomnopnopq"; + static const char message2b[] = + "abcdefghbcdefghicdefghijdefghijkefghij" + "klfghijklmghijklmnhijklmnoijklmnopjklm" + "nopqklmnopqrlmnopqrsmnopqrstnopqrstu"; + uint8 *message3; + uint32 message3_len = 1000000; + uint8 digest[SHA512_DIGEST_SIZE]; + + message3 = malloc(message3_len); + if (message3 == NULL) { + fprintf(stderr, "Can't allocate memory\n"); + return -1; + } + memset(message3, 'a', message3_len); + + printf("SHA-2 FIPS 180-2 Validation tests\n\n"); + printf("SHA-224 Test vectors\n"); + + sha224((const uint8 *)message1, strlen(message1), digest); + test(vectors[0][0], digest, SHA224_DIGEST_SIZE); + sha224((const uint8 *)message2a, strlen(message2a), digest); + test(vectors[0][1], digest, SHA224_DIGEST_SIZE); + sha224(message3, message3_len, digest); + test(vectors[0][2], digest, SHA224_DIGEST_SIZE); + test_sha224_message4(digest); + test(vectors[0][3], digest, SHA224_DIGEST_SIZE); +#ifdef TEST_VECTORS_LONG + test_sha224_long_message(digest); + test(vectors[0][4], digest, SHA224_DIGEST_SIZE); +#endif + printf("\n"); + + printf("SHA-256 Test vectors\n"); + + sha256((const uint8 *)message1, strlen(message1), digest); + test(vectors[1][0], digest, SHA256_DIGEST_SIZE); + sha256((const uint8 *)message2a, strlen(message2a), digest); + test(vectors[1][1], digest, SHA256_DIGEST_SIZE); + sha256(message3, message3_len, digest); + test(vectors[1][2], digest, SHA256_DIGEST_SIZE); + test_sha256_message4(digest); + test(vectors[1][3], digest, SHA256_DIGEST_SIZE); +#ifdef TEST_VECTORS_LONG + test_sha256_long_message(digest); + test(vectors[1][4], digest, SHA256_DIGEST_SIZE); +#endif + printf("\n"); + + printf("SHA-384 Test vectors\n"); + + sha384((const uint8 *)message1, strlen(message1), digest); + test(vectors[2][0], digest, SHA384_DIGEST_SIZE); + sha384((const uint8 *)message2b, strlen(message2b), digest); + test(vectors[2][1], digest, SHA384_DIGEST_SIZE); + sha384(message3, message3_len, digest); + test(vectors[2][2], digest, SHA384_DIGEST_SIZE); + test_sha384_message4(digest); + test(vectors[2][3], digest, SHA384_DIGEST_SIZE); +#ifdef TEST_VECTORS_LONG + test_sha384_long_message(digest); + test(vectors[2][4], digest, SHA384_DIGEST_SIZE); +#endif + printf("\n"); + + printf("SHA-512 Test vectors\n"); + + sha512((const uint8 *)message1, strlen(message1), digest); + test(vectors[3][0], digest, SHA512_DIGEST_SIZE); + sha512((const uint8 *)message2b, strlen(message2b), digest); + test(vectors[3][1], digest, SHA512_DIGEST_SIZE); + sha512(message3, message3_len, digest); + test(vectors[3][2], digest, SHA512_DIGEST_SIZE); + test_sha512_message4(digest); + test(vectors[3][3], digest, SHA512_DIGEST_SIZE); +#ifdef TEST_VECTORS_LONG + test_sha512_long_message(digest); + test(vectors[3][4], digest, SHA512_DIGEST_SIZE); +#endif + printf("\n"); + + printf("All tests passed.\n"); + + return 0; +} + +#endif /* TEST_VECTORS */