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