1 /*
2 * Copyright (c) 2022-2023 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 #include "dcm_attest_utils.h"
17
18 #include <stddef.h>
19
20 #include "dcm_asn1.h"
21 #include "hks_crypto_hal.h"
22 #include "hks_log.h"
23 #include "hks_template.h"
24 #include "securec.h"
25
26 static const uint8_t g_p256SpkiHeaderForEcc[] = {
27 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
28 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04
29 };
30
31 static const uint8_t g_p256SpkiHeaderForSm2[] = {
32 0x30, 0x5a, 0x30, 0x14, 0x06, 0x08, 0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d,
33 0x06, 0x08, 0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d, 0x03, 0x42, 0x00, 0x04
34 };
35
36 static const uint8_t g_p384SpkiHeader[] = {
37 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b,
38 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04
39 };
40
41 static const uint8_t g_p521SpkiHeader[] = {
42 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05,
43 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, 0x00, 0x04
44 };
45
46 static uint8_t g_rsaEnTag[] = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
47 DECLARE_OID(g_rsaEn);
48
49 static uint8_t g_x25519Tag[] = { 0x06, 0x03, 0x2B, 0x65, 0x6E };
50 DECLARE_OID(g_x25519);
51
52 #define ENCODED_SEC_LEVEL_SIZE 3
EncodeSecurityLevel(uint8_t * out,uint32_t level)53 static uint32_t EncodeSecurityLevel(uint8_t *out, uint32_t level)
54 {
55 HKS_ASN1_ENCODE_BYTE(out, ASN_1_TAG_TYPE_INT);
56 HKS_ASN1_ENCODE_BYTE(out, 1);
57 HKS_ASN1_ENCODE_BYTE(out, level);
58 return ENCODED_SEC_LEVEL_SIZE;
59 }
60
DcmInsertClaim(struct HksBlob * out,const struct HksBlob * oid,const struct HksAsn1Blob * value,uint32_t secLevel)61 int32_t DcmInsertClaim(struct HksBlob *out, const struct HksBlob *oid, const struct HksAsn1Blob *value,
62 uint32_t secLevel)
63 {
64 if ((CheckBlob(out) != HKS_SUCCESS) || (CheckBlob(oid) != HKS_SUCCESS) || (CheckAsn1Blob(value) != HKS_SUCCESS)) {
65 HKS_LOG_E("invalid input");
66 return HKS_ERROR_INVALID_ARGUMENT;
67 }
68 if (out->size < oid->size + value->size + ENCODED_SEC_LEVEL_SIZE + ASN_1_MAX_HEADER_LEN) {
69 HKS_LOG_E("out buffer too small");
70 return HKS_ERROR_BUFFER_TOO_SMALL;
71 }
72
73 uint8_t *buf = out->data + ASN_1_MAX_HEADER_LEN;
74 buf += EncodeSecurityLevel(buf, secLevel);
75 (void)memcpy_s(buf, out->size - ASN_1_MAX_HEADER_LEN - ENCODED_SEC_LEVEL_SIZE, oid->data, oid->size);
76 buf += oid->size;
77
78 uint32_t offset = buf - out->data;
79 struct HksBlob tmp = { out->size - offset, buf };
80 int32_t ret = DcmAsn1WriteFinal(&tmp, value);
81 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "write final value fail\n")
82
83 uint32_t seqSize = ENCODED_SEC_LEVEL_SIZE + oid->size + tmp.size;
84 struct HksAsn1Blob seq = { ASN_1_TAG_TYPE_SEQ, seqSize, out->data + ASN_1_MAX_HEADER_LEN };
85 return DcmAsn1InsertValue(out, NULL, &seq);
86 }
87
GetEcPublicKey(struct HksBlob * key,const struct HksPubKeyInfo * info)88 static int32_t GetEcPublicKey(struct HksBlob *key, const struct HksPubKeyInfo *info)
89 {
90 const uint8_t *spkiHeader = NULL;
91 uint32_t spkiHeaderLen;
92
93 if (info->keyAlg == HKS_ALG_SM2) {
94 spkiHeader = (const uint8_t *)g_p256SpkiHeaderForSm2;
95 spkiHeaderLen = sizeof(g_p256SpkiHeaderForSm2);
96 } else {
97 switch (info->keySize) {
98 case HKS_ECC_KEY_SIZE_256:
99 spkiHeader = (const uint8_t *)g_p256SpkiHeaderForEcc;
100 spkiHeaderLen = sizeof(g_p256SpkiHeaderForEcc);
101 break;
102 case HKS_ECC_KEY_SIZE_384:
103 spkiHeader = (const uint8_t *)g_p384SpkiHeader;
104 spkiHeaderLen = sizeof(g_p384SpkiHeader);
105 break;
106 case HKS_ECC_KEY_SIZE_521:
107 spkiHeader = (const uint8_t *)g_p521SpkiHeader;
108 spkiHeaderLen = sizeof(g_p521SpkiHeader);
109 break;
110 default:
111 HKS_LOG_E("ec curve not supported: %" LOG_PUBLIC "u\n", info->keySize);
112 return HKS_ERROR_NOT_SUPPORTED;
113 }
114 }
115
116 uint32_t totalSize = spkiHeaderLen + info->nOrXSize + info->eOrYSize;
117 if (key->size < totalSize) {
118 HKS_LOG_E("out size is too small: %" LOG_PUBLIC "u < %" LOG_PUBLIC "u\n", key->size, totalSize);
119 return HKS_ERROR_BUFFER_TOO_SMALL;
120 }
121 key->size = totalSize;
122
123 uint8_t *p = key->data;
124 (void)memcpy_s(p, spkiHeaderLen, spkiHeader, spkiHeaderLen);
125 p += spkiHeaderLen;
126 uint8_t *publicKey = (uint8_t *)(info + 1);
127 (void)memcpy_s(p, totalSize - spkiHeaderLen, publicKey, info->nOrXSize);
128 p += info->nOrXSize;
129 (void)memcpy_s(p, totalSize - spkiHeaderLen - info->nOrXSize, publicKey + info->nOrXSize, info->eOrYSize);
130 return HKS_SUCCESS;
131 }
132
ConstructKeySeq(struct HksBlob * out,const struct HksPubKeyInfo * info)133 static int32_t ConstructKeySeq(struct HksBlob *out, const struct HksPubKeyInfo *info)
134 {
135 struct HksBlob buf = *out;
136 if (buf.size < ASN_1_MAX_HEADER_LEN) {
137 HKS_LOG_E("buf is not big enough\n");
138 return HKS_ERROR_INSUFFICIENT_MEMORY;
139 }
140 buf.data += ASN_1_MAX_HEADER_LEN;
141 buf.size -= ASN_1_MAX_HEADER_LEN;
142
143 uint8_t *publicKey = (uint8_t *)(info + 1);
144 struct HksAsn1Blob n = { ASN_1_TAG_TYPE_INT, info->nOrXSize, publicKey };
145 int32_t ret = DcmAsn1InsertValue(&buf, NULL, &n);
146 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "insert n value fail\n")
147
148 struct HksAsn1Blob e = { ASN_1_TAG_TYPE_INT, info->eOrYSize, publicKey + info->nOrXSize };
149 ret = DcmAsn1InsertValue(&buf, NULL, &e);
150 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "insert e value fail\n")
151
152 uint32_t seqSize = buf.data - out->data - ASN_1_MAX_HEADER_LEN;
153 struct HksAsn1Blob seq = { ASN_1_TAG_TYPE_SEQ, seqSize, out->data + ASN_1_MAX_HEADER_LEN };
154 ret = DcmAsn1WriteFinal(out, &seq);
155 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "write final value fail\n")
156
157 return HKS_SUCCESS;
158 }
159
GetRsaSignOid(uint32_t digest)160 static const struct HksBlob *GetRsaSignOid(uint32_t digest)
161 {
162 (void)digest;
163 return &g_rsaEnOid;
164 }
165
GetRsaPublicKey(struct HksBlob * key,const struct HksPubKeyInfo * info,const struct HksUsageSpec * usageSpec)166 static int32_t GetRsaPublicKey(struct HksBlob *key, const struct HksPubKeyInfo *info,
167 const struct HksUsageSpec *usageSpec)
168 {
169 struct HksBlob tmp = *key;
170 tmp.data += ASN_1_MAX_HEADER_LEN;
171 tmp.size -= ASN_1_MAX_HEADER_LEN;
172 if (tmp.size < ASN_1_MAX_HEADER_LEN) {
173 HKS_LOG_E("buf is not big enough\n");
174 return HKS_ERROR_INSUFFICIENT_MEMORY;
175 }
176
177 const struct HksBlob *signOid = GetRsaSignOid(usageSpec->digest);
178 HKS_IF_NULL_LOGE_RETURN(signOid, HKS_ERROR_INVALID_ALGORITHM, "invalid digest\n")
179
180 struct HksAsn1Blob signOidBlob = { ASN_1_TAG_TYPE_SEQ, signOid->size, signOid->data };
181 int32_t ret = DcmAsn1InsertValue(&tmp, NULL, &signOidBlob);
182 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "insert signOid value fail\n")
183
184 struct HksBlob spki = tmp;
185 ret = ConstructKeySeq(&spki, info);
186 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "construct key seq fail\n")
187
188 struct HksAsn1Blob spkiBlob = { ASN_1_TAG_TYPE_BIT_STR, spki.size, spki.data };
189 ret = DcmAsn1InsertValue(&tmp, NULL, &spkiBlob);
190 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "insert spkiBlob value fail\n")
191
192 uint8_t *seqData = key->data + ASN_1_MAX_HEADER_LEN;
193 uint32_t seqSize = tmp.data - seqData;
194 struct HksAsn1Blob seqDataBlob = { ASN_1_TAG_TYPE_SEQ, seqSize, seqData };
195 return DcmAsn1WriteFinal(key, &seqDataBlob);
196 }
197
GetX25519PublicKey(struct HksBlob * key,const struct HksPubKeyInfo * info)198 static int32_t GetX25519PublicKey(struct HksBlob *key, const struct HksPubKeyInfo *info)
199 {
200 struct HksBlob tmp = *key;
201 tmp.data += ASN_1_MAX_HEADER_LEN;
202 tmp.size -= ASN_1_MAX_HEADER_LEN;
203 if (tmp.size < ASN_1_MAX_HEADER_LEN) {
204 HKS_LOG_E("buf is not big enough\n");
205 return HKS_ERROR_INSUFFICIENT_MEMORY;
206 }
207
208 struct HksAsn1Blob x25519Oid = { ASN_1_TAG_TYPE_SEQ, g_x25519Oid.size, g_x25519Oid.data };
209 int32_t ret = DcmAsn1InsertValue(&tmp, NULL, &x25519Oid);
210 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "insert oid value fail\n")
211
212 uint8_t *publicKey = (uint8_t *)(info + 1);
213 struct HksAsn1Blob spkiBlob = { ASN_1_TAG_TYPE_BIT_STR, info->nOrXSize, publicKey };
214 ret = DcmAsn1InsertValue(&tmp, NULL, &spkiBlob);
215 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "insert pub value fail\n")
216
217 uint8_t *seqData = key->data + ASN_1_MAX_HEADER_LEN;
218 uint32_t seqSize = tmp.data - seqData;
219 struct HksAsn1Blob seqDataBlob = { ASN_1_TAG_TYPE_SEQ, seqSize, seqData };
220 return DcmAsn1WriteFinal(key, &seqDataBlob);
221 }
222
GetSm2PublicKey(struct HksBlob * key,const struct HksPubKeyInfo * info)223 static int32_t GetSm2PublicKey(struct HksBlob *key, const struct HksPubKeyInfo *info)
224 {
225 if (info->keySize != HKS_SM2_KEY_SIZE_256) {
226 HKS_LOG_E("sm2 not supported key size: %" LOG_PUBLIC "u\n", info->keySize);
227 return HKS_ERROR_NOT_SUPPORTED;
228 }
229 return GetEcPublicKey(key, info);
230 }
231
DcmGetPublicKey(struct HksBlob * key,const struct HksPubKeyInfo * info,const struct HksUsageSpec * usageSpec)232 int32_t DcmGetPublicKey(struct HksBlob *key, const struct HksPubKeyInfo *info, const struct HksUsageSpec *usageSpec)
233 {
234 if ((CheckBlob(key) != HKS_SUCCESS) || (info == NULL) || (usageSpec == NULL)) {
235 HKS_LOG_E("invalid get public key params\n");
236 return HKS_ERROR_INVALID_ARGUMENT;
237 }
238
239 if (info->keyAlg == HKS_ALG_RSA) {
240 return GetRsaPublicKey(key, info, usageSpec);
241 } else if (info->keyAlg == HKS_ALG_ECC) {
242 return GetEcPublicKey(key, info);
243 } else if (info->keyAlg == HKS_ALG_X25519) {
244 return GetX25519PublicKey(key, info);
245 } else if (info->keyAlg == HKS_ALG_SM2) {
246 return GetSm2PublicKey(key, info);
247 } else {
248 HKS_LOG_E("alg %" LOG_PUBLIC "u not supported to export public key\n", info->keyAlg);
249 return HKS_ERROR_NOT_SUPPORTED;
250 }
251 }
252