Coverage Report

Created: 2024-05-20 06:23

/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
}