security_huks/huks_standard/common/hks_base_check源码分析(二)

总体概述

封装各种参数的检查函数,包括RSA AES的各种参数的校对与检查
各种模式包括GCM CBC等额外参数的检查

代码详解

各种算法的签名检查函数

注意这里的检查绝大部分是对长度进行规范检查

  1. ECC签名检查
    验证的规则在代码中已经详细的写出根据cmdId进行上限或下限的检验
    在这里插入图片描述
  2. Ed25519椭圆加密算法的签名检查
    验证的思路跟ECC相似
    在这里插入图片描述
  3. 对于RSA进行padding和签名长度的检查
    这里GenKeyPadding值的验证使用了函数HksCheckValue()进行输入值和期望值的比较,这里不再是参数长度规范的检查而是实实在在的参数验证(是否一致)
    在这里插入图片描述

RSA和AES算法的数据size检查

RSA

  1. 对于inData和outData的size检查
    在这里插入图片描述
  2. 对于RSA加密数据的size检查
//对于RSA加密数据的长度进行检查
//OAEP:最优非对称加密填充
static int32_t CheckRsaOaepCipherData(uint32_t cmdId, uint32_t keySize, uint32_t digest,
    const struct HksBlob *inData, const struct HksBlob *outData)
{
    uint32_t digestLen;
    //获取digest的长度在digestLen中
    int32_t ret = HksGetDigestLen(digest, &digestLen);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("GetDigestLen failed, ret = %x", ret);
        return ret;
    }
    /*
     * encrypt: inSize no greater than keySize - 2*digestLen - 2, outSize no less than keySize (in: plain; out: cipher)
     * decrypt: inSize no greater than keySize, outSize no less than keySize - 2*digestLen - 2 (in: cipher; out: plain)
     */
    if (keySize <= (HKS_RSA_OAEP_DIGEST_NUM * digestLen - HKS_RSA_OAEP_DIGEST_NUM)) {
        return HKS_ERROR_INVALID_KEY_FILE;
    }
    uint32_t size = keySize - HKS_RSA_OAEP_DIGEST_NUM * digestLen - HKS_RSA_OAEP_DIGEST_NUM;
    //对数据进行size检查
    if (cmdId == HKS_CMD_ID_ENCRYPT) {
        if (inData->size > size) {
            HKS_LOG_E("encrypt, invalid insize: %u, keySize: %u, digestLen: %u", inData->size, keySize, digestLen);
            return HKS_ERROR_INVALID_ARGUMENT;
        }
        if (outData->size < keySize) {
            HKS_LOG_E("encrypt, outData buffer too small size: %u, keySize: %u", outData->size, keySize);
            return HKS_ERROR_BUFFER_TOO_SMALL;
        }
    } else if (cmdId == HKS_CMD_ID_DECRYPT) {
        if (inData->size > keySize) {
            HKS_LOG_E("decrypt, invalid inData size: %u, keySize: %u", inData->size, keySize);
            return HKS_ERROR_INVALID_ARGUMENT;
        }
        if (outData->size < size) {
            HKS_LOG_E("decrypt, outData buffer too small size: %u, keySize: %u", outData->size, keySize);
            return HKS_ERROR_BUFFER_TOO_SMALL;
        }
    }

    return HKS_SUCCESS;
}
  1. RSA加密算法是否使用padding的封装调用检查函数
    在这里插入图片描述

AES

AES的参数检查框架几乎和RSA相同,内部略有不同:
1.padding模式上分为CBC GCM有不同的padding进行value检查
2.加密模式又分为CBC和AE,根据mode的不同调用不同的检查函数进行检查

#ifdef HKS_SUPPORT_AES_C
//对于AES进行padding检查
//mode的不同对应的g_padding不同
static int32_t CheckAesPadding(uint32_t mode, uint32_t padding)
{
    if (mode == HKS_MODE_CBC) {
        return HksCheckValue(padding, g_aesCbcPadding, HKS_ARRAY_SIZE(g_aesCbcPadding));
    }

    if ((mode == HKS_MODE_GCM) || (mode == HKS_MODE_CCM)) {
        return HksCheckValue(padding, g_aesAeadPadding, HKS_ARRAY_SIZE(g_aesAeadPadding));
    }

    return HKS_SUCCESS;
}

//进行AESCBC加密数据的size检查
static int32_t CheckAesCbcCipherData(uint32_t cmdId, uint32_t padding,
    const struct HksBlob *inData, const struct HksBlob *outData)
{
    /*
     * encrypt: inSize greater than 0(has been checked), no-padding: inSize need to be integer multiple of 16
     *          outSize no less than inSize + (16 - inSize % 16) (in: plain; out: cipher)
     * decrypt: inSize greater than 0(has been checked) && inSize is integer multiple of 16
     *          outSize no less than inSize (in: cipher; out: plain)
     */
    switch (cmdId) {
        case HKS_CMD_ID_ENCRYPT: {
            uint32_t paddingSize = 0;
            if (padding == HKS_PADDING_NONE) {
                if (inData->size % HKS_AES_CBC_BLOCK_SIZE != 0) {
                    HKS_LOG_E("encrypt cbc no-padding, invalid inSize: %u", inData->size);
                    return HKS_ERROR_INVALID_ARGUMENT;
                }
            } else {
                paddingSize = HKS_AES_CBC_BLOCK_SIZE - inData->size % HKS_AES_CBC_BLOCK_SIZE;
                if (inData->size > (UINT32_MAX - paddingSize)) {
                    HKS_LOG_E("encrypt, invalid inData size: %u", inData->size);
                    return HKS_ERROR_INVALID_ARGUMENT;
                }
            }
            if (outData->size < (inData->size + paddingSize)) {
                HKS_LOG_E("encrypt, outData buffer too small size: %u, need: %u",
                    outData->size, inData->size + paddingSize);
                return HKS_ERROR_BUFFER_TOO_SMALL;
            }
            break;
        }
        case HKS_CMD_ID_DECRYPT:
            if ((inData->size % HKS_AES_CBC_BLOCK_SIZE) != 0) {
                HKS_LOG_E("decrypt, invalid inData size: %u", inData->size);
                return HKS_ERROR_INVALID_ARGUMENT;
            }
            if (outData->size < inData->size) {
                HKS_LOG_E("decrypt, outData buffer too small size: %u, inDataSize: %u", outData->size, inData->size);
                return HKS_ERROR_BUFFER_TOO_SMALL;
            }
            break;
        default:
            return HKS_ERROR_INVALID_ARGUMENT;
    }

    return HKS_SUCCESS;
}

//进行AES AEC加密数据的size检查
static int32_t CheckAesAeCipherData(uint32_t cmdId, const struct HksBlob *inData, const struct HksBlob *outData)
{
    /*
     * encrypt: inSize greater than 0(has been checked),
     *          outSize no less than inSize + 16(tagLen) (in: plain; out: cipher)
     * decrypt: inSize greater than 16(tagLen), outSize no less than inSize - 16(tagLen)
     * decryptFinal: inSize greater than 0(has been checked), outSize no less than inSize (in: cipher; out: plain)
     */
    switch (cmdId) {
        case HKS_CMD_ID_ENCRYPT:
            if (inData->size > (UINT32_MAX - HKS_AE_TAG_LEN)) {
                HKS_LOG_E("encrypt, invalid inSize: %u", inData->size);
                return HKS_ERROR_INVALID_ARGUMENT;
            }
            if (outData->size < (inData->size + HKS_AE_TAG_LEN)) {
                HKS_LOG_E("encrypt, out buffer too small size: %u, inSize: %u", outData->size, inData->size);
                return HKS_ERROR_BUFFER_TOO_SMALL;
            }
            break;
        case HKS_CMD_ID_DECRYPT:
            if ((inData->size < HKS_AE_TAG_LEN) || (outData->size < inData->size - HKS_AE_TAG_LEN)) {
                HKS_LOG_E("decryptfinal, out buffer too small size: %u, inSize: %u", outData->size, inData->size);
                return HKS_ERROR_BUFFER_TOO_SMALL;
            }
            break;
        default:
            return HKS_ERROR_INVALID_ARGUMENT;
    }

    return HKS_SUCCESS;
}

//根据模式的不同调用不同的函数进行AES数据检查
static int32_t CheckAesCipherData(uint32_t cmdId, const struct ParamsValues *inputParams,
    const struct HksBlob *inData, const struct HksBlob *outData)
{
    uint32_t mode = inputParams->mode.value;

    if (mode == HKS_MODE_CBC) {
        uint32_t padding = inputParams->padding.value;
        return CheckAesCbcCipherData(cmdId, padding, inData, outData);
    } else if ((mode == HKS_MODE_GCM) || (mode == HKS_MODE_CCM)) {
        return CheckAesAeCipherData(cmdId, inData, outData);
    }

    return HKS_ERROR_INVALID_MODE;
}

对各种信息的检查

包括:

  • Iv
  • addParam
  • Blob
  • nonceParam
    函数CheckCipherAeMaterial检查addParam和noneParam
    函数HksCheckGenKeyPurpose检查inputPurpose的唯一性和有效性(调用上一篇博客所将的两个检查函数)
//根据iv_tag从paramSet获取ivParam
static int32_t CheckCipherIvMaterial(const struct HksParamSet *paramSet)
{
    struct HksParam *ivParam = NULL;
    int32_t ret = HksGetParam(paramSet, HKS_TAG_IV, &ivParam);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("cipher get iv param failed!");
        return HKS_ERROR_CHECK_GET_IV_FAIL;
    }

    if ((ivParam->blob.size != HKS_AES_CBC_IV_LEN) || (ivParam->blob.data == NULL)) {
        HKS_LOG_E("cbc iv param invalid");
        return HKS_ERROR_INVALID_IV;
    }

    return ret;
}

//对add关联信息进行检查
static int32_t CheckCipherAeAadMaterial(uint32_t mode, const struct HksParamSet *paramSet)
{
    struct HksParam *aadParam = NULL;
    int32_t ret = HksGetParam(paramSet, HKS_TAG_ASSOCIATED_DATA, &aadParam);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("cipher get aad param failed!");
        return HKS_ERROR_CHECK_GET_AAD_FAIL;
    }
    //检查blob是否存在
    if (CheckBlob(&aadParam->blob) != HKS_SUCCESS) {
        return HKS_ERROR_INVALID_AAD;
    }

    /* gcmMode: aadSize greater than 0 (has been checked); ccmMode: aadSize no less than 4 */
    if (mode == HKS_MODE_CCM) {
        if (aadParam->blob.size < HKS_AES_CCM_AAD_LEN_MIN) {
            HKS_LOG_E("ccm invalid aad size, aad size = %u", aadParam->blob.size);
            return HKS_ERROR_INVALID_AAD;
        }
    }

    return HKS_SUCCESS;
}

//对AE暂时材料参数的检查
static int32_t CheckCipherAeNonceMaterial(uint32_t mode, const struct HksParamSet *paramSet)
{
    struct HksParam *nonceParam = NULL;
    int32_t ret = HksGetParam(paramSet, HKS_TAG_NONCE, &nonceParam);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("cipher get nonce param failed!");
        return HKS_ERROR_CHECK_GET_NONCE_FAIL;
    }

    if (CheckBlob(&nonceParam->blob) != HKS_SUCCESS) {
        return HKS_ERROR_INVALID_NONCE;
    }

    /* gcmMode: nonceSize no less than 12; ccmMode: nonceSize no less than 7, and no greater than 13 */
    if (mode == HKS_MODE_GCM) {
        if (nonceParam->blob.size < HKS_AES_GCM_NONCE_LEN_MIN) {
            HKS_LOG_E("gcm invalid nonce size, nonce size = %u", nonceParam->blob.size);
            return HKS_ERROR_INVALID_NONCE;
        }
    } else if (mode == HKS_MODE_CCM) {
        if ((nonceParam->blob.size < HKS_AES_CCM_NONCE_LEN_MIN) ||
            (nonceParam->blob.size > HKS_AES_CCM_NONCE_LEN_MAX)) {
            HKS_LOG_E("ccm invalid nonce size, nonce size = %u", nonceParam->blob.size);
            return HKS_ERROR_INVALID_NONCE;
        }
    }

    return HKS_SUCCESS;
}

//分别检查add和nonce的material
static int32_t CheckCipherAeMaterial(uint32_t mode, const struct HksParamSet *paramSet)
{
    int32_t ret = CheckCipherAeAadMaterial(mode, paramSet);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("check ae cipher aad failed!");
        return ret;
    }

    ret = CheckCipherAeNonceMaterial(mode, paramSet);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("check ae cipher nonce failed!");
        return ret;
    }

    return ret;
}
#endif

#ifndef _CUT_AUTHENTICATE_
//检查根密钥purpose两个方面:唯一性和有效性
int32_t HksCheckGenKeyPurpose(uint32_t alg, uint32_t inputPurpose)
{
    //首先对inputpurpose进行独一性检验
    int32_t ret = CheckPurposeUnique(inputPurpose);
    if (ret != HKS_SUCCESS) {
        HKS_LOG_E("gen key purpose not unique");
        return ret;
    }
    //根据alg进行inputPurpose的有效性检验
    return CheckPurposeValid(alg, inputPurpose);
}

其他的功能函数

  1. 根据加密模式和alg标志的不同检查并获取密钥size
    在这里插入图片描述
  2. 封装的上层函HksGetInputParmasByAlg
    通过alg初始化输入参数再从参数集合中获取输入参数
    在这里插入图片描述
  3. HksCheckFixedParams
    对于参数结构体中的五个部分进行检查
    keylen padding purpose digest mode
//检查混合加密算法的参数(五个params)
int32_t HksCheckFixedParams(uint32_t alg, enum CheckKeyType checkType, const struct ParamsValues *inputParams)
{
    struct ExpectParamsValues expectValues;
    //首先获取期望参数的值用于下面的value比较
    int32_t ret = GetExpectParams(alg, checkType, &expectValues);
    if (ret != HKS_SUCCESS) {
        return ret;
    }

    if (expectValues.keyLen.needCheck) {
        ret = HksCheckValue(inputParams->keyLen.value, expectValues.keyLen.values, expectValues.keyLen.valueCnt);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("check keyLen not expected, len = %u", inputParams->keyLen.value);
            return HKS_ERROR_INVALID_KEY_SIZE;
        }
    }

    if (expectValues.padding.needCheck) {
        ret = HksCheckValue(inputParams->padding.value, expectValues.padding.values, expectValues.padding.valueCnt);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("check  padding not expected, padding = %u", inputParams->padding.value);
            return HKS_ERROR_INVALID_PADDING;
        }
    }

    if (expectValues.purpose.needCheck) {
        ret = HksCheckValue(inputParams->purpose.value, expectValues.purpose.values, expectValues.purpose.valueCnt);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("check  purpose not expected, purpose = %u", inputParams->purpose.value);
            return HKS_ERROR_INVALID_PURPOSE;
        }
    }

    if (expectValues.digest.needCheck) {
        ret = HksCheckValue(inputParams->digest.value, expectValues.digest.values, expectValues.digest.valueCnt);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("check  digest not expected, digest = %u", inputParams->digest.value);
            return HKS_ERROR_INVALID_DIGEST;
        }
    }

    if (expectValues.mode.needCheck) {
        ret = HksCheckValue(inputParams->mode.value, expectValues.mode.values, expectValues.mode.valueCnt);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("check  mode not expected, mode = %u", inputParams->mode.value);
            return HKS_ERROR_INVALID_MODE;
        }
    }

    return ret;
}
  1. 两种加密算法RSA AES的数据检查封装函数
    在这里插入图片描述
    感谢阅读!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

国家一级假勤奋研究牲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值