• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #ifdef HKS_SUPPORT_DH_C
23 
24 #include "hks_openssl_dh.h"
25 
26 #include <openssl/bn.h>
27 #include <openssl/dh.h>
28 #include <openssl/obj_mac.h>
29 #include <openssl/ossl_typ.h>
30 #include <stdbool.h>
31 #include <stddef.h>
32 
33 #include "hks_log.h"
34 #include "hks_mem.h"
35 #include "hks_openssl_engine.h"
36 #include "hks_template.h"
37 #include "securec.h"
38 
HksOpensslGetNid(uint32_t keySize,int * nid)39 static int32_t HksOpensslGetNid(uint32_t keySize, int *nid)
40 {
41     switch (keySize) {
42         case HKS_DH_KEY_SIZE_2048:
43             *nid = NID_ffdhe2048;
44             return HKS_SUCCESS;
45         case HKS_DH_KEY_SIZE_3072:
46             *nid = NID_ffdhe3072;
47             return HKS_SUCCESS;
48         case HKS_DH_KEY_SIZE_4096:
49             *nid = NID_ffdhe4096;
50             return HKS_SUCCESS;
51         default:
52             HKS_LOG_E("invalid key size, keySize = %" LOG_PUBLIC "u", keySize);
53             return HKS_ERROR_INVALID_KEY_SIZE;
54     }
55 }
56 
InitDhStruct(const struct HksBlob * key,const bool needPrivateExponent)57 static DH *InitDhStruct(const struct HksBlob *key, const bool needPrivateExponent)
58 {
59     const struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)(key->data);
60     if (key->size != sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize + keyMaterial->priKeySize) {
61         return NULL;
62     }
63 
64     int nid = 0;
65     int32_t ret = HksOpensslGetNid(keyMaterial->keySize, &nid);
66     HKS_IF_NOT_SUCC_RETURN(ret, NULL)
67 
68     DH *dh = DH_new_by_nid(nid);
69     if (dh == NULL) {
70         HksLogOpensslError();
71         return NULL;
72     }
73 
74     uint32_t offset = sizeof(struct KeyMaterialDh);
75     BIGNUM *pubKey = BN_bin2bn(key->data + offset, keyMaterial->pubKeySize, NULL);
76     offset += keyMaterial->pubKeySize;
77     BIGNUM *privKey = BN_bin2bn(key->data + offset, keyMaterial->priKeySize, NULL);
78 
79     if (DH_set0_key(dh, pubKey, privKey) != HKS_OPENSSL_SUCCESS) {
80         HksLogOpensslError();
81         DH_free(dh);
82         return NULL;
83     }
84 
85     return dh;
86 }
87 
88 #ifdef HKS_SUPPORT_DH_GENERATE_KEY
DhSaveKeyMaterial(const DH * dh,const uint32_t keySize,struct HksBlob * key)89 static int32_t DhSaveKeyMaterial(const DH *dh, const uint32_t keySize, struct HksBlob *key)
90 {
91     const BIGNUM *pubKey = NULL;
92     const BIGNUM *privKey = NULL;
93     DH_get0_key(dh, &pubKey, &privKey);
94     const uint32_t rawMaterialLen = sizeof(struct KeyMaterialDh) + (uint32_t)BN_num_bytes(pubKey)
95         + (uint32_t)BN_num_bytes(privKey);
96     uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
97     HKS_IF_NULL_RETURN(rawMaterial, HKS_ERROR_MALLOC_FAIL)
98 
99     (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
100 
101     struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)rawMaterial;
102     keyMaterial->keyAlg = HKS_ALG_DH;
103     keyMaterial->keySize = keySize;
104     keyMaterial->pubKeySize = (uint32_t)BN_num_bytes(pubKey);
105     keyMaterial->priKeySize = (uint32_t)BN_num_bytes(privKey);
106     keyMaterial->reserved = 0;
107 
108     uint32_t offset = sizeof(struct KeyMaterialDh);
109     BN_bn2bin(pubKey, rawMaterial + offset);
110     offset += keyMaterial->pubKeySize;
111     BN_bn2bin(privKey, rawMaterial + offset);
112 
113     key->size = rawMaterialLen;
114     key->data = rawMaterial;
115 
116     return HKS_SUCCESS;
117 }
118 
HksOpensslDhGenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)119 int32_t HksOpensslDhGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
120 {
121     int32_t ret;
122     int nid = 0;
123     ret = HksOpensslGetNid(spec->keyLen, &nid);
124     HKS_IF_NOT_SUCC_RETURN(ret, ret)
125 
126     DH *dh = DH_new_by_nid(nid);
127     if (dh == NULL) {
128         HksLogOpensslError();
129         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
130     }
131     if (DH_generate_key(dh) != HKS_OPENSSL_SUCCESS) {
132         HksLogOpensslError();
133         DH_free(dh);
134         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
135     }
136 
137     ret = DhSaveKeyMaterial(dh, spec->keyLen, key);
138 
139     DH_free(dh);
140 
141     return ret;
142 }
143 #endif /* HKS_SUPPORT_DH_GENERATE_KEY */
144 
145 #ifdef HKS_SUPPORT_DH_GET_PUBLIC_KEY
HksOpensslGetDhPubKey(const struct HksBlob * input,struct HksBlob * output)146 int32_t HksOpensslGetDhPubKey(const struct HksBlob *input, struct HksBlob *output)
147 {
148     struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)input->data;
149     if (input->size < sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize) {
150         return HKS_ERROR_INVALID_ARGUMENT;
151     }
152     if (output->size < sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize) {
153         return HKS_ERROR_INVALID_ARGUMENT;
154     }
155 
156     (void)memcpy_s(output->data, output->size, input->data, sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize);
157     ((struct KeyMaterialDh *)output->data)->priKeySize = 0;
158     ((struct KeyMaterialDh *)output->data)->reserved = 0;
159     output->size = sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize;
160 
161     return HKS_SUCCESS;
162 }
163 #endif /* HKS_SUPPORT_DH_GET_PUBLIC_KEY */
164 
165 #ifdef HKS_SUPPORT_DH_AGREE_KEY
HksOpensslDhAgreeKey(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)166 int32_t HksOpensslDhAgreeKey(const struct HksBlob *nativeKey, const struct HksBlob *pubKey,
167     const struct HksKeySpec *spec, struct HksBlob *sharedKey)
168 {
169     int32_t ret;
170     if (HKS_KEY_BYTES(spec->keyLen) > sharedKey->size) {
171         return HKS_ERROR_INVALID_KEY_SIZE;
172     }
173 
174     struct KeyMaterialDh *pubKeyMaterial = (struct KeyMaterialDh *)pubKey->data;
175     BIGNUM *pub = BN_bin2bn(pubKey->data + sizeof(struct KeyMaterialDh), pubKeyMaterial->pubKeySize, NULL);
176     HKS_IF_NULL_RETURN(pub, HKS_ERROR_CRYPTO_ENGINE_ERROR)
177 
178     DH *dh = InitDhStruct(nativeKey, true);
179     if (dh == NULL) {
180         BN_free(pub);
181         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
182     }
183 
184     uint8_t *computeKey = HksMalloc(DH_size(dh));
185     if (computeKey == NULL) {
186         BN_free(pub);
187         DH_free(dh);
188         return HKS_ERROR_MALLOC_FAIL;
189     }
190 
191     if (DH_compute_key_padded(computeKey, pub, dh) <= 0) {
192         HksLogOpensslError();
193         BN_free(pub);
194         DH_free(dh);
195         HksFree(computeKey);
196         return HKS_ERROR_CRYPTO_ENGINE_ERROR;
197     }
198 
199     if (HKS_KEY_BYTES(spec->keyLen) > (uint32_t)DH_size(dh)) {
200         ret = HKS_ERROR_INVALID_KEY_SIZE;
201     } else {
202         if (memcpy_s(sharedKey->data, sharedKey->size, computeKey, HKS_KEY_BYTES(spec->keyLen)) != EOK) {
203             ret = HKS_ERROR_INSUFFICIENT_MEMORY;
204         } else {
205             sharedKey->size = (uint32_t)DH_size(dh);
206             ret = HKS_SUCCESS;
207         }
208     }
209 
210     (void)memset_s(computeKey, DH_size(dh), 0, DH_size(dh));
211     BN_free(pub);
212     DH_free(dh);
213     HksFree(computeKey);
214     return ret;
215 }
216 #endif /* HKS_SUPPORT_DH_AGREE_KEY */
217 
218 #endif /* HKS_SUPPORT_DH_C */