/src/nss/lib/freebl/ecdecode.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifdef FREEBL_NO_DEPEND |
6 | | #include "stubs.h" |
7 | | #endif |
8 | | |
9 | | #include "blapi.h" |
10 | | #include "secoid.h" |
11 | | #include "secitem.h" |
12 | | #include "secerr.h" |
13 | | #include "ec.h" |
14 | | #include "ecl-curve.h" |
15 | | |
16 | | #define CHECK_OK(func) \ |
17 | 3.48k | if (func == NULL) \ |
18 | 3.48k | goto cleanup |
19 | | #define CHECK_SEC_OK(func) \ |
20 | 3.48k | if (SECSuccess != (rv = func)) \ |
21 | 3.48k | goto cleanup |
22 | | |
23 | | /* Copy all of the fields from srcParams into dstParams |
24 | | */ |
25 | | SECStatus |
26 | | EC_CopyParams(PLArenaPool *arena, ECParams *dstParams, |
27 | | const ECParams *srcParams) |
28 | 0 | { |
29 | 0 | SECStatus rv = SECFailure; |
30 | |
|
31 | 0 | dstParams->arena = arena; |
32 | 0 | dstParams->type = srcParams->type; |
33 | 0 | dstParams->fieldID.size = srcParams->fieldID.size; |
34 | 0 | dstParams->fieldID.type = srcParams->fieldID.type; |
35 | 0 | if (srcParams->fieldID.type == ec_field_GFp || |
36 | 0 | srcParams->fieldID.type == ec_field_plain) { |
37 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime, |
38 | 0 | &srcParams->fieldID.u.prime)); |
39 | 0 | } else { |
40 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly, |
41 | 0 | &srcParams->fieldID.u.poly)); |
42 | 0 | } |
43 | 0 | dstParams->fieldID.k1 = srcParams->fieldID.k1; |
44 | 0 | dstParams->fieldID.k2 = srcParams->fieldID.k2; |
45 | 0 | dstParams->fieldID.k3 = srcParams->fieldID.k3; |
46 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a, |
47 | 0 | &srcParams->curve.a)); |
48 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b, |
49 | 0 | &srcParams->curve.b)); |
50 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed, |
51 | 0 | &srcParams->curve.seed)); |
52 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base, |
53 | 0 | &srcParams->base)); |
54 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order, |
55 | 0 | &srcParams->order)); |
56 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding, |
57 | 0 | &srcParams->DEREncoding)); |
58 | 0 | dstParams->name = srcParams->name; |
59 | 0 | CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID, |
60 | 0 | &srcParams->curveOID)); |
61 | 0 | dstParams->cofactor = srcParams->cofactor; |
62 | |
|
63 | 0 | return SECSuccess; |
64 | | |
65 | 0 | cleanup: |
66 | 0 | return SECFailure; |
67 | 0 | } |
68 | | |
69 | | static SECStatus |
70 | | gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *params) |
71 | 3.48k | { |
72 | 3.48k | SECStatus rv = SECFailure; |
73 | 3.48k | const ECCurveBytes *curveParams; |
74 | | |
75 | 3.48k | if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) |
76 | 0 | goto cleanup; |
77 | 3.48k | params->name = name; |
78 | 3.48k | curveParams = ecCurve_map[params->name]; |
79 | 3.48k | CHECK_OK(curveParams); |
80 | 3.48k | params->fieldID.size = curveParams->size; |
81 | 3.48k | params->fieldID.type = field_type; |
82 | 3.48k | if (field_type != ec_field_GFp && field_type != ec_field_plain) { |
83 | 0 | return SECFailure; |
84 | 0 | } |
85 | 3.48k | params->fieldID.u.prime.len = curveParams->scalarSize; |
86 | 3.48k | params->fieldID.u.prime.data = (unsigned char *)curveParams->irr; |
87 | 3.48k | params->curve.a.len = curveParams->scalarSize; |
88 | 3.48k | params->curve.a.data = (unsigned char *)curveParams->curvea; |
89 | 3.48k | params->curve.b.len = curveParams->scalarSize; |
90 | 3.48k | params->curve.b.data = (unsigned char *)curveParams->curveb; |
91 | 3.48k | params->base.len = curveParams->pointSize; |
92 | 3.48k | params->base.data = (unsigned char *)curveParams->base; |
93 | 3.48k | params->order.len = curveParams->scalarSize; |
94 | 3.48k | params->order.data = (unsigned char *)curveParams->order; |
95 | 3.48k | params->cofactor = curveParams->cofactor; |
96 | | |
97 | 3.48k | rv = SECSuccess; |
98 | | |
99 | 3.48k | cleanup: |
100 | 3.48k | return rv; |
101 | 3.48k | } |
102 | | |
103 | | SECStatus |
104 | | EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams, |
105 | | ECParams *params) |
106 | 3.61k | { |
107 | 3.61k | SECStatus rv = SECFailure; |
108 | 3.61k | SECOidTag tag; |
109 | 3.61k | SECItem oid = { siBuffer, NULL, 0 }; |
110 | | |
111 | | #if EC_DEBUG |
112 | | int i; |
113 | | |
114 | | printf("Encoded params in EC_DecodeParams: "); |
115 | | for (i = 0; i < encodedParams->len; i++) { |
116 | | printf("%02x:", encodedParams->data[i]); |
117 | | } |
118 | | printf("\n"); |
119 | | #endif |
120 | | |
121 | 3.61k | if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) && |
122 | 3.61k | (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) && |
123 | 3.61k | (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN) && |
124 | 3.61k | (encodedParams->len != ED25519_OID_TOTAL_LEN)) { |
125 | 0 | PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); |
126 | 0 | return SECFailure; |
127 | 3.61k | }; |
128 | | |
129 | 3.61k | oid.len = encodedParams->len - 2; |
130 | 3.61k | oid.data = encodedParams->data + 2; |
131 | 3.61k | if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) || |
132 | 3.61k | ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) { |
133 | 0 | PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); |
134 | 0 | return SECFailure; |
135 | 0 | } |
136 | | |
137 | 3.61k | params->arena = arena; |
138 | 3.61k | params->cofactor = 0; |
139 | 3.61k | params->type = ec_params_named; |
140 | 3.61k | params->name = ECCurve_noName; |
141 | | |
142 | | /* Fill out curveOID */ |
143 | 3.61k | params->curveOID.len = oid.len; |
144 | 3.61k | params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len); |
145 | 3.61k | if (params->curveOID.data == NULL) |
146 | 0 | goto cleanup; |
147 | 3.61k | memcpy(params->curveOID.data, oid.data, oid.len); |
148 | | |
149 | | #if EC_DEBUG |
150 | | printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); |
151 | | #endif |
152 | | |
153 | 3.61k | switch (tag) { |
154 | 1.00k | case SEC_OID_ANSIX962_EC_PRIME256V1: |
155 | | /* Populate params for prime256v1 aka secp256r1 |
156 | | * (the NIST P-256 curve) |
157 | | */ |
158 | 1.00k | CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_X9_62_PRIME_256V1, |
159 | 1.00k | ec_field_plain, params)); |
160 | 1.00k | break; |
161 | | |
162 | 2.13k | case SEC_OID_SECG_EC_SECP384R1: |
163 | | /* Populate params for secp384r1 |
164 | | * (the NIST P-384 curve) |
165 | | */ |
166 | 2.13k | CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_384R1, |
167 | 2.13k | ec_field_GFp, params)); |
168 | 2.13k | break; |
169 | | |
170 | 2.13k | case SEC_OID_SECG_EC_SECP521R1: |
171 | | /* Populate params for secp521r1 |
172 | | * (the NIST P-521 curve) |
173 | | */ |
174 | 344 | CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1, |
175 | 344 | ec_field_GFp, params)); |
176 | 344 | break; |
177 | | |
178 | 344 | case SEC_OID_ED25519_PUBLIC_KEY: |
179 | 0 | params->type = ec_params_edwards_named; |
180 | 0 | CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_Ed25519, |
181 | 0 | ec_field_plain, params)); |
182 | | |
183 | 0 | break; |
184 | | |
185 | 0 | case SEC_OID_CURVE25519: |
186 | | /* Populate params for Curve25519 */ |
187 | 0 | params->type = ec_params_montgomery_named; |
188 | 0 | CHECK_SEC_OK(gf_populate_params_bytes(ECCurve25519, |
189 | 0 | ec_field_plain, |
190 | 0 | params)); |
191 | 0 | break; |
192 | | |
193 | 129 | default: |
194 | 129 | break; |
195 | 3.61k | }; |
196 | | |
197 | 3.61k | cleanup: |
198 | 3.61k | if (!params->cofactor) { |
199 | 129 | PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); |
200 | | #if EC_DEBUG |
201 | | printf("Unrecognized curve, returning NULL params\n"); |
202 | | #endif |
203 | 129 | } |
204 | | |
205 | 3.61k | return rv; |
206 | 3.61k | } |
207 | | |
208 | | SECStatus |
209 | | EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams) |
210 | 915 | { |
211 | 915 | PLArenaPool *arena; |
212 | 915 | ECParams *params; |
213 | 915 | SECStatus rv = SECFailure; |
214 | | |
215 | | /* Initialize an arena for the ECParams structure */ |
216 | 915 | if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE))) |
217 | 0 | return SECFailure; |
218 | | |
219 | 915 | params = (ECParams *)PORT_ArenaZAlloc(arena, sizeof(ECParams)); |
220 | 915 | if (!params) { |
221 | 0 | PORT_FreeArena(arena, PR_TRUE); |
222 | 0 | return SECFailure; |
223 | 0 | } |
224 | | |
225 | | /* Copy the encoded params */ |
226 | 915 | SECITEM_AllocItem(arena, &(params->DEREncoding), |
227 | 915 | encodedParams->len); |
228 | 915 | memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len); |
229 | | |
230 | | /* Fill out the rest of the ECParams structure based on |
231 | | * the encoded params |
232 | | */ |
233 | 915 | rv = EC_FillParams(arena, encodedParams, params); |
234 | 915 | if (rv == SECFailure) { |
235 | 92 | PORT_FreeArena(arena, PR_TRUE); |
236 | 92 | return SECFailure; |
237 | 823 | } else { |
238 | 823 | *ecparams = params; |
239 | 823 | ; |
240 | 823 | return SECSuccess; |
241 | 823 | } |
242 | 915 | } |
243 | | |
244 | | int |
245 | | EC_GetPointSize(const ECParams *params) |
246 | 5.54k | { |
247 | 5.54k | ECCurveName name = params->name; |
248 | 5.54k | const ECCurveBytes *curveParams; |
249 | | |
250 | 5.54k | if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) || |
251 | 5.54k | ((curveParams = ecCurve_map[name]) == NULL)) { |
252 | | /* unknown curve, calculate point size from params. assume standard curves with 2 points |
253 | | * and a point compression indicator byte */ |
254 | 0 | int sizeInBytes = (params->fieldID.size + 7) / 8; |
255 | 0 | return sizeInBytes * 2 + 1; |
256 | 0 | } |
257 | | |
258 | 5.54k | if (params->type == ec_params_edwards_named || params->type == ec_params_montgomery_named) { |
259 | 0 | return curveParams->scalarSize; |
260 | 0 | } |
261 | | |
262 | 5.54k | return curveParams->pointSize - 1; |
263 | 5.54k | } |
264 | | |
265 | | int |
266 | | EC_GetScalarSize(const ECParams *params) |
267 | 2.26k | { |
268 | 2.26k | ECCurveName name = params->name; |
269 | 2.26k | const ECCurveBytes *curveParams; |
270 | | |
271 | 2.26k | if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) || |
272 | 2.26k | ((curveParams = ecCurve_map[name]) == NULL)) { |
273 | | /* unknown curve, calculate scalar size from field size in params */ |
274 | 0 | int sizeInBytes = (params->fieldID.size + 7) / 8; |
275 | 0 | return sizeInBytes; |
276 | 0 | } |
277 | 2.26k | return curveParams->scalarSize; |
278 | 2.26k | } |