Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/freebl/ecl/ecp_secp256r1.c
Line
Count
Source (jump to first uncovered line)
1
/* P-256 from HACL* */
2
3
#ifdef FREEBL_NO_DEPEND
4
#include "../stubs.h"
5
#endif
6
7
#include "ecl-priv.h"
8
#include "secitem.h"
9
#include "secerr.h"
10
#include "secmpi.h"
11
#include "../verified/Hacl_P256.h"
12
13
/*
14
 * Point Validation for P-256.
15
 */
16
17
SECStatus
18
ec_secp256r1_pt_validate(const SECItem *pt)
19
28
{
20
28
    SECStatus res = SECSuccess;
21
28
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
28
    if (pt->len != 65) {
28
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
0
        res = SECFailure;
30
0
        return res;
31
0
    }
32
33
28
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
0
        res = SECFailure;
36
0
        return res;
37
0
    }
38
39
28
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
40
41
28
    if (!b) {
42
10
        PORT_SetError(SEC_ERROR_BAD_KEY);
43
10
        res = SECFailure;
44
10
    }
45
28
    return res;
46
28
}
47
48
/*
49
 * Scalar Validation for P-256.
50
 */
51
52
SECStatus
53
ec_secp256r1_scalar_validate(const SECItem *scalar)
54
40
{
55
40
    SECStatus res = SECSuccess;
56
40
    if (!scalar || !scalar->data) {
57
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
58
0
        res = SECFailure;
59
0
        return res;
60
0
    }
61
62
40
    if (scalar->len != 32) {
63
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
64
0
        res = SECFailure;
65
0
        return res;
66
0
    }
67
68
40
    bool b = Hacl_P256_validate_private_key(scalar->data);
69
70
40
    if (!b) {
71
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
72
0
        res = SECFailure;
73
0
    }
74
40
    return res;
75
40
}
76
77
/*
78
 * Scalar multiplication for P-256.
79
 * If P == NULL, the base point is used.
80
 * Returns X = k*P
81
 */
82
83
SECStatus
84
ec_secp256r1_pt_mul(SECItem *X, SECItem *k, SECItem *P)
85
89
{
86
89
    SECStatus res = SECSuccess;
87
89
    if (!P) {
88
89
        uint8_t derived[64] = { 0 };
89
90
89
        if (!X || !k || !X->data || !k->data ||
91
89
            X->len < 65 || k->len != 32) {
92
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
93
0
            res = SECFailure;
94
0
            return res;
95
0
        }
96
97
89
        bool b = Hacl_P256_dh_initiator(derived, k->data);
98
99
89
        if (!b) {
100
4
            PORT_SetError(SEC_ERROR_BAD_KEY);
101
4
            res = SECFailure;
102
4
            return res;
103
4
        }
104
105
85
        X->len = 65;
106
85
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
107
85
        memcpy(X->data + 1, derived, 64);
108
109
85
    } else {
110
0
        uint8_t full_key[32] = { 0 };
111
0
        uint8_t *key;
112
0
        uint8_t derived[64] = { 0 };
113
114
0
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
115
0
            X->len < 32 || P->len != 65 ||
116
0
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
117
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
118
0
            res = SECFailure;
119
0
            return res;
120
0
        }
121
122
        /* We consider keys of up to size 32, or of size 33 with a single leading 0 */
123
0
        if (k->len < 32) {
124
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
125
0
            key = full_key;
126
0
        } else if (k->len == 32) {
127
0
            key = k->data;
128
0
        } else if (k->len == 33 && k->data[0] == 0) {
129
0
            key = k->data + 1;
130
0
        } else {
131
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
132
0
            res = SECFailure;
133
0
            return res;
134
0
        }
135
136
0
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
137
138
0
        if (!b) {
139
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
140
0
            res = SECFailure;
141
0
            return res;
142
0
        }
143
144
0
        X->len = 32;
145
0
        memcpy(X->data, derived, 32);
146
0
    }
147
148
85
    return res;
149
89
}
150
151
/*
152
 * ECDSA Signature for P-256
153
 */
154
155
SECStatus
156
ec_secp256r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature,
157
                         const SECItem *digest, const unsigned char *kb,
158
                         const unsigned int kblen)
159
16
{
160
16
    SECStatus res = SECSuccess;
161
162
16
    if (!ecPrivKey || !signature || !digest || !kb ||
163
16
        !ecPrivKey->privateValue.data ||
164
16
        !signature->data || !digest->data ||
165
16
        ecPrivKey->ecParams.name != ECCurve_NIST_P256) {
166
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
167
0
        res = SECFailure;
168
0
        return res;
169
0
    }
170
171
16
    if (kblen == 0 || digest->len == 0 || signature->len < 64) {
172
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
173
0
        res = SECFailure;
174
0
        return res;
175
0
    }
176
177
    // Private keys should be 32 bytes, but some software trims leading zeros,
178
    // and some software produces 33 byte keys with a leading zero. We'll
179
    // accept these variants.
180
16
    uint8_t padded_key_data[32] = { 0 };
181
16
    uint8_t *key;
182
16
    SECItem *privKey = &ecPrivKey->privateValue;
183
16
    if (privKey->len == 32) {
184
16
        key = privKey->data;
185
16
    } else if (privKey->len == 33 && privKey->data[0] == 0) {
186
0
        key = privKey->data + 1;
187
0
    } else if (privKey->len < 32) {
188
0
        memcpy(padded_key_data + 32 - privKey->len, privKey->data, privKey->len);
189
0
        key = padded_key_data;
190
0
    } else {
191
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
192
0
        return SECFailure;
193
0
    }
194
195
16
    uint8_t hash[32] = { 0 };
196
16
    if (digest->len < 32) {
197
16
        memcpy(hash + 32 - digest->len, digest->data, digest->len);
198
16
    } else {
199
0
        memcpy(hash, digest->data, 32);
200
0
    }
201
202
16
    uint8_t nonce[32] = { 0 };
203
16
    if (kblen < 32) {
204
1
        memcpy(nonce + 32 - kblen, kb, kblen);
205
15
    } else {
206
15
        memcpy(nonce, kb, 32);
207
15
    }
208
209
16
    bool b = Hacl_P256_ecdsa_sign_p256_without_hash(
210
16
        signature->data, 32, hash, key, nonce);
211
16
    if (!b) {
212
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
213
0
        res = SECFailure;
214
0
        return res;
215
0
    }
216
217
16
    signature->len = 64;
218
16
    return res;
219
16
}
220
221
/*
222
 * ECDSA Signature Verification for P-256
223
 */
224
225
SECStatus
226
ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
227
                           const SECItem *digest)
228
17
{
229
17
    SECStatus res = SECSuccess;
230
231
17
    unsigned char _padded_sig_data[64] = { 0 };
232
17
    unsigned char *sig_r, *sig_s;
233
234
17
    if (!key || !signature || !digest ||
235
17
        !key->publicValue.data ||
236
17
        !signature->data || !digest->data ||
237
17
        key->ecParams.name != ECCurve_NIST_P256) {
238
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
239
0
        res = SECFailure;
240
0
        return res;
241
0
    }
242
243
17
    unsigned int olen = key->ecParams.order.len;
244
17
    if (signature->len == 0 || signature->len % 2 != 0 ||
245
17
        signature->len > 2 * olen ||
246
17
        digest->len == 0 || key->publicValue.len != 65) {
247
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
248
0
        res = SECFailure;
249
0
        return res;
250
0
    }
251
252
17
    if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
253
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
254
0
        res = SECFailure;
255
0
        return res;
256
0
    }
257
258
    /* P-256 signature has to be 64 bytes long, pad it with 0s if it isn't */
259
17
    if (signature->len != 64) {
260
0
        unsigned split = signature->len / 2;
261
0
        unsigned pad = 32 - split;
262
263
0
        unsigned char *o_sig = signature->data;
264
0
        unsigned char *p_sig = _padded_sig_data;
265
266
0
        memcpy(p_sig + pad, o_sig, split);
267
0
        memcpy(p_sig + 32 + pad, o_sig + split, split);
268
269
0
        sig_r = p_sig;
270
0
        sig_s = p_sig + 32;
271
17
    } else {
272
17
        sig_r = signature->data;
273
17
        sig_s = signature->data + 32;
274
17
    }
275
276
17
    uint8_t hash[32] = { 0 };
277
17
    if (digest->len < 32) {
278
17
        memcpy(hash + 32 - digest->len, digest->data, digest->len);
279
17
    } else {
280
0
        memcpy(hash, digest->data, 32);
281
0
    }
282
283
17
    bool b = Hacl_P256_ecdsa_verif_without_hash(
284
17
        32, hash,
285
17
        key->publicValue.data + 1,
286
17
        sig_r, sig_s);
287
17
    if (!b) {
288
1
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
289
1
        res = SECFailure;
290
1
        return res;
291
1
    }
292
293
16
    return res;
294
17
}