1 /*
2 * Copyright (C) 2021 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 "pake_protocol_ec_common.h"
17 #include "device_auth_defines.h"
18 #include "hc_log.h"
19 #include "hc_types.h"
20 #include "pake_defs.h"
21 #include "protocol_common.h"
22
23 #define PAKE_PRIVATE_KEY_AND_MASK_HIGH 0xF8
24 #define PAKE_PRIVATE_KEY_AND_MASK_LOW 0x7F
25 #define PAKE_PRIVATE_KEY_OR_MASK_LOW 0x40
26
GetPakeEcAlg(void)27 uint32_t GetPakeEcAlg(void)
28 {
29 return PAKE_ALG_EC;
30 }
31
GenerateEsk(PakeBaseParams * params)32 static int32_t GenerateEsk(PakeBaseParams *params)
33 {
34 int32_t res;
35 if (params->curveType == CURVE_256) {
36 return params->loader->generateRandom(&(params->eskSelf));
37 } else if (params->curveType == CURVE_25519) {
38 res = params->loader->generateRandom(&(params->eskSelf));
39 if (res != HC_SUCCESS) {
40 LOGE("CURVE_25519: GenerateRandom for eskSelf failed, res: %x.", res);
41 return res;
42 }
43 params->eskSelf.val[PAKE_EC_KEY_LEN - 1] &= PAKE_PRIVATE_KEY_AND_MASK_HIGH;
44 params->eskSelf.val[0] &= PAKE_PRIVATE_KEY_AND_MASK_LOW;
45 params->eskSelf.val[0] |= PAKE_PRIVATE_KEY_OR_MASK_LOW;
46 return HC_SUCCESS;
47 } else {
48 LOGE("Unsupported curve: %d.", params->curveType);
49 return HC_ERR_UNSUPPORTED_CURVE;
50 }
51 }
52
InitEcPakeParams(PakeBaseParams * params)53 static int32_t InitEcPakeParams(PakeBaseParams *params)
54 {
55 params->eskSelf.length = PAKE_EC_KEY_LEN;
56 params->innerKeyLen = PAKE_EC_KEY_LEN;
57 /* P256 requires buffer for both X and Y coordinates. */
58 uint32_t keyBufferLen = (params->curveType == CURVE_256) ? (params->innerKeyLen * 2) : (params->innerKeyLen);
59 int32_t res = InitSingleParam(&(params->eskSelf), params->eskSelf.length);
60 if (res != HC_SUCCESS) {
61 LOGE("InitSingleParam for eskSelf failed, res: %x.", res);
62 return res;
63 }
64 res = InitSingleParam(&(params->epkSelf), keyBufferLen);
65 if (res != HC_SUCCESS) {
66 LOGE("InitSingleParam for epkSelf failed, res: %x.", res);
67 return res;
68 }
69 res = InitSingleParam(&(params->base), keyBufferLen);
70 if (res != HC_SUCCESS) {
71 LOGE("InitSingleParam for base failed, res: %x.", res);
72 return res;
73 }
74 return res;
75 }
76
GenerateEcPakeParams(PakeBaseParams * params,Uint8Buff * secret)77 int32_t GenerateEcPakeParams(PakeBaseParams *params, Uint8Buff *secret)
78 {
79 int32_t res = InitEcPakeParams(params);
80 if (res != HC_SUCCESS) {
81 LOGE("InitEcPakeParams failed, res: %x.", res);
82 goto CLEAN_UP;
83 }
84
85 res = GenerateEsk(params);
86 if (res != HC_SUCCESS) {
87 LOGE("GenerateEsk failed, res: %x.", res);
88 goto CLEAN_UP;
89 }
90
91 Algorithm alg = (params->curveType == CURVE_256) ? P256 : X25519;
92 res = params->loader->hashToPoint(secret, alg, ¶ms->base);
93 if (res != HC_SUCCESS) {
94 LOGE("HashToPoint from secret to base failed, res: %x.", res);
95 goto CLEAN_UP;
96 }
97 KeyBuff eskSelfBuff = { params->eskSelf.val, params->eskSelf.length, false };
98 KeyBuff baseBuff = { params->base.val, params->base.length, false };
99 res = params->loader->agreeSharedSecret(&eskSelfBuff, &baseBuff, alg, ¶ms->epkSelf);
100 if (res != HC_SUCCESS) {
101 LOGE("AgreeSharedSecret failed, res: %x.", res);
102 goto CLEAN_UP;
103 }
104 return res;
105 CLEAN_UP:
106 CleanPakeSensitiveKeys(params);
107 return res;
108 }
109
AgreeEcSharedSecret(PakeBaseParams * params,Uint8Buff * sharedSecret)110 int32_t AgreeEcSharedSecret(PakeBaseParams *params, Uint8Buff *sharedSecret)
111 {
112 int32_t res;
113 /* P256 requires buffer for both X and Y coordinates. */
114 uint32_t validKeyBufferLen = (params->curveType == CURVE_256) ? (PAKE_EC_KEY_LEN * 2) : (PAKE_EC_KEY_LEN);
115 if (params->epkPeer.length != validKeyBufferLen) {
116 LOGE("Invalid epkPeer length: %u.", params->epkPeer.length);
117 res = HC_ERR_INVALID_LEN;
118 goto CLEAN_UP;
119 }
120
121 Algorithm alg = (params->curveType == CURVE_256) ? P256 : X25519;
122 if (!params->loader->checkEcPublicKey(&(params->epkPeer), alg)) {
123 LOGE("Check public key failed.");
124 res = HC_ERR_INVALID_PUBLIC_KEY;
125 goto CLEAN_UP;
126 }
127 KeyBuff eskSelfBuff = { params->eskSelf.val, params->eskSelf.length, false };
128 KeyBuff epkPeerBuff = { params->epkPeer.val, params->epkPeer.length, false };
129 res = params->loader->agreeSharedSecret(&eskSelfBuff, &epkPeerBuff, alg, sharedSecret);
130 if (res != HC_SUCCESS) {
131 LOGE("AgreeSharedSecret failed, res: %x.", res);
132 goto CLEAN_UP;
133 }
134 return res;
135 CLEAN_UP:
136 CleanPakeSensitiveKeys(params);
137 return res;
138 }