📄 sps.c
字号:
* @return SPS_SUCCESSFUL in case of success * SPS_NULL_PTR_FAIL in case of null pointer * SPS_PHEADER_FAIL if size and number of patch records * is inconsistent */SpsSuccess_t SpsEvaluatePatchHeader(SpsPpPatchHeader_t * pHeader){ SpsSuccess_t ret; ret = SPS_UNSUCCESSFUL; do { if (pHeader == NULL) { ret = SPS_NULL_PTR_FAIL; break; } if (pHeader->PrSize < 4) { ret = SPS_PHEADER_FAIL; break; } ret = SPS_SUCCESSFUL; } while (0); return ret;}/** * @brief check consistency of the shadow patch buffer * validates the sizes, lengths and number of patch records * of the received data * * @param pBuf address of the patch shadow buffer * @param Size size of the patch shadow buffer * @param PrNb number of expected patch records * @param PrSize expected patch data size * * @return SPS_SUCCESSFUL or error code in case of any inconsitency * */SpsSuccess_t SpsEvaluatePatchBuffer(Int8 * pBuf, Int32 Size, Int32 PrSize){ SpsSuccess_t ret; SpsPpPatchRecord_t *pPr; Int32 offset, prcnt; ret = SPS_UNSUCCESSFUL; do { if ((pBuf == NULL) || (Size == 0)) { ret = SPS_NULL_PTR_FAIL; break; }#if 0 offset = 0; prcnt = 0; /* iterate over data - patch record by patch record */ while (offset < Size) { if ((Size - offset) < PP_PR_MIN_SIZE) { /* not enough for a valid patch record */ break; } pPr = (SpsPpPatchRecord_t *) & (pBuf[offset]); prcnt++; offset += pPr->Length + PP_PR_HEADER_LENGTH; } /* we received not exact the amount of data, that we received in all fragments */ if (offset != Size) { ret = SPS_PP_DATASIZE_FAIL; break; } /* we did not receive the expected amount data */ if (offset != PrSize) { ret = SPS_EPR_LENGTH_FAIL; break; } /* in the data we did not found the expected number of patch records */ if (prcnt != PrNb) { ret = SPS_PP_NBPR_FAIL; break; }#endif /* at this point the check is passed */ ret = SPS_SUCCESSFUL; } while (0); return ret;}/** * @brief retrieve from the ssf context the * shadow buffer, where the patch data are stored * before they cpoied to the patch RAM. * * @param pCtx pointer to sps context structure * * @return SPS_SUCCESSFUL or error code if something goes wrong * */SpsSuccess_t SpsAssignPatchBufferToContext(SpsContext_t * pCtx){ SpsSuccess_t ret; SsfSuccess_t retssf; ret = SPS_UNSUCCESSFUL; do { if (pCtx == NULL) { ret = SPS_NULL_PTR_FAIL; break; } pCtx->pPatchBuffer = NULL; pCtx->PatchBufferSize = 0; retssf = SsfGetSpsBuffer(&pCtx->pPatchBuffer, &pCtx->PatchBufferSize); if (retssf != SSF_SUCCESSFUL) { break; } if (pCtx->patchheader.PrSize > pCtx->PatchBufferSize) { pCtx->OverFlowObserved = 1; ret = SPS_SMALL_BUFFER_FAIL; break; } ret = SPS_SUCCESSFUL; } while (0); return ret;}/** * @brief validates the EPR record * if this function returns success, the PR Data are * installed in the PatchBuffer * * @param pEpr pointer to encapsulate patch record * * @return SPS_SUCCESSFUL */SpsSuccess_t SpsEvaluateEprData(SpsPpPatchRecord_t * pPr){ SpsSuccess_t ret; do { if (pPr == NULL) { ret = SPS_NULL_PTR_FAIL; break; } if (pPr->Length < PP_PR_MIN_LENGTH) { ret = SPS_EPR_LENGTH_FAIL; break; } if (pPr->Length > PP_PR_MAX_LENGTH) { ret = SPS_EPR_LENGTH_FAIL; break; } ret = SPS_SUCCESSFUL; } while (0); return ret;}/** * @brief reset all variables in the SPS context, * which depend on a patch package; * * @param pCtx pointer to SPS context structure * * @return SPS_UNSUCCESSFUL if pCtx is NULL, otherwise * SPS_SUCCESSFUL */SpsSuccess_t SpsResetContext(SpsContext_t * pCtx){ SpsSuccess_t ret; ret = SPS_UNSUCCESSFUL; if (pCtx != NULL) { if (TRUE == SpsIsPatchChainComplete(&pCtx->patchheader)) { DP0(("SPS Reset: patch chain end!")); if (pCtx->pDveWorkspace != NULL) { DP0(("SPS Reset: free pDveWorkspace")); SsfFree(pCtx->pDveWorkspace); pCtx->pDveWorkspace = NULL; } } else { DP0(("SPS Reset: patch chain continues!")); } pCtx->OverFlowObserved = FALSE; pCtx->TrustedEncrKey = FALSE; pCtx->WithSignature = FALSE; ssf_memset(&pCtx->patchheader, 0, sizeof(SpsPpPatchHeader_t)); pCtx->PatchRecordCnt = 0; ret = SPS_SUCCESSFUL; } return ret;}/** * @brief setup the decrypt and signature context * @param pCtx sps context pointer * @param pInfo Info Structure pointer * * @return SPS_UNSUCCESSFUL in any case of error * else SPS_SUCCESSFUL */SpsSuccess_t SpsSecurityInit(SpsContext_t * pCtx, SpsPpPatchInfo_t * pInfo){ SpsSuccess_t ret; Int32 i; Int8 val; ret = SPS_UNSUCCESSFUL; do { /* setup security, if patch is a signed patch */ /* check the encryption key, if Iv is 0, then it's untrusted */ val = 0; for (i = 0; i < PP_CRYPT_IV_LENGTH; i++) { val += pInfo->Iv[i]; } if (val != 0) { pCtx->TrustedEncrKey = TRUE; } else { pCtx->TrustedEncrKey = FALSE; } /* check if it looks like a signature */ val = 0; for (i = 0; i < PP_SIGNATURE_DATA_SIZE; i++) { val |= pInfo->SigData[i]; } /* if it is a signed patch, setup security */ /* todo mgrell: review this check; is it secure? */ if (val != PP_INVALID_SIGNATURE_PATTERN) { DP0(("SPS: patch is signed")); pCtx->WithSignature = TRUE; if (pCtx->pDveWorkspace == NULL) { DP0(("SPS: allocate new workspace")); pCtx->pDveWorkspace = SsfMalloc(sizeof(dve_workspace_t)); if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_DVEINIT) != 0) { DP0(("SPS: dve init")); dve_init(pInfo->SigData, pInfo->Iv, pCtx->pDveWorkspace); } } i = 0; if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_DVEPROCESS) != 0) { DP0(("SPS: dve process info")); i = dve_process(pInfo->SigData, PP_SIGNATURE_DATA_SIZE, pCtx->IntCheckMode); } if (0 != i) { DP0(("SPS: invalid security header")); ret = SPS_UNSUCCESSFUL; break; } } else { DP0(("SPS: patch is not signed")); pCtx->WithSignature = FALSE; } /* processing of hash chain */ if (pCtx->pHashChainWorkspace == NULL) { pCtx->pHashChainWorkspace = SsfMalloc(SPS_HC_WORKSPACE_SIZE); ssf_memset(pCtx->pHashChainWorkspace, 0, SPS_HC_WORKSPACE_SIZE); } ret = SPS_SUCCESSFUL; if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_HCINIT) != 0) { DP0(("SPS: hc init")); ret = SpsHashChainInit((SpsHashChainWorkspace_t *) pCtx-> pHashChainWorkspace); } if (ret != SPS_SUCCESSFUL) { DP0(("SPS: error setup hash chain\n")); break; } ret = SPS_SUCCESSFUL; } while (0); return ret;}/** * @brief update a data block with the security function * * @param pCtx pointer to SPS context * @param pData pointer to data buffer * because the decryption of data occurs in place, * the buffer is overwritten with the decrypted data * @param Size number of bytes to process * * @return number of processed bytes */Int32 SpsSecurityUpdate(SpsContext_t * pCtx, Int8 * pData, Int32 Size){ Int32 ret; ret = Size; if (pCtx->pDveWorkspace != NULL) { /* it's a dve fragment */ if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_DVEPROCESS) != 0) { ret = dve_process(pData, Size, pCtx->IntCheckMode); } } /* we discard here the return value, no matter, what happens, we * will see later */ if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_HCPROCESS) != 0) { SpsHashChainProcess((SpsHashChainWorkspace_t *) pCtx-> pHashChainWorkspace, pData, Size); } return ret;}/** * @brief evaluate the security level of the * current patch * @param pCtx patch context structure * * @return numeric value of trust level * trusted encr key used : 1 point * patch is signed : 1 point * signature check ok : 3 points * */Int8 SpsComputeTrustLevel(SpsContext_t * pCtx){ Int8 ret; int retsig; ret = 0; do { if (pCtx == NULL) { break; } if (pCtx->WithSignature == TRUE) { ret++; } if (pCtx->TrustedEncrKey == TRUE) { ret++; } if (pCtx->pDveWorkspace != NULL) { retsig = 0; if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_DVESIGCHK) != 0) { /* this saves time, we do not try to check the * 0x55 dummy signature pattern (chained patch) */ if (pCtx->WithSignature == TRUE) { retsig = dve_sigcheck(); DP0(("SPS: sig check result is %d", retsig)); } } if (retsig == 0) { ret += 3; } } if ((SsfGetSecurityEnableMask() & SECURITY_ENABLE_HCCHK) != 0) { ret += SpsHashChainCheckHash((SpsHashChainWorkspace_t *) pCtx-> pHashChainWorkspace); } } while (0); return ret;}/** * @brief test, if the patch chain is finished. * * @param pHeader pointer to the patch header * * @return TRUE, if the whole sha1 field consists * of PP_PATCH_CHAIN_END_PATTERN (0xaa) * otherwise FALSE */Boolean SpsIsPatchChainComplete(SpsPpPatchHeader_t * pHeader){ Boolean ret; Int32 i; Int8 val; ret = FALSE; if (pHeader != NULL) { val = 0; for (i = 0; i < PP_SHA1_LENGTH; i++) { val |= pHeader->sha1[i]; } if (val == PP_PATCH_CHAIN_END_PATTERN) { ret = TRUE; } } return ret;}/**\}*//* ------------------------------------------------------------------------- *//**\}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -