/* * Copyright (C) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "crypto_signature.h" #include "sm2_ec_signature_data.h" #include "securec.h" #include #include #include "signature.h" #include "memory.h" #include "crypto_common.h" #include "blob.h" #include "object_base.h" #include "result.h" #include "native_common.h" struct OH_CryptoVerify { HcfObjectBase base; HcfResult (*init)(HcfVerify *self, HcfParamsSpec *params, HcfPubKey *publicKey); HcfResult (*update)(HcfVerify *self, HcfBlob *data); bool (*verify)(HcfVerify *self, HcfBlob *data, HcfBlob *signatureData); HcfResult (*recover)(HcfVerify *self, HcfBlob *signatureData, HcfBlob *rawSignatureData); const char *(*getAlgoName)(HcfVerify *self); HcfResult (*setVerifySpecInt)(HcfVerify *self, SignSpecItem item, int32_t saltLen); HcfResult (*getVerifySpecString)(HcfVerify *self, SignSpecItem item, char **returnString); HcfResult (*getVerifySpecInt)(HcfVerify *self, SignSpecItem item, int32_t *returnInt); HcfResult (*setVerifySpecUint8Array)(HcfVerify *self, SignSpecItem item, HcfBlob blob); }; struct OH_CryptoSign { HcfObjectBase base; HcfResult (*init)(HcfSign *self, HcfParamsSpec *params, HcfPriKey *privateKey); HcfResult (*update)(HcfSign *self, HcfBlob *data); HcfResult (*sign)(HcfSign *self, HcfBlob *data, HcfBlob *returnSignatureData); const char *(*getAlgoName)(HcfSign *self); HcfResult (*setSignSpecInt)(HcfSign *self, SignSpecItem item, int32_t saltLen); HcfResult (*getSignSpecString)(HcfSign *self, SignSpecItem item, char **returnString); HcfResult (*getSignSpecInt)(HcfSign *self, SignSpecItem item, int32_t *returnInt); HcfResult (*setSignSpecUint8Array)(HcfSign *self, SignSpecItem item, HcfBlob blob); }; OH_Crypto_ErrCode OH_CryptoVerify_Create(const char *algoName, OH_CryptoVerify **verify) { if (verify == NULL) { return CRYPTO_INVALID_PARAMS; } HcfResult ret = HcfVerifyCreate(algoName, (HcfVerify **)verify); return GetOhCryptoErrCode(ret); } OH_Crypto_ErrCode OH_CryptoVerify_Init(OH_CryptoVerify *ctx, OH_CryptoPubKey *pubKey) { if ((ctx == NULL) || (ctx->init == NULL) || (pubKey == NULL)) { return CRYPTO_INVALID_PARAMS; } HcfResult ret = ctx->init((HcfVerify *)ctx, NULL, (HcfPubKey *)pubKey); return GetOhCryptoErrCode(ret); } OH_Crypto_ErrCode OH_CryptoVerify_Update(OH_CryptoVerify *ctx, Crypto_DataBlob *in) { if ((ctx == NULL) || (ctx->update == NULL) || (in == NULL)) { return CRYPTO_INVALID_PARAMS; } HcfResult ret = ctx->update((HcfVerify *)ctx, (HcfBlob *)in); return GetOhCryptoErrCode(ret); } bool OH_CryptoVerify_Final(OH_CryptoVerify *ctx, Crypto_DataBlob *in, Crypto_DataBlob *signData) { if ((ctx == NULL) || (ctx->verify == NULL) || (signData == NULL)) { return false; } bool ret = ctx->verify((HcfVerify *)ctx, (HcfBlob *)in, (HcfBlob *)signData); if (ret != true) { return false; } return ret; } OH_Crypto_ErrCode OH_CryptoVerify_Recover(OH_CryptoVerify *ctx, Crypto_DataBlob *signData, Crypto_DataBlob *rawSignData) { if ((ctx == NULL) || (ctx->recover == NULL) || (signData == NULL) || (rawSignData == NULL)) { return CRYPTO_INVALID_PARAMS; } HcfResult ret = ctx->recover((HcfVerify *)ctx, (HcfBlob *)signData, (HcfBlob *)rawSignData); return GetOhCryptoErrCode(ret); } const char *OH_CryptoVerify_GetAlgoName(OH_CryptoVerify *ctx) { if ((ctx == NULL) || (ctx->getAlgoName == NULL)) { return NULL; } return ctx->getAlgoName((HcfVerify *)ctx); } OH_Crypto_ErrCode OH_CryptoVerify_SetParam(OH_CryptoVerify *ctx, CryptoSignature_ParamType type, Crypto_DataBlob *value) { if ((ctx == NULL) || (value == NULL)) { return CRYPTO_INVALID_PARAMS; } HcfResult ret = HCF_INVALID_PARAMS; switch (type) { case CRYPTO_PSS_SALT_LEN_INT: case CRYPTO_PSS_TRAILER_FIELD_INT: if ((value->data == NULL) || (value->len != sizeof(int32_t)) || (ctx->setVerifySpecInt == NULL)) { ret = HCF_INVALID_PARAMS; break; } ret = ctx->setVerifySpecInt((HcfVerify *)ctx, (SignSpecItem)type, *((int32_t *)value->data)); break; case CRYPTO_SM2_USER_ID_DATABLOB: case CRYPTO_PSS_MGF1_NAME_STR: case CRYPTO_PSS_MGF_NAME_STR: case CRYPTO_PSS_MD_NAME_STR: if (ctx->setVerifySpecUint8Array == NULL) { ret = HCF_INVALID_PARAMS; break; } ret = ctx->setVerifySpecUint8Array((HcfVerify *)ctx, (SignSpecItem)type, *((HcfBlob *)value)); break; default: return CRYPTO_INVALID_PARAMS; } return GetOhCryptoErrCode(ret); } OH_Crypto_ErrCode OH_CryptoVerify_GetParam(OH_CryptoVerify *ctx, CryptoSignature_ParamType type, Crypto_DataBlob *value) { if ((ctx == NULL) || (value == NULL)) { return CRYPTO_INVALID_PARAMS; } int32_t *returnInt = NULL; char *returnStr = NULL; HcfResult ret = HCF_INVALID_PARAMS; switch (type) { case CRYPTO_PSS_SALT_LEN_INT: case CRYPTO_PSS_TRAILER_FIELD_INT: case CRYPTO_SM2_USER_ID_DATABLOB: if (ctx->getVerifySpecInt == NULL) { ret = HCF_INVALID_PARAMS; break; } returnInt = (int32_t *)HcfMalloc(sizeof(int32_t), 0); if (returnInt == NULL) { return CRYPTO_MEMORY_ERROR; } ret = ctx->getVerifySpecInt((HcfVerify *)ctx, (SignSpecItem)type, returnInt); if (ret != HCF_SUCCESS) { HcfFree(returnInt); returnInt = NULL; break; } value->data = (uint8_t *)returnInt; value->len = sizeof(int32_t); break; case CRYPTO_PSS_MD_NAME_STR: case CRYPTO_PSS_MGF_NAME_STR: case CRYPTO_PSS_MGF1_NAME_STR: if (ctx->getVerifySpecString == NULL) { ret = HCF_INVALID_PARAMS; break; } ret = ctx->getVerifySpecString((HcfVerify *)ctx, (SignSpecItem)type, &returnStr); if (ret != HCF_SUCCESS) { break; } value->data = (uint8_t *)returnStr; value->len = strlen(returnStr); break; default: return CRYPTO_INVALID_PARAMS; } return GetOhCryptoErrCode(ret); } void OH_CryptoVerify_Destroy(OH_CryptoVerify *ctx) { if (ctx == NULL || ctx->base.destroy == NULL) { return; } ctx->base.destroy((HcfObjectBase *)ctx); } OH_Crypto_ErrCode OH_CryptoSign_Create(const char *algoName, OH_CryptoSign **sign) { if (sign == NULL) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfResult ret = HcfSignCreate(algoName, (HcfSign **)sign); return GetOhCryptoErrCodeNew(ret); } OH_Crypto_ErrCode OH_CryptoSign_Init(OH_CryptoSign *ctx, OH_CryptoPrivKey *privKey) { if ((ctx == NULL) || (ctx->init == NULL) || (privKey == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfResult ret = ctx->init((HcfSign *)ctx, NULL, (HcfPriKey *)privKey); return GetOhCryptoErrCodeNew(ret); } OH_Crypto_ErrCode OH_CryptoSign_Update(OH_CryptoSign *ctx, const Crypto_DataBlob *in) { if ((ctx == NULL) || (ctx->update == NULL) || (in == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfResult ret = ctx->update((HcfSign *)ctx, (HcfBlob *)in); return GetOhCryptoErrCodeNew(ret); } OH_Crypto_ErrCode OH_CryptoSign_Final(OH_CryptoSign *ctx, const Crypto_DataBlob *in, Crypto_DataBlob *out) { if ((ctx == NULL) || (ctx->sign == NULL) || (out == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfResult ret = ctx->sign((HcfSign *)ctx, (HcfBlob *)in, (HcfBlob *)out); return GetOhCryptoErrCodeNew(ret); } const char *OH_CryptoSign_GetAlgoName(OH_CryptoSign *ctx) { if ((ctx == NULL) || (ctx->getAlgoName == NULL)) { return NULL; } return ctx->getAlgoName((HcfSign *)ctx); } OH_Crypto_ErrCode OH_CryptoSign_SetParam(OH_CryptoSign *ctx, CryptoSignature_ParamType type, const Crypto_DataBlob *value) { if ((ctx == NULL) || (value == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfResult ret = HCF_INVALID_PARAMS; switch (type) { case CRYPTO_PSS_SALT_LEN_INT: case CRYPTO_PSS_TRAILER_FIELD_INT: if ((value->data == NULL) || (value->len != sizeof(int32_t)) || (ctx->setSignSpecInt == NULL)) { ret = HCF_INVALID_PARAMS; break; } ret = ctx->setSignSpecInt((HcfSign *)ctx, (SignSpecItem)type, *((int32_t *)value->data)); break; case CRYPTO_SM2_USER_ID_DATABLOB: case CRYPTO_PSS_MGF1_NAME_STR: case CRYPTO_PSS_MGF_NAME_STR: case CRYPTO_PSS_MD_NAME_STR: if (ctx->setSignSpecUint8Array == NULL) { ret = HCF_INVALID_PARAMS; break; } ret = ctx->setSignSpecUint8Array((HcfSign *)ctx, (SignSpecItem)type, *((HcfBlob *)value)); break; default: return CRYPTO_PARAMETER_CHECK_FAILED; } return GetOhCryptoErrCodeNew(ret); } OH_Crypto_ErrCode OH_CryptoSign_GetParam(OH_CryptoSign *ctx, CryptoSignature_ParamType type, Crypto_DataBlob *value) { if ((ctx == NULL) || (value == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } int32_t *returnInt = NULL; char *returnStr = NULL; HcfResult ret = HCF_INVALID_PARAMS; switch (type) { case CRYPTO_PSS_SALT_LEN_INT: case CRYPTO_PSS_TRAILER_FIELD_INT: case CRYPTO_SM2_USER_ID_DATABLOB: if (ctx->getSignSpecInt == NULL) { ret = HCF_INVALID_PARAMS; break; } returnInt = (int32_t *)HcfMalloc(sizeof(int32_t), 0); if (returnInt == NULL) { return CRYPTO_MEMORY_ERROR; } ret = ctx->getSignSpecInt((HcfSign *)ctx, (SignSpecItem)type, returnInt); if (ret != HCF_SUCCESS) { HcfFree(returnInt); returnInt = NULL; break; } value->data = (uint8_t *)returnInt; value->len = sizeof(int32_t); break; case CRYPTO_PSS_MD_NAME_STR: case CRYPTO_PSS_MGF_NAME_STR: case CRYPTO_PSS_MGF1_NAME_STR: if (ctx->getSignSpecString == NULL) { ret = HCF_INVALID_PARAMS; break; } ret = ctx->getSignSpecString((HcfSign *)ctx, (SignSpecItem)type, &returnStr); if (ret != HCF_SUCCESS) { break; } value->data = (uint8_t *)returnStr; value->len = strlen(returnStr); break; default: return CRYPTO_PARAMETER_CHECK_FAILED; } return GetOhCryptoErrCodeNew(ret); } void OH_CryptoSign_Destroy(OH_CryptoSign *ctx) { if (ctx == NULL || ctx->base.destroy == NULL) { return; } ctx->base.destroy((HcfObjectBase *)ctx); } struct OH_CryptoEccSignatureSpec { HcfBigInteger r; HcfBigInteger s; }; OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_Create(Crypto_DataBlob *eccSignature, OH_CryptoEccSignatureSpec **spec) { if (spec == NULL) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfResult ret = HCF_INVALID_PARAMS; if (eccSignature == NULL) { *spec = (OH_CryptoEccSignatureSpec *)HcfMalloc(sizeof(OH_CryptoEccSignatureSpec), 0); if (*spec == NULL) { return CRYPTO_MEMORY_ERROR; } return GetOhCryptoErrCodeNew(HCF_SUCCESS); } ret = HcfGenEcSignatureSpecByData((HcfBlob *)eccSignature, (Sm2EcSignatureDataSpec **)spec); return GetOhCryptoErrCodeNew(ret); } OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_GetRAndS(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *r, Crypto_DataBlob *s) { if ((spec == NULL) || (r == NULL) || (s == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } if ((spec->r.data == NULL) || (spec->s.data == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } // Allocate memory for r->data r->data = (uint8_t *)HcfMalloc(spec->r.len, 0); if (r->data == NULL) { return CRYPTO_MEMORY_ERROR; } // Copy data for r if (memcpy_s(r->data, spec->r.len, spec->r.data, spec->r.len) != 0) { HcfFree(r->data); r->data = NULL; // Ensure pointer is null after freeing return CRYPTO_MEMORY_ERROR; } r->len = (size_t)spec->r.len; // Allocate memory for s->data s->data = (uint8_t *)HcfMalloc(spec->s.len, 0); if (s->data == NULL) { HcfFree(r->data); r->data = NULL; // Ensure pointer is null after freeing return CRYPTO_MEMORY_ERROR; } // Copy data for s if (memcpy_s(s->data, spec->s.len, spec->s.data, spec->s.len) != 0) { HcfFree(r->data); r->data = NULL; // Ensure pointer is null after freeing HcfFree(s->data); s->data = NULL; // Ensure pointer is null after freeing return CRYPTO_MEMORY_ERROR; } s->len = (size_t)spec->s.len; return GetOhCryptoErrCodeNew(HCF_SUCCESS); } OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_SetRAndS(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *r, Crypto_DataBlob *s) { if ((spec == NULL) || (r == NULL) || (s == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } if (r->data == NULL || s->data == NULL) { return CRYPTO_PARAMETER_CHECK_FAILED; } // Allocate memory for r->data spec->r.data = (unsigned char *)HcfMalloc(r->len, 0); if (spec->r.data == NULL) { return CRYPTO_MEMORY_ERROR; } if (memcpy_s(spec->r.data, r->len, r->data, r->len) != 0) { HcfFree(spec->r.data); spec->r.data = NULL; return CRYPTO_MEMORY_ERROR; } spec->r.len = (uint32_t)r->len; // Allocate memory for s->data spec->s.data = (unsigned char *)HcfMalloc(s->len, 0); if (spec->s.data == NULL) { HcfFree(spec->r.data); spec->r.data = NULL; return CRYPTO_MEMORY_ERROR; } if (memcpy_s(spec->s.data, s->len, s->data, s->len) != 0) { HcfFree(spec->r.data); HcfFree(spec->s.data); spec->r.data = NULL; spec->s.data = NULL; return CRYPTO_MEMORY_ERROR; } spec->s.len = (uint32_t)s->len; return GetOhCryptoErrCodeNew(HCF_SUCCESS); } OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_Encode(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *out) { if ((spec == NULL) || (out == NULL)) { return CRYPTO_PARAMETER_CHECK_FAILED; } HcfBlob *outBlob = (HcfBlob *)HcfMalloc(sizeof(HcfBlob), 0); if (outBlob == NULL) { return CRYPTO_MEMORY_ERROR; } HcfResult ret = HcfGenEcSignatureDataBySpec((Sm2EcSignatureDataSpec *)spec, outBlob); if (ret != HCF_SUCCESS) { HcfFree(outBlob); outBlob = NULL; return GetOhCryptoErrCode(ret); } out->data = outBlob->data; out->len = outBlob->len; HcfFree(outBlob); outBlob = NULL; return GetOhCryptoErrCodeNew(HCF_SUCCESS); } void OH_CryptoEccSignatureSpec_Destroy(OH_CryptoEccSignatureSpec *spec) { if (spec == NULL) { return; } if (spec->r.data != NULL) { HcfFree(spec->r.data); spec->r.data = NULL; } if (spec->s.data != NULL) { HcfFree(spec->s.data); spec->s.data = NULL; } HcfFree(spec); }