1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *    http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifdef HKS_CONFIG_FILE
17#include HKS_CONFIG_FILE
18#else
19#include "hks_config.h"
20#endif
21
22#include "hks_client_service_adapter.h"
23
24#include <openssl/bn.h>
25#include <openssl/core_names.h>
26#include <openssl/dh.h>
27#include <openssl/dsa.h>
28#include <openssl/ec.h>
29#include <openssl/err.h>
30#include <openssl/evp.h>
31#include <openssl/obj_mac.h>
32#include <openssl/ossl_typ.h>
33#include <openssl/param_build.h>
34#include "openssl/params.h"
35#include <openssl/rsa.h>
36#include <openssl/x509.h>
37#include <stddef.h>
38#include <stdint.h>
39
40#include "hks_crypto_hal.h"
41#include "hks_log.h"
42#include "hks_mem.h"
43#include "hks_openssl_engine.h"
44#include "hks_template.h"
45#include "hks_type.h"
46#include "securec.h"
47
48#if defined(HKS_SUPPORT_DSA_C)
49typedef const BIGNUM* (*GetDsaInfoFunc)(const DSA *d);
50#endif
51
52#if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C) || defined(HKS_SUPPORT_DSA_C) || \
53    defined(HKS_SUPPORT_DH_C) || defined(HKS_SUPPORT_SM2_C)
54static int32_t EvpKeyToX509Format(EVP_PKEY *pkey, struct HksBlob *x509Key)
55{
56    int32_t length = i2d_PUBKEY(pkey, NULL);
57    if (length <= 0 || length > MAX_OUT_BLOB_SIZE) {
58        HKS_LOG_E("i2d_PUBKEY error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
59        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
60    }
61
62    uint32_t keyLength = (uint32_t)length;
63    uint8_t *key = (uint8_t *)HksMalloc(keyLength);
64    HKS_IF_NULL_LOGE_RETURN(key, HKS_ERROR_MALLOC_FAIL, "malloc key fail")
65
66    /* tmp will be modified in i2d_PUBKEY */
67    uint8_t *tmp = key;
68    if ((uint32_t)i2d_PUBKEY(pkey, &tmp) != keyLength) {
69        HKS_LOG_E("i2d_PUBKEY error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
70        HKS_FREE(key);
71        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
72    }
73
74    x509Key->size = keyLength;
75    x509Key->data = key;
76    return HKS_SUCCESS;
77}
78
79#if defined(HKS_SUPPORT_RSA_C) && defined(HKS_SUPPORT_RSA_GET_PUBLIC_KEY)
80static int32_t RsaToX509PublicKey(const struct HksBlob *mod, const struct HksBlob *e, struct HksBlob *x509Key)
81{
82    RSA *rsa = NULL;
83    BIGNUM *rsaN = NULL;
84    BIGNUM *rsaE = NULL;
85    EVP_PKEY *pkey = NULL;
86    int32_t result;
87
88    do {
89        result = HKS_ERROR_CRYPTO_ENGINE_ERROR;
90        rsa = RSA_new();
91        HKS_IF_NULL_LOGE_BREAK(rsa, "rsa is null")
92        rsaN = BN_bin2bn(mod->data, mod->size, NULL);
93        rsaE = BN_bin2bn(e->data, e->size, NULL);
94        if (rsaN == NULL || rsaE == NULL) {
95            HKS_LOG_E("BN_bin2bn error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
96            break;
97        }
98        if (RSA_set0_key(rsa, rsaN, rsaE, NULL) == 0) {
99            HKS_LOG_E("RSA_set0_key error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
100            break;
101        }
102        rsaN = NULL;
103        rsaE = NULL;
104        pkey = EVP_PKEY_new();
105        HKS_IF_NULL_LOGE_BREAK(pkey, "pkey is null")
106        if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
107            HKS_LOG_E("EVP_PKEY_set1_RSA error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
108            break;
109        }
110        result = EvpKeyToX509Format(pkey, x509Key);
111    } while (0);
112
113    SELF_FREE_PTR(rsa, RSA_free)
114    SELF_FREE_PTR(rsaN, BN_free)
115    SELF_FREE_PTR(rsaE, BN_free)
116    SELF_FREE_PTR(pkey, EVP_PKEY_free)
117    return result;
118}
119#endif
120
121#if defined(HKS_SUPPORT_ECC_C) && defined(HKS_SUPPORT_ECC_GET_PUBLIC_KEY)
122static int32_t GetEccNid(uint32_t keySize, int32_t *nid)
123{
124    int32_t nids[][2] = {
125        /* 2 is size */
126        { 224, NID_secp224r1 },
127        { 256, NID_X9_62_prime256v1 },
128        { 384, NID_secp384r1 },
129        { 521, NID_secp521r1 },
130    };
131
132    uint32_t nidCount = sizeof(nids) / sizeof(nids[0]);
133
134    for (uint32_t i = 0; i < nidCount; i++) {
135        if (keySize == (uint32_t)nids[i][0]) {
136            *nid = nids[i][1];
137            return HKS_SUCCESS;
138        }
139    }
140
141    HKS_LOG_E("not found nid!");
142    return HKS_ERROR_INVALID_ARGUMENT;
143}
144
145static int32_t EccToX509PublicKey(
146    const uint32_t alg, uint32_t keySize, const struct HksBlob *x, const struct HksBlob *y, struct HksBlob *x509Key)
147{
148    int32_t nid;
149    if (alg == HKS_ALG_SM2) {
150        nid = NID_sm2;
151    } else {
152        HKS_IF_NOT_SUCC_LOGE_RETURN(GetEccNid(keySize, &nid), HKS_ERROR_INVALID_ARGUMENT, "GetNidFromKeySize fail")
153    }
154
155    EC_KEY *ecKey = NULL;
156    BIGNUM *ecX = NULL;
157    BIGNUM *ecY = NULL;
158    EVP_PKEY *pkey = NULL;
159    int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
160    do {
161        ecKey = EC_KEY_new_by_curve_name(nid);
162        HKS_IF_NULL_LOGE_BREAK(ecKey,
163            "EC_KEY_new_by_curve_name error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
164
165        ecX = BN_bin2bn(x->data, x->size, NULL);
166        ecY = BN_bin2bn(y->data, y->size, NULL);
167        if (ecX == NULL || ecY == NULL) {
168            HKS_LOG_E("x y point is null");
169            break;
170        }
171
172        if (EC_KEY_set_public_key_affine_coordinates(ecKey, ecX, ecY) == 0) {
173            HKS_LOG_E("EC_KEY_set_public_key_affine_coordinates error %" LOG_PUBLIC "s",
174                ERR_reason_error_string(ERR_get_error()));
175            break;
176        }
177
178        EC_KEY_set_conv_form(ecKey, POINT_CONVERSION_UNCOMPRESSED);
179        pkey = EVP_PKEY_new();
180        HKS_IF_NULL_LOGE_BREAK(pkey, "pkey is null")
181
182        if (EVP_PKEY_set1_EC_KEY(pkey, ecKey) == 0) {
183            HKS_LOG_E("EVP_PKEY_set1_EC_KEY error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
184            break;
185        }
186
187        ret = EvpKeyToX509Format(pkey, x509Key);
188    } while (0);
189
190    SELF_FREE_PTR(ecKey, EC_KEY_free)
191    SELF_FREE_PTR(ecX, BN_free)
192    SELF_FREE_PTR(ecY, BN_free)
193    SELF_FREE_PTR(pkey, EVP_PKEY_free)
194    return ret;
195}
196#endif
197
198#if defined(HKS_SUPPORT_SM2_C) && defined(HKS_SUPPORT_SM2_GET_PUBLIC_KEY)
199static int32_t Sm2ToX509PublicKey(
200    const uint32_t alg, uint32_t keySize, const struct HksBlob *x, const struct HksBlob *y, struct HksBlob *x509Key)
201{
202    return EccToX509PublicKey(alg, keySize, x, y, x509Key);
203}
204#endif
205
206#if defined(HKS_SUPPORT_DSA_C) && defined(HKS_SUPPORT_DSA_GET_PUBLIC_KEY)
207static int32_t GetDsaPubKeyParam(
208    const struct HksBlob *publicKey, struct HksBlob *y, struct HksBlob *p, struct HksBlob *q, struct HksBlob *g)
209{
210    if (publicKey->size < sizeof(struct KeyMaterialDsa)) {
211        HKS_LOG_E("Invaild dsa key material size!");
212        return HKS_ERROR_INVALID_ARGUMENT;
213    }
214
215    struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)publicKey->data;
216    uint32_t keyMaterialSize = sizeof(struct KeyMaterialDsa) + keyMaterial->xSize + keyMaterial->ySize +
217        keyMaterial->pSize + keyMaterial->qSize + keyMaterial->gSize;
218    if (publicKey->size < keyMaterialSize) {
219        HKS_LOG_E("translate to x509 public key invalid size");
220        return HKS_ERROR_INVALID_ARGUMENT;
221    }
222    uint32_t offset = sizeof(struct KeyMaterialDsa) + keyMaterial->xSize;
223    y->size = keyMaterial->ySize;
224    y->data = publicKey->data + offset;
225    offset += keyMaterial->ySize;
226    p->size = keyMaterial->pSize;
227    p->data = publicKey->data + offset;
228    offset += keyMaterial->pSize;
229    q->size = keyMaterial->qSize;
230    q->data = publicKey->data + offset;
231    offset += keyMaterial->qSize;
232    g->size = keyMaterial->gSize;
233    g->data = publicKey->data + offset;
234    return HKS_SUCCESS;
235}
236
237static int32_t DsaToX509PublicKey(const struct HksBlob *y, const struct HksBlob *p, const struct HksBlob *q,
238    const struct HksBlob *g, struct HksBlob *x509Key)
239{
240    int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
241    DSA *dsa = NULL;
242    BIGNUM *dsaY = BN_bin2bn(y->data, y->size, NULL);
243    BIGNUM *dsaP = BN_bin2bn(p->data, p->size, NULL);
244    BIGNUM *dsaQ = BN_bin2bn(q->data, q->size, NULL);
245    BIGNUM *dsaG = BN_bin2bn(g->data, g->size, NULL);
246    EVP_PKEY *pkey = NULL;
247    do {
248        dsa = DSA_new();
249        HKS_IF_NULL_LOGE_BREAK(dsa, "DSA_new error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
250
251        if (dsaY == NULL || dsaP == NULL || dsaQ == NULL || dsaG == NULL) {
252            HKS_LOG_E("DSA parameter is null.");
253            break;
254        }
255
256        if (DSA_set0_key(dsa, dsaY, NULL) != 1) {
257            HKS_LOG_E("DSA_set0_key error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
258            break;
259        }
260        dsaY = NULL;
261        if (DSA_set0_pqg(dsa, dsaP, dsaQ, dsaG) != 1) {
262            HKS_LOG_E("DSA_set0_pqg error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
263            break;
264        }
265        dsaP = NULL;
266        dsaQ = NULL;
267        dsaG = NULL;
268
269        pkey = EVP_PKEY_new();
270        HKS_IF_NULL_LOGE_BREAK(pkey, "pkey is null")
271
272        if (EVP_PKEY_set1_DSA(pkey, dsa) == 0) {
273            HKS_LOG_E("EVP_PKEY_set1_DSA error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
274            break;
275        }
276
277        ret = EvpKeyToX509Format(pkey, x509Key);
278    } while (0);
279
280    SELF_FREE_PTR(dsa, DSA_free)
281    SELF_FREE_PTR(dsaY, BN_free)
282    SELF_FREE_PTR(dsaP, BN_free)
283    SELF_FREE_PTR(dsaQ, BN_free)
284    SELF_FREE_PTR(dsaG, BN_free)
285    SELF_FREE_PTR(pkey, EVP_PKEY_free)
286    return ret;
287}
288
289static int32_t DsaPublicKeyToX509(const struct HksBlob *publicKey, struct HksBlob *x509Key)
290{
291    struct HksBlob y = {0};
292    struct HksBlob p = {0};
293    struct HksBlob q = {0};
294    struct HksBlob g = {0};
295    int32_t ret = GetDsaPubKeyParam(publicKey, &y, &p, &q, &g);
296    HKS_IF_NOT_SUCC_RETURN(ret, ret)
297
298    return DsaToX509PublicKey(&y, &p, &q, &g, x509Key);
299}
300
301#endif
302
303#if defined(HKS_SUPPORT_DH_C) && defined(HKS_SUPPORT_DH_GET_PUBLIC_KEY)
304static int32_t GetDhNid(uint32_t keySize, int32_t *nid)
305{
306    switch (keySize) {
307        case HKS_DH_KEY_SIZE_2048:
308            *nid = NID_ffdhe2048;
309            return HKS_SUCCESS;
310        case HKS_DH_KEY_SIZE_3072:
311            *nid = NID_ffdhe3072;
312            return HKS_SUCCESS;
313        case HKS_DH_KEY_SIZE_4096:
314            *nid = NID_ffdhe4096;
315            return HKS_SUCCESS;
316        default:
317            return HKS_ERROR_INVALID_ARGUMENT;
318    }
319}
320
321static int32_t DhToX509PublicKey(
322    uint32_t keySize, const struct HksBlob *pubKey, const struct HksBlob *privKey, struct HksBlob *x509Key)
323{
324    int32_t nid;
325    int32_t ret = GetDhNid(keySize, &nid);
326    HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "GetNidFromKeySize fail")
327
328    BIGNUM *pub = NULL;
329    DH *dh = NULL;
330    EVP_PKEY *pkey = NULL;
331    do {
332        dh = DH_new_by_nid(nid);
333        HKS_IF_NULL_LOGE_BREAK(dh, "DH_new_by_nid error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
334
335        pub = BN_bin2bn(pubKey->data, pubKey->size, NULL);
336        HKS_IF_NULL_LOGE_BREAK(pub, "BN_bin2bn error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
337
338        if (DH_set0_key(dh, pub, NULL) != 1) {
339            HKS_LOG_E("DH_set0_key error:%" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
340            break;
341        }
342        pub = NULL;
343
344        pkey = EVP_PKEY_new();
345        HKS_IF_NULL_LOGE_BREAK(pkey, "pkey is null")
346
347        if (EVP_PKEY_set1_DH(pkey, dh) == 0) {
348            HKS_LOG_E("EVP_PKEY_set1_DH error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
349            break;
350        }
351
352        ret = EvpKeyToX509Format(pkey, x509Key);
353    } while (0);
354
355    SELF_FREE_PTR(dh, DH_free)
356    SELF_FREE_PTR(pub, BN_free)
357    SELF_FREE_PTR(pkey, EVP_PKEY_free)
358    return ret;
359}
360#endif
361#endif
362
363#if defined(HKS_SUPPORT_X25519_C) || defined(HKS_SUPPORT_ED25519_C)
364static int32_t Curve25519ToX509PublicKey(const struct HksBlob *publicKey, struct HksBlob *x509Key)
365{
366    if (publicKey->size != HKS_KEY_BYTES(HKS_CURVE25519_KEY_SIZE_256)) {
367        HKS_LOG_E("Invalid public key size! key size = 0x%" LOG_PUBLIC "X", publicKey->size);
368        return HKS_ERROR_INVALID_ARGUMENT;
369    }
370
371    x509Key->data = (uint8_t *)HksMalloc(publicKey->size);
372    HKS_IF_NULL_LOGE_RETURN(x509Key->data, HKS_ERROR_MALLOC_FAIL,
373        "X25519/Ed25519 to x509 public key malloc x509 key data failed!")
374
375    (void)memcpy_s(x509Key->data, publicKey->size, publicKey->data, publicKey->size);
376    x509Key->size = publicKey->size;
377
378    return HKS_SUCCESS;
379}
380#endif
381
382static int32_t TranslateToX509PublicKeySwitchAlg(const struct HksPubKeyInfo *publicKeyInfo,
383    const struct HksBlob *material1, const struct HksBlob *material2, const struct HksBlob *publicKey,
384    struct HksBlob *x509Key)
385{
386    switch (publicKeyInfo->keyAlg) {
387#if defined(HKS_SUPPORT_RSA_C) && defined(HKS_SUPPORT_RSA_GET_PUBLIC_KEY)
388        case HKS_ALG_RSA:
389            return RsaToX509PublicKey(material1, material2, x509Key);
390#endif
391#if defined(HKS_SUPPORT_ECC_C) && defined(HKS_SUPPORT_ECC_GET_PUBLIC_KEY)
392        case HKS_ALG_ECC:
393            return EccToX509PublicKey(publicKeyInfo->keyAlg, publicKeyInfo->keySize, material1, material2, x509Key);
394#endif
395#if defined(HKS_SUPPORT_SM2_C) && defined(HKS_SUPPORT_SM2_GET_PUBLIC_KEY)
396        case HKS_ALG_SM2:
397            return Sm2ToX509PublicKey(publicKeyInfo->keyAlg, publicKeyInfo->keySize, material1, material2, x509Key);
398#endif
399#if defined(HKS_SUPPORT_DSA_C) && defined(HKS_SUPPORT_DSA_GET_PUBLIC_KEY)
400        case HKS_ALG_DSA:
401            return DsaPublicKeyToX509(publicKey, x509Key);
402#endif
403#if defined(HKS_SUPPORT_X25519_C) || defined(HKS_SUPPORT_ED25519_C)
404        case HKS_ALG_X25519:
405        case HKS_ALG_ED25519:
406            return Curve25519ToX509PublicKey(material1, x509Key);
407#endif
408#if defined(HKS_SUPPORT_DH_C) && defined(HKS_SUPPORT_DH_GET_PUBLIC_KEY)
409        case HKS_ALG_DH:
410            return DhToX509PublicKey(publicKeyInfo->keySize, material1, NULL, x509Key);
411#endif
412        default:
413            HKS_LOG_E("Unsupport alg type! type = 0x%" LOG_PUBLIC "X", publicKeyInfo->keyAlg);
414            return HKS_ERROR_INVALID_ARGUMENT;
415    }
416}
417
418int32_t TranslateToX509PublicKey(const struct HksBlob *publicKey, struct HksBlob *x509Key)
419{
420    if ((publicKey == NULL) || (publicKey->data == NULL) || (publicKey->size == 0) || (x509Key == NULL)) {
421        HKS_LOG_E("translate to x509 public key invalid args");
422        return HKS_ERROR_INVALID_ARGUMENT;
423    }
424
425    if (publicKey->size < sizeof(struct HksPubKeyInfo)) {
426        HKS_LOG_E("translate to x509 public key invalid publicKey size");
427        return HKS_ERROR_INVALID_ARGUMENT;
428    }
429
430    struct HksPubKeyInfo *publicKeyInfo = (struct HksPubKeyInfo *)publicKey->data;
431    uint32_t offset = sizeof(struct HksPubKeyInfo);
432    if ((publicKey->size - offset) < publicKeyInfo->nOrXSize) {
433        HKS_LOG_E("translate to x509 public key invalid nOrXSize size");
434        return HKS_ERROR_INVALID_ARGUMENT;
435    }
436
437    struct HksBlob material1 = { publicKeyInfo->nOrXSize, publicKey->data + offset };
438    offset += publicKeyInfo->nOrXSize;
439    if ((publicKey->size - offset) < publicKeyInfo->eOrYSize) {
440        HKS_LOG_E("translate to x509 public key invalid eOrYSize size");
441        return HKS_ERROR_INVALID_ARGUMENT;
442    }
443
444    struct HksBlob material2 = { publicKeyInfo->eOrYSize, publicKey->data + offset };
445    return TranslateToX509PublicKeySwitchAlg(publicKeyInfo, &material1, &material2, publicKey, x509Key);
446}
447
448#if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C) || defined(HKS_SUPPORT_DSA_C) || \
449    defined(HKS_SUPPORT_DH_C)
450#ifdef HKS_SUPPORT_RSA_C
451static int32_t X509PublicKeyToRsa(EVP_PKEY *pkey, struct HksBlob *rsaPublicKey)
452{
453    const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
454    HKS_IF_NULL_LOGE_RETURN(rsa, HKS_ERROR_NULL_POINTER,
455        "EVP_PKEY_get1_RSA error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
456
457    int nSize = BN_num_bytes(RSA_get0_n(rsa));
458    int eSize = BN_num_bytes(RSA_get0_e(rsa));
459    if (nSize <= 0 || eSize <= 0) {
460        HKS_LOG_E("X509PublicKeyToRsa BN_num_bytes failed");
461        return HKS_ERROR_INTERNAL_ERROR;
462    }
463
464    /* n and e in RSA algorithm is small, will never overflow. */
465    uint32_t totalSize = (uint32_t)nSize + (uint32_t)eSize + sizeof(struct HksPubKeyInfo);
466    uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
467    HKS_IF_NULL_LOGE_RETURN(keyBuffer, HKS_ERROR_MALLOC_FAIL, "X509PublicKeyToRsa keyBuffer failed")
468
469    struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)keyBuffer;
470    pubKeyInfo->keyAlg = HKS_ALG_RSA;
471    pubKeyInfo->keySize = ((uint32_t)RSA_size(rsa)) * HKS_BITS_PER_BYTE;
472    pubKeyInfo->nOrXSize = (uint32_t)nSize;
473    pubKeyInfo->eOrYSize = (uint32_t)eSize;
474    pubKeyInfo->placeHolder = 0;
475    if (BN_bn2bin(RSA_get0_n(rsa), keyBuffer + sizeof(struct HksPubKeyInfo)) == 0 ||
476        BN_bn2bin(RSA_get0_e(rsa), keyBuffer + sizeof(struct HksPubKeyInfo) + (uint32_t)nSize) == 0) {
477        HKS_LOG_E("BN_bn2bin error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
478        HKS_FREE(keyBuffer);
479        return HKS_ERROR_INTERNAL_ERROR;
480    }
481
482    rsaPublicKey->data = keyBuffer;
483    rsaPublicKey->size = totalSize;
484    return HKS_SUCCESS;
485}
486#endif
487
488#ifdef HKS_SUPPORT_ECC_C
489static int32_t EcKeyToPublicKey(const uint32_t alg, const EC_KEY *ecKey, struct HksBlob *eccPublicKey)
490{
491    BIGNUM *x = BN_new();
492    BIGNUM *y = BN_new();
493    int32_t ret;
494    do {
495        ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
496        if (x == NULL || y == NULL) {
497            HKS_LOG_E("X509PublicKeyToEcc BN_new failed");
498            break;
499        }
500
501        if (EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ecKey), EC_KEY_get0_public_key(ecKey), x, y, NULL) ==
502            0) {
503            HKS_LOG_E("EC_POINT_get_affine_coordinates_GFp error %" LOG_PUBLIC "s",
504                ERR_reason_error_string(ERR_get_error()));
505            break;
506        }
507
508        uint32_t keyLen = (uint32_t)EC_GROUP_order_bits(EC_KEY_get0_group(ecKey));
509        uint32_t xSize = HKS_KEY_BYTES(keyLen);
510        uint32_t ySize = HKS_KEY_BYTES(keyLen);
511
512        if ((keyLen == 0) || (keyLen > HKS_ECC_KEY_SIZE_521)) {
513            HKS_LOG_E("invalid ecc key length");
514            break;
515        }
516
517        uint32_t totalSize = xSize + ySize + sizeof(struct HksPubKeyInfo);
518        uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
519        HKS_IF_NULL_LOGE_BREAK(keyBuffer, "X509PublicKeyToRsa keyBuffer failed")
520
521        struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)keyBuffer;
522        pubKeyInfo->keyAlg = alg;
523        pubKeyInfo->keySize = keyLen;
524        pubKeyInfo->nOrXSize = xSize;
525        pubKeyInfo->eOrYSize = ySize;
526        pubKeyInfo->placeHolder = 0;
527        if (BN_bn2binpad(x, keyBuffer + sizeof(struct HksPubKeyInfo), xSize) == 0 ||
528            BN_bn2binpad(y, keyBuffer + sizeof(struct HksPubKeyInfo) + xSize, ySize) == 0) {
529            HKS_LOG_E("BN_bn2binpad error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
530            HKS_FREE(keyBuffer);
531            break;
532        }
533
534        ret = HKS_SUCCESS;
535        eccPublicKey->data = keyBuffer;
536        eccPublicKey->size = totalSize;
537    } while (0);
538
539    SELF_FREE_PTR(x, BN_free)
540    SELF_FREE_PTR(y, BN_free)
541    return ret;
542}
543
544static int32_t X509PublicKeyToEcc(const uint32_t alg, EVP_PKEY *pkey, struct HksBlob *eccPublicKey)
545{
546    const EC_KEY *ecKey = EVP_PKEY_get0_EC_KEY(pkey);
547    HKS_IF_NULL_LOGE_RETURN(ecKey, HKS_ERROR_NULL_POINTER,
548        "EVP_PKEY_get1_EC_KEY error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
549
550    return EcKeyToPublicKey(alg, ecKey, eccPublicKey);
551}
552#endif
553
554#ifdef HKS_SUPPORT_SM2_C
555static int32_t EvpPkeyToHksPubKeyInfo(
556    const uint32_t alg, uint32_t keyLen, const EVP_PKEY *pkey, struct HksBlob *sm2PublicKey)
557{
558    struct HksBlob pubXBlob = { 0, NULL };
559    struct HksBlob pubYBlob = { 0, NULL };
560    int pubXRet = GetBnBinpadFromPkey(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &pubXBlob);
561    int pubYRet = GetBnBinpadFromPkey(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &pubYBlob);
562    int ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
563    do {
564        if (pubXRet != HKS_SUCCESS || pubYRet != HKS_SUCCESS) {
565            break;
566        }
567        // NOTICE! x size and y size are smaller than or equal to HKS_KEY_BYTES(keyLen)
568        // e.g. assuming that HKS_KEY_BYTES(keyLen) is 32, x size might be 32, 31, 30, etc.
569        uint32_t rawInfoLen = sizeof(struct HksPubKeyInfo) + pubXBlob.size + pubYBlob.size;
570        uint8_t *rawInfo = (uint8_t *)HksMalloc(rawInfoLen);
571        if (!rawInfo) {
572            HKS_LOG_E("HksMalloc rawInfo NULL");
573            ret = HKS_ERROR_INSUFFICIENT_MEMORY;
574            break;
575        }
576        struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)rawInfo;
577        pubKeyInfo->keyAlg = (enum HksKeyAlg)alg;
578        pubKeyInfo->keySize = keyLen;
579        pubKeyInfo->nOrXSize = pubXBlob.size;
580        pubKeyInfo->eOrYSize = pubYBlob.size;
581        pubKeyInfo->placeHolder = 0;
582        uint32_t offset = sizeof(struct HksPubKeyInfo);
583        pubXRet = memcpy_s(rawInfo + offset, pubXBlob.size, pubXBlob.data, pubXBlob.size);
584        offset += pubKeyInfo->nOrXSize;
585        pubYRet = memcpy_s(rawInfo + offset, pubYBlob.size, pubYBlob.data, pubYBlob.size);
586        if (pubXRet != EOK || pubYRet != EOK) {
587            HKS_LOG_E("memcpy_s failed");
588            HKS_FREE(rawInfo);
589            ret = HKS_ERROR_BAD_STATE;
590            break;
591        }
592        sm2PublicKey->data = rawInfo;
593        sm2PublicKey->size = rawInfoLen;
594        ret = HKS_SUCCESS;
595    } while (false);
596    HKS_FREE(pubXBlob.data);
597    HKS_FREE(pubYBlob.data);
598    return ret;
599}
600
601static int32_t X509PublicKeyToSm2(const uint32_t alg, EVP_PKEY *pkey, struct HksBlob *sm2PublicKey)
602{
603    HKS_LOG_I("into X509PublicKeyToSm2");
604    int keyLen = EVP_PKEY_get_bits(pkey);
605    if (keyLen <= 0) {
606        HKS_LOG_E("EVP_PKEY_get_bits failed keyLen = %" LOG_PUBLIC "d", keyLen);
607        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
608    }
609    if (keyLen != HKS_SM2_KEY_SIZE_256) {
610        HKS_LOG_E("not supported sm2 keyLen %" LOG_PUBLIC "d", keyLen);
611        return HKS_ERROR_NOT_SUPPORTED;
612    }
613    int ret = EvpPkeyToHksPubKeyInfo(alg, (uint32_t)keyLen, pkey, sm2PublicKey);
614    if (ret != HKS_SUCCESS) {
615        HKS_LOG_E("EvpPkeyToHksPubKeyInfo failed ret = %" LOG_PUBLIC "d", ret);
616    }
617    return ret;
618}
619#endif
620
621#ifdef HKS_SUPPORT_DSA_C
622
623static int32_t GetDsaKeyInfo(const DSA *dsa, const BIGNUM **info, uint32_t *infoSize, GetDsaInfoFunc func)
624{
625    *info = func(dsa);
626    HKS_IF_NULL_RETURN(*info, HKS_ERROR_NULL_POINTER)
627
628    int size = BN_num_bytes(*info);
629    if (size <= 0) {
630        return HKS_ERROR_INVALID_ARGUMENT;
631    }
632
633    *infoSize = (uint32_t)size;
634    return HKS_SUCCESS;
635}
636
637static int32_t X509PublicKeyToDsa(EVP_PKEY *pkey, struct HksBlob *dsaPublicKey)
638{
639    const DSA *dsa = EVP_PKEY_get0_DSA(pkey);
640    HKS_IF_NULL_LOGE_RETURN(dsa, HKS_ERROR_NULL_POINTER,
641        "EVP_PKEY_get1_DSA error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
642
643    const BIGNUM *y = NULL;
644    const BIGNUM *p = NULL;
645    const BIGNUM *q = NULL;
646    const BIGNUM *g = NULL;
647    uint32_t ySize = 0;
648    uint32_t pSize = 0;
649    uint32_t qSize = 0;
650    uint32_t gSize = 0;
651
652    if (GetDsaKeyInfo(dsa, &y, &ySize, DSA_get0_pub_key) != HKS_SUCCESS ||
653        GetDsaKeyInfo(dsa, &p, &pSize, DSA_get0_p) != HKS_SUCCESS ||
654        GetDsaKeyInfo(dsa, &q, &qSize, DSA_get0_q) != HKS_SUCCESS ||
655        GetDsaKeyInfo(dsa, &g, &gSize, DSA_get0_g) != HKS_SUCCESS) {
656        return HKS_ERROR_INVALID_ARGUMENT;
657    }
658
659    uint32_t totalSize = sizeof(struct KeyMaterialDsa) + ySize + pSize + qSize + gSize;
660    uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
661    HKS_IF_NULL_RETURN(keyBuffer, HKS_ERROR_MALLOC_FAIL)
662
663    if ((ySize > UINT32_MAX - HKS_BITS_PER_BYTE) ||
664        ((ySize + HKS_BITS_PER_BYTE - 1) / HKS_BITS_PER_BYTE > UINT32_MAX / (HKS_BITS_PER_BYTE * HKS_BITS_PER_BYTE))) {
665        HKS_FREE(keyBuffer);
666        return HKS_ERROR_BAD_STATE;
667    }
668
669    struct KeyMaterialDsa *keyMaterial = (struct KeyMaterialDsa *)keyBuffer;
670    keyMaterial->keyAlg = HKS_ALG_DSA;
671    keyMaterial->keySize = (ySize + HKS_BITS_PER_BYTE - 1) / HKS_BITS_PER_BYTE * HKS_BITS_PER_BYTE * HKS_BITS_PER_BYTE;
672    keyMaterial->xSize = 0;
673    keyMaterial->ySize = ySize;
674    keyMaterial->pSize = pSize;
675    keyMaterial->qSize = qSize;
676    keyMaterial->gSize = gSize;
677
678    if ((BN_bn2bin(y, keyBuffer + sizeof(struct KeyMaterialDsa) + keyMaterial->xSize) == 0) ||
679        (BN_bn2bin(p, keyBuffer + sizeof(struct KeyMaterialDsa) + keyMaterial->xSize + ySize) == 0) ||
680        (BN_bn2bin(q, keyBuffer + sizeof(struct KeyMaterialDsa) + keyMaterial->xSize + ySize + pSize) == 0) ||
681        (BN_bn2bin(g, keyBuffer + sizeof(struct KeyMaterialDsa) + keyMaterial->xSize + ySize + pSize + qSize) == 0)) {
682        HKS_LOG_E("BN_bn2bin error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
683        HKS_FREE(keyBuffer);
684        return HKS_ERROR_CRYPTO_ENGINE_ERROR;
685    }
686    dsaPublicKey->size = totalSize;
687    dsaPublicKey->data = keyBuffer;
688
689    return HKS_SUCCESS;
690}
691#endif
692
693#ifdef HKS_SUPPORT_DH_C
694static int32_t X509PublicKeyToDh(EVP_PKEY *pkey, struct HksBlob *dhPublicKey)
695{
696    const DH *dh = EVP_PKEY_get0_DH(pkey);
697    HKS_IF_NULL_LOGE_RETURN(dh, HKS_ERROR_NULL_POINTER,
698        "EVP_PKEY_get0_DH error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
699
700    const BIGNUM *pubKey = DH_get0_pub_key(dh);
701    HKS_IF_NULL_LOGE_RETURN(pubKey, HKS_ERROR_NULL_POINTER,
702        "DH_get0_pub_key error %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
703
704    uint32_t pubKeySize = (uint32_t)BN_num_bytes(pubKey);
705    if (pubKeySize > UINT32_MAX - sizeof(struct KeyMaterialDh)) {
706        HKS_LOG_E("the size is too long, failed");
707        return HKS_ERROR_BAD_STATE;
708    }
709
710    uint32_t totalSize = sizeof(struct KeyMaterialDh) + pubKeySize;
711    uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
712    HKS_IF_NULL_LOGE_RETURN(keyBuffer, HKS_ERROR_MALLOC_FAIL, "alloc keyBuffer failed")
713    struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)keyBuffer;
714    keyMaterial->keyAlg = HKS_ALG_DH;
715    keyMaterial->keySize = (uint32_t)DH_bits(dh);
716    keyMaterial->pubKeySize = pubKeySize;
717    keyMaterial->priKeySize = 0;
718    keyMaterial->reserved = 0;
719
720    BN_bn2bin(pubKey, keyBuffer + sizeof(struct KeyMaterialDh));
721
722    dhPublicKey->size = totalSize;
723    dhPublicKey->data = keyBuffer;
724
725    return HKS_SUCCESS;
726}
727#endif
728
729int32_t TranslateFromX509PublicKey(const uint32_t alg, const struct HksBlob *x509Key, struct HksBlob *publicKey)
730{
731    if (x509Key == NULL || x509Key->data == NULL || x509Key->size == 0 || publicKey == NULL) {
732        HKS_LOG_E("TranslateFromX509PublicKey invalid args");
733        return HKS_ERROR_INVALID_ARGUMENT;
734    }
735
736    uint8_t *data = x509Key->data;
737
738    EVP_PKEY *pkey = d2i_PUBKEY(NULL, (const unsigned char **)&data, x509Key->size);
739    HKS_IF_NULL_RETURN(pkey, HKS_ERROR_INVALID_ARGUMENT)
740
741    int32_t ret;
742    int32_t keyType = EVP_PKEY_base_id(pkey);
743    if (keyType == EVP_PKEY_RSA) {
744#ifdef HKS_SUPPORT_RSA_C
745        ret = X509PublicKeyToRsa(pkey, publicKey);
746#else
747        ret = HKS_ERROR_INVALID_ALGORITHM;
748#endif
749    } else if (keyType == EVP_PKEY_EC) {
750#ifdef HKS_SUPPORT_ECC_C
751        ret = X509PublicKeyToEcc(alg, pkey, publicKey);
752#else
753        ret = HKS_ERROR_INVALID_ALGORITHM;
754#endif
755    } else if (EVP_PKEY_is_a(pkey, SN_sm2)) {
756#ifdef HKS_SUPPORT_SM2_C
757        ret = X509PublicKeyToSm2(alg, pkey, publicKey);
758#else
759        ret = HKS_ERROR_INVALID_ALGORITHM;
760#endif
761    } else if (keyType == EVP_PKEY_DSA) {
762#ifdef HKS_SUPPORT_DSA_C
763        ret = X509PublicKeyToDsa(pkey, publicKey);
764#else
765        ret = HKS_ERROR_INVALID_ALGORITHM;
766#endif
767    } else if (keyType == EVP_PKEY_DH) {
768#ifdef HKS_SUPPORT_DH_C
769        ret = X509PublicKeyToDh(pkey, publicKey);
770#else
771        ret = HKS_ERROR_INVALID_ALGORITHM;
772#endif
773    } else {
774        HKS_LOG_E("Unsupport alg type! %" LOG_PUBLIC "d", keyType);
775        ret = HKS_ERROR_INVALID_ARGUMENT;
776    }
777
778    SELF_FREE_PTR(pkey, EVP_PKEY_free)
779    return ret;
780}
781#endif
782
783