Coverage Report

Created: 2026-10-28 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libspdm/os_stub/cryptlib_mbedtls/pk/ec.c
Line
Count
Source
1
/**
2
 *  Copyright Notice:
3
 *  Copyright 2021-2022 DMTF. All rights reserved.
4
 *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5
 **/
6
7
/** @file
8
 * Elliptic Curve Wrapper Implementation.
9
 *
10
 * RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites
11
 * FIPS 186-4 - Digital signature Standard (DSS)
12
 **/
13
14
#include "internal_crypt_lib.h"
15
#include <mbedtls/ecp.h>
16
#include <mbedtls/ecdh.h>
17
#include <mbedtls/ecdsa.h>
18
#include <mbedtls/bignum.h>
19
20
/**
21
 * Allocates and Initializes one Elliptic Curve context for subsequent use
22
 * with the NID.
23
 *
24
 * @param nid cipher NID
25
 *
26
 * @return  Pointer to the Elliptic Curve context that has been initialized.
27
 *         If the allocations fails, libspdm_ec_new_by_nid() returns NULL.
28
 *
29
 **/
30
void *libspdm_ec_new_by_nid(size_t nid)
31
308
{
32
308
    mbedtls_ecdh_context *ctx;
33
308
    mbedtls_ecp_group_id grp_id;
34
308
    int ret;
35
36
308
    ctx = allocate_zero_pool(sizeof(mbedtls_ecdh_context));
37
308
    if (ctx == NULL) {
38
0
        return NULL;
39
0
    }
40
308
    switch (nid) {
41
308
    case LIBSPDM_CRYPTO_NID_SECP256R1:
42
308
    case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P256:
43
308
        grp_id = MBEDTLS_ECP_DP_SECP256R1;
44
308
        break;
45
0
    case LIBSPDM_CRYPTO_NID_SECP384R1:
46
0
    case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P384:
47
0
        grp_id = MBEDTLS_ECP_DP_SECP384R1;
48
0
        break;
49
0
    case LIBSPDM_CRYPTO_NID_SECP521R1:
50
0
    case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P521:
51
0
        grp_id = MBEDTLS_ECP_DP_SECP521R1;
52
0
        break;
53
0
    default:
54
0
        goto error;
55
308
    }
56
57
308
    mbedtls_ecdh_init(ctx);
58
308
    ret = mbedtls_ecdh_setup(ctx, grp_id);
59
308
    if (ret != 0) {
60
0
        goto error;
61
0
    }
62
308
    return ctx;
63
0
error:
64
0
    free_pool(ctx);
65
0
    return NULL;
66
308
}
67
68
/**
69
 * Release the specified EC context.
70
 *
71
 * @param[in]  ec_context  Pointer to the EC context to be released.
72
 *
73
 **/
74
void libspdm_ec_free(void *ec_context)
75
9.27k
{
76
9.27k
    mbedtls_ecdh_free(ec_context);
77
9.27k
    free_pool(ec_context);
78
9.27k
}
79
80
/**
81
 * Sets the public key component into the established EC context.
82
 *
83
 * For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
84
 * For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
85
 * For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
86
 *
87
 * @param[in, out]  ec_context      Pointer to EC context being set.
88
 * @param[in]       public         Pointer to the buffer to receive generated public X,Y.
89
 * @param[in]       public_size     The size of public buffer in bytes.
90
 *
91
 * @retval  true   EC public key component was set successfully.
92
 * @retval  false  Invalid EC public key component.
93
 *
94
 **/
95
bool libspdm_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
96
                            size_t public_key_size)
97
0
{
98
0
    mbedtls_ecdh_context *ctx;
99
0
    int ret;
100
0
    size_t half_size;
101
102
0
    if (ec_context == NULL || public_key == NULL) {
103
0
        return false;
104
0
    }
105
106
0
    ctx = ec_context;
107
0
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
108
0
    case MBEDTLS_ECP_DP_SECP256R1:
109
0
        half_size = 32;
110
0
        break;
111
0
    case MBEDTLS_ECP_DP_SECP384R1:
112
0
        half_size = 48;
113
0
        break;
114
0
    case MBEDTLS_ECP_DP_SECP521R1:
115
0
        half_size = 66;
116
0
        break;
117
0
    default:
118
0
        return false;
119
0
    }
120
0
    if (public_key_size != half_size * 2) {
121
0
        return false;
122
0
    }
123
124
0
    ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
125
0
                                  public_key, half_size);
126
0
    if (ret != 0) {
127
0
        return false;
128
0
    }
129
0
    ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
130
0
                                  public_key + half_size, half_size);
131
0
    if (ret != 0) {
132
0
        return false;
133
0
    }
134
0
    ret = mbedtls_mpi_lset(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1);
135
0
    if (ret != 0) {
136
0
        return false;
137
0
    }
138
139
0
    return true;
140
0
}
141
142
/**
143
 * Sets the private key component into the established EC context.
144
 *
145
 * For P-256, the private_key_size is 32 byte.
146
 * For P-384, the private_key_size is 48 byte.
147
 * For P-521, the private_key_size is 66 byte.
148
 *
149
 * @param[in, out]  ec_context       Pointer to EC context being set.
150
 * @param[in]       private_key      Pointer to the private key buffer.
151
 * @param[in]       private_key_size The size of private key buffer in bytes.
152
 *
153
 * @retval  true   EC private key component was set successfully.
154
 * @retval  false  Invalid EC private key component.
155
 *
156
 **/
157
bool libspdm_ec_set_priv_key(void *ec_context, const uint8_t *private_key,
158
                             size_t private_key_size)
159
0
{
160
0
    mbedtls_ecdh_context *ctx;
161
0
    int ret;
162
0
    size_t half_size;
163
164
0
    if (ec_context == NULL || private_key == NULL) {
165
0
        return false;
166
0
    }
167
168
0
    ctx = ec_context;
169
0
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
170
0
    case MBEDTLS_ECP_DP_SECP256R1:
171
0
        half_size = 32;
172
0
        break;
173
0
    case MBEDTLS_ECP_DP_SECP384R1:
174
0
        half_size = 48;
175
0
        break;
176
0
    case MBEDTLS_ECP_DP_SECP521R1:
177
0
        half_size = 66;
178
0
        break;
179
0
    default:
180
0
        return false;
181
0
    }
182
0
    if (private_key_size != half_size) {
183
0
        return false;
184
0
    }
185
186
0
    ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(d), private_key,
187
0
                                  private_key_size);
188
0
    if (ret != 0) {
189
0
        return false;
190
0
    }
191
192
0
    return true;
193
0
}
194
195
/**
196
 * Gets the public key component from the established EC context.
197
 *
198
 * For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
199
 * For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
200
 * For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
201
 *
202
 * @param[in, out]  ec_context      Pointer to EC context being set.
203
 * @param[out]      public         Pointer to the buffer to receive generated public X,Y.
204
 * @param[in, out]  public_size     On input, the size of public buffer in bytes.
205
 *                                On output, the size of data returned in public buffer in bytes.
206
 *
207
 * @retval  true   EC key component was retrieved successfully.
208
 * @retval  false  Invalid EC key component.
209
 *
210
 **/
211
bool libspdm_ec_get_pub_key(void *ec_context, uint8_t *public_key,
212
                            size_t *public_key_size)
213
0
{
214
0
    mbedtls_ecdh_context *ctx;
215
0
    int ret;
216
0
    size_t half_size;
217
0
    size_t x_size;
218
0
    size_t y_size;
219
220
0
    if (ec_context == NULL || public_key_size == NULL) {
221
0
        return false;
222
0
    }
223
224
0
    if (public_key == NULL && *public_key_size != 0) {
225
0
        return false;
226
0
    }
227
228
0
    ctx = ec_context;
229
0
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
230
0
    case MBEDTLS_ECP_DP_SECP256R1:
231
0
        half_size = 32;
232
0
        break;
233
0
    case MBEDTLS_ECP_DP_SECP384R1:
234
0
        half_size = 48;
235
0
        break;
236
0
    case MBEDTLS_ECP_DP_SECP521R1:
237
0
        half_size = 66;
238
0
        break;
239
0
    default:
240
0
        return false;
241
0
    }
242
0
    if (*public_key_size < half_size * 2) {
243
0
        *public_key_size = half_size * 2;
244
0
        return false;
245
0
    }
246
0
    *public_key_size = half_size * 2;
247
0
    libspdm_zero_mem(public_key, *public_key_size);
248
249
0
    x_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X));
250
0
    y_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y));
251
0
    LIBSPDM_ASSERT(x_size <= half_size && y_size <= half_size);
252
253
0
    ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
254
0
                                   &public_key[0 + half_size - x_size], x_size);
255
0
    if (ret != 0) {
256
0
        return false;
257
0
    }
258
0
    ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
259
0
                                   &public_key[half_size + half_size - y_size],
260
0
                                   y_size);
261
0
    if (ret != 0) {
262
0
        return false;
263
0
    }
264
265
0
    return true;
266
0
}
267
268
/**
269
 * Validates key components of EC context.
270
 * NOTE: This function performs integrity checks on all the EC key material, so
271
 *      the EC key structure must contain all the private key data.
272
 *
273
 * If ec_context is NULL, then return false.
274
 *
275
 * @param[in]  ec_context  Pointer to EC context to check.
276
 *
277
 * @retval  true   EC key components are valid.
278
 * @retval  false  EC key components are not valid.
279
 *
280
 **/
281
bool libspdm_ec_check_key(const void *ec_context)
282
0
{
283
    /* TBD*/
284
0
    return true;
285
0
}
286
287
/**
288
 * Generates EC key and returns EC public key (X, Y).
289
 *
290
 * This function generates random secret, and computes the public key (X, Y), which is
291
 * returned via parameter public, public_size.
292
 * X is the first half of public with size being public_size / 2,
293
 * Y is the second half of public with size being public_size / 2.
294
 * EC context is updated accordingly.
295
 * If the public buffer is too small to hold the public X, Y, false is returned and
296
 * public_size is set to the required buffer size to obtain the public X, Y.
297
 *
298
 * For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
299
 * For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
300
 * For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
301
 *
302
 * If ec_context is NULL, then return false.
303
 * If public_size is NULL, then return false.
304
 * If public_size is large enough but public is NULL, then return false.
305
 *
306
 * @param[in, out]  ec_context      Pointer to the EC context.
307
 * @param[out]      public_data     Pointer to the buffer to receive generated public X,Y.
308
 * @param[in, out]  public_size     On input, the size of public buffer in bytes.
309
 *                                On output, the size of data returned in public buffer in bytes.
310
 *
311
 * @retval true   EC public X,Y generation succeeded.
312
 * @retval false  EC public X,Y generation failed.
313
 * @retval false  public_size is not large enough.
314
 *
315
 **/
316
bool libspdm_ec_generate_key(void *ec_context, uint8_t *public_data,
317
                             size_t *public_size)
318
308
{
319
308
    mbedtls_ecdh_context *ctx;
320
308
    int ret;
321
308
    size_t half_size;
322
308
    size_t x_size;
323
308
    size_t y_size;
324
325
308
    if (ec_context == NULL || public_size == NULL) {
326
0
        return false;
327
0
    }
328
329
308
    if (public_data == NULL && *public_size != 0) {
330
0
        return false;
331
0
    }
332
333
308
    ctx = ec_context;
334
308
    ret = mbedtls_ecdh_gen_public(&ctx->MBEDTLS_PRIVATE(grp),
335
308
                                  &ctx->MBEDTLS_PRIVATE(d),
336
308
                                  &ctx->MBEDTLS_PRIVATE(Q), libspdm_myrand,
337
308
                                  NULL);
338
308
    if (ret != 0) {
339
0
        return false;
340
0
    }
341
342
308
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
343
308
    case MBEDTLS_ECP_DP_SECP256R1:
344
308
        half_size = 32;
345
308
        break;
346
0
    case MBEDTLS_ECP_DP_SECP384R1:
347
0
        half_size = 48;
348
0
        break;
349
0
    case MBEDTLS_ECP_DP_SECP521R1:
350
0
        half_size = 66;
351
0
        break;
352
0
    default:
353
0
        return false;
354
308
    }
355
308
    if (*public_size < half_size * 2) {
356
0
        *public_size = half_size * 2;
357
0
        return false;
358
0
    }
359
308
    *public_size = half_size * 2;
360
308
    libspdm_zero_mem(public_data, *public_size);
361
362
308
    x_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X));
363
308
    y_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y));
364
308
    LIBSPDM_ASSERT(x_size <= half_size && y_size <= half_size);
365
366
308
    ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
367
308
                                   &public_data[0 + half_size - x_size], x_size);
368
308
    if (ret != 0) {
369
0
        return false;
370
0
    }
371
308
    ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
372
308
                                   &public_data[half_size + half_size - y_size],
373
308
                                   y_size);
374
308
    if (ret != 0) {
375
0
        return false;
376
0
    }
377
378
308
    return true;
379
308
}
380
381
/**
382
 * Computes exchanged common key.
383
 *
384
 * Given peer's public key (X, Y), this function computes the exchanged common key,
385
 * based on its own context including value of curve parameter and random secret.
386
 * X is the first half of peer_public with size being peer_public_size / 2,
387
 * Y is the second half of peer_public with size being peer_public_size / 2.
388
 *
389
 * If ec_context is NULL, then return false.
390
 * If peer_public is NULL, then return false.
391
 * If peer_public_size is 0, then return false.
392
 * If key is NULL, then return false.
393
 * If key_size is not large enough, then return false.
394
 *
395
 * For P-256, the peer_public_size is 64. first 32-byte is X, second 32-byte is Y. The key_size is 32.
396
 * For P-384, the peer_public_size is 96. first 48-byte is X, second 48-byte is Y. The key_size is 48.
397
 * For P-521, the peer_public_size is 132. first 66-byte is X, second 66-byte is Y. The key_size is 66.
398
 *
399
 * @param[in, out]  ec_context          Pointer to the EC context.
400
 * @param[in]       peer_public         Pointer to the peer's public X,Y.
401
 * @param[in]       peer_public_size     size of peer's public X,Y in bytes.
402
 * @param[out]      key                Pointer to the buffer to receive generated key.
403
 * @param[in, out]  key_size            On input, the size of key buffer in bytes.
404
 *                                    On output, the size of data returned in key buffer in bytes.
405
 *
406
 * @retval true   EC exchanged key generation succeeded.
407
 * @retval false  EC exchanged key generation failed.
408
 * @retval false  key_size is not large enough.
409
 *
410
 **/
411
bool libspdm_ec_compute_key(void *ec_context, const uint8_t *peer_public,
412
                            size_t peer_public_size, uint8_t *key,
413
                            size_t *key_size)
414
0
{
415
0
    mbedtls_ecdh_context *ctx;
416
0
    size_t half_size;
417
0
    int ret;
418
419
0
    if (ec_context == NULL || peer_public == NULL || key_size == NULL ||
420
0
        key == NULL) {
421
0
        return false;
422
0
    }
423
424
0
    if (peer_public_size > INT_MAX) {
425
0
        return false;
426
0
    }
427
428
0
    ctx = ec_context;
429
0
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
430
0
    case MBEDTLS_ECP_DP_SECP256R1:
431
0
        half_size = 32;
432
0
        break;
433
0
    case MBEDTLS_ECP_DP_SECP384R1:
434
0
        half_size = 48;
435
0
        break;
436
0
    case MBEDTLS_ECP_DP_SECP521R1:
437
0
        half_size = 66;
438
0
        break;
439
0
    default:
440
0
        return false;
441
0
    }
442
0
    if (peer_public_size != half_size * 2) {
443
0
        return false;
444
0
    }
445
446
0
    ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Qp).MBEDTLS_PRIVATE(X),
447
0
                                  peer_public, half_size);
448
0
    if (ret != 0) {
449
0
        return false;
450
0
    }
451
0
    ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Qp).MBEDTLS_PRIVATE(Y),
452
0
                                  peer_public + half_size, half_size);
453
0
    if (ret != 0) {
454
0
        return false;
455
0
    }
456
0
    ret = mbedtls_mpi_lset(&ctx->MBEDTLS_PRIVATE(Qp).MBEDTLS_PRIVATE(Z), 1);
457
0
    if (ret != 0) {
458
0
        return false;
459
0
    }
460
461
0
    ret = mbedtls_ecdh_compute_shared(&ctx->MBEDTLS_PRIVATE(grp),
462
0
                                      &ctx->MBEDTLS_PRIVATE(z),
463
0
                                      &ctx->MBEDTLS_PRIVATE(Qp),
464
0
                                      &ctx->MBEDTLS_PRIVATE(d),
465
0
                                      libspdm_myrand, NULL);
466
0
    if (ret != 0) {
467
0
        return false;
468
0
    }
469
470
0
    if (mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(z)) > *key_size) {
471
0
        return false;
472
0
    }
473
474
0
    *key_size = ctx->MBEDTLS_PRIVATE(grp).pbits / 8 +
475
0
                ((ctx->MBEDTLS_PRIVATE(grp).pbits % 8) != 0);
476
0
    ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(z), key, *key_size);
477
0
    if (ret != 0) {
478
0
        return false;
479
0
    }
480
481
0
    return true;
482
0
}
483
484
/**
485
 * Carries out the EC-DSA signature.
486
 *
487
 * This function carries out the EC-DSA signature.
488
 * If the signature buffer is too small to hold the contents of signature, false
489
 * is returned and sig_size is set to the required buffer size to obtain the signature.
490
 *
491
 * If ec_context is NULL, then return false.
492
 * If message_hash is NULL, then return false.
493
 * If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
494
 * If sig_size is large enough but signature is NULL, then return false.
495
 *
496
 * For P-256, the sig_size is 64. first 32-byte is R, second 32-byte is S.
497
 * For P-384, the sig_size is 96. first 48-byte is R, second 48-byte is S.
498
 * For P-521, the sig_size is 132. first 66-byte is R, second 66-byte is S.
499
 *
500
 * @param[in]       ec_context    Pointer to EC context for signature generation.
501
 * @param[in]       hash_nid      hash NID
502
 * @param[in]       message_hash  Pointer to octet message hash to be signed.
503
 * @param[in]       hash_size     size of the message hash in bytes.
504
 * @param[out]      signature    Pointer to buffer to receive EC-DSA signature.
505
 * @param[in, out]  sig_size      On input, the size of signature buffer in bytes.
506
 *                              On output, the size of data returned in signature buffer in bytes.
507
 *
508
 * @retval  true   signature successfully generated in EC-DSA.
509
 * @retval  false  signature generation failed.
510
 * @retval  false  sig_size is too small.
511
 *
512
 **/
513
bool libspdm_ecdsa_sign(void *ec_context, size_t hash_nid,
514
                        const uint8_t *message_hash, size_t hash_size,
515
                        uint8_t *signature, size_t *sig_size)
516
210
{
517
210
    int ret;
518
210
    mbedtls_ecdh_context *ctx;
519
210
    mbedtls_mpi bn_r;
520
210
    mbedtls_mpi bn_s;
521
210
    size_t r_size;
522
210
    size_t s_size;
523
210
    size_t half_size;
524
525
210
    if (ec_context == NULL || message_hash == NULL) {
526
0
        return false;
527
0
    }
528
529
210
    if (signature == NULL) {
530
0
        return false;
531
0
    }
532
533
210
    ctx = ec_context;
534
210
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
535
210
    case MBEDTLS_ECP_DP_SECP256R1:
536
210
        half_size = 32;
537
210
        break;
538
0
    case MBEDTLS_ECP_DP_SECP384R1:
539
0
        half_size = 48;
540
0
        break;
541
0
    case MBEDTLS_ECP_DP_SECP521R1:
542
0
        half_size = 66;
543
0
        break;
544
0
    default:
545
0
        return false;
546
210
    }
547
210
    if (*sig_size < (size_t)(half_size * 2)) {
548
0
        *sig_size = half_size * 2;
549
0
        return false;
550
0
    }
551
210
    *sig_size = half_size * 2;
552
210
    libspdm_zero_mem(signature, *sig_size);
553
554
210
    switch (hash_nid) {
555
210
    case LIBSPDM_CRYPTO_NID_SHA256:
556
210
        if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
557
0
            return false;
558
0
        }
559
210
        break;
560
561
210
    case LIBSPDM_CRYPTO_NID_SHA384:
562
0
        if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
563
0
            return false;
564
0
        }
565
0
        break;
566
567
0
    case LIBSPDM_CRYPTO_NID_SHA512:
568
0
        if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
569
0
            return false;
570
0
        }
571
0
        break;
572
573
0
    case LIBSPDM_CRYPTO_NID_SHA3_256:
574
0
        if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
575
0
            return false;
576
0
        }
577
0
        break;
578
579
0
    case LIBSPDM_CRYPTO_NID_SHA3_384:
580
0
        if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
581
0
            return false;
582
0
        }
583
0
        break;
584
585
0
    case LIBSPDM_CRYPTO_NID_SHA3_512:
586
0
        if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
587
0
            return false;
588
0
        }
589
0
        break;
590
591
0
    default:
592
0
        return false;
593
210
    }
594
595
210
    mbedtls_mpi_init(&bn_r);
596
210
    mbedtls_mpi_init(&bn_s);
597
598
210
    ret = mbedtls_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &bn_r, &bn_s,
599
210
                             &ctx->MBEDTLS_PRIVATE(d), message_hash,
600
210
                             hash_size, libspdm_myrand, NULL);
601
210
    if (ret != 0) {
602
0
        return false;
603
0
    }
604
605
210
    r_size = mbedtls_mpi_size(&bn_r);
606
210
    s_size = mbedtls_mpi_size(&bn_s);
607
210
    LIBSPDM_ASSERT(r_size <= half_size && s_size <= half_size);
608
609
210
    ret = mbedtls_mpi_write_binary(
610
210
        &bn_r, &signature[0 + half_size - r_size], r_size);
611
210
    if (ret != 0) {
612
0
        mbedtls_mpi_free(&bn_r);
613
0
        mbedtls_mpi_free(&bn_s);
614
0
        return false;
615
0
    }
616
210
    ret = mbedtls_mpi_write_binary(
617
210
        &bn_s, &signature[half_size + half_size - s_size], s_size);
618
210
    if (ret != 0) {
619
0
        mbedtls_mpi_free(&bn_r);
620
0
        mbedtls_mpi_free(&bn_s);
621
0
        return false;
622
0
    }
623
624
210
    mbedtls_mpi_free(&bn_r);
625
210
    mbedtls_mpi_free(&bn_s);
626
627
210
    return true;
628
210
}
629
630
/**
631
 * Verifies the EC-DSA signature.
632
 *
633
 * If ec_context is NULL, then return false.
634
 * If message_hash is NULL, then return false.
635
 * If signature is NULL, then return false.
636
 * If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
637
 *
638
 * For P-256, the sig_size is 64. first 32-byte is R, second 32-byte is S.
639
 * For P-384, the sig_size is 96. first 48-byte is R, second 48-byte is S.
640
 * For P-521, the sig_size is 132. first 66-byte is R, second 66-byte is S.
641
 *
642
 * @param[in]  ec_context    Pointer to EC context for signature verification.
643
 * @param[in]  hash_nid      hash NID
644
 * @param[in]  message_hash  Pointer to octet message hash to be checked.
645
 * @param[in]  hash_size     size of the message hash in bytes.
646
 * @param[in]  signature    Pointer to EC-DSA signature to be verified.
647
 * @param[in]  sig_size      size of signature in bytes.
648
 *
649
 * @retval  true   Valid signature encoded in EC-DSA.
650
 * @retval  false  Invalid signature or invalid EC context.
651
 *
652
 **/
653
bool libspdm_ecdsa_verify(void *ec_context, size_t hash_nid,
654
                          const uint8_t *message_hash, size_t hash_size,
655
                          const uint8_t *signature, size_t sig_size)
656
8
{
657
8
    int ret;
658
8
    mbedtls_ecdh_context *ctx;
659
8
    mbedtls_mpi bn_r;
660
8
    mbedtls_mpi bn_s;
661
8
    size_t half_size;
662
663
8
    if (ec_context == NULL || message_hash == NULL || signature == NULL) {
664
0
        return false;
665
0
    }
666
667
8
    if (sig_size > INT_MAX || sig_size == 0) {
668
0
        return false;
669
0
    }
670
671
8
    ctx = ec_context;
672
8
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
673
8
    case MBEDTLS_ECP_DP_SECP256R1:
674
8
        half_size = 32;
675
8
        break;
676
0
    case MBEDTLS_ECP_DP_SECP384R1:
677
0
        half_size = 48;
678
0
        break;
679
0
    case MBEDTLS_ECP_DP_SECP521R1:
680
0
        half_size = 66;
681
0
        break;
682
0
    default:
683
0
        return false;
684
8
    }
685
8
    if (sig_size != (size_t)(half_size * 2)) {
686
0
        return false;
687
0
    }
688
689
8
    switch (hash_nid) {
690
8
    case LIBSPDM_CRYPTO_NID_SHA256:
691
8
        if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
692
0
            return false;
693
0
        }
694
8
        break;
695
696
8
    case LIBSPDM_CRYPTO_NID_SHA384:
697
0
        if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
698
0
            return false;
699
0
        }
700
0
        break;
701
702
0
    case LIBSPDM_CRYPTO_NID_SHA512:
703
0
        if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
704
0
            return false;
705
0
        }
706
0
        break;
707
708
0
    case LIBSPDM_CRYPTO_NID_SHA3_256:
709
0
        if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
710
0
            return false;
711
0
        }
712
0
        break;
713
714
0
    case LIBSPDM_CRYPTO_NID_SHA3_384:
715
0
        if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
716
0
            return false;
717
0
        }
718
0
        break;
719
720
0
    case LIBSPDM_CRYPTO_NID_SHA3_512:
721
0
        if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
722
0
            return false;
723
0
        }
724
0
        break;
725
726
0
    default:
727
0
        return false;
728
8
    }
729
730
8
    mbedtls_mpi_init(&bn_r);
731
8
    mbedtls_mpi_init(&bn_s);
732
733
8
    ret = mbedtls_mpi_read_binary(&bn_r, signature, half_size);
734
8
    if (ret != 0) {
735
0
        mbedtls_mpi_free(&bn_r);
736
0
        mbedtls_mpi_free(&bn_s);
737
0
        return false;
738
0
    }
739
8
    ret = mbedtls_mpi_read_binary(&bn_s, signature + half_size, half_size);
740
8
    if (ret != 0) {
741
0
        mbedtls_mpi_free(&bn_r);
742
0
        mbedtls_mpi_free(&bn_s);
743
0
        return false;
744
0
    }
745
746
8
    ret = mbedtls_ecdsa_verify(&ctx->MBEDTLS_PRIVATE(grp), message_hash,
747
8
                               hash_size, &ctx->MBEDTLS_PRIVATE(Q),
748
8
                               &bn_r, &bn_s);
749
8
    mbedtls_mpi_free(&bn_r);
750
8
    mbedtls_mpi_free(&bn_s);
751
752
8
    if (ret != 0) {
753
6
        return false;
754
6
    }
755
756
2
    return true;
757
8
}
758
759
#if LIBSPDM_FIPS_MODE
760
/**
761
 * Carries out the EC-DSA signature with caller input random function. This API can be used for FIPS test.
762
 *
763
 * @param[in]       ec_context    Pointer to EC context for signature generation.
764
 * @param[in]       hash_nid      hash NID
765
 * @param[in]       message_hash  Pointer to octet message hash to be signed.
766
 * @param[in]       hash_size     Size of the message hash in bytes.
767
 * @param[out]      signature     Pointer to buffer to receive EC-DSA signature.
768
 * @param[in, out]  sig_size      On input, the size of signature buffer in bytes.
769
 *                                On output, the size of data returned in signature buffer in bytes.
770
 * @param[in]       random_func   random number function
771
 *
772
 * @retval  true   signature successfully generated in EC-DSA.
773
 * @retval  false  signature generation failed.
774
 * @retval  false  sig_size is too small.
775
 **/
776
bool libspdm_ecdsa_sign_ex(void *ec_context, size_t hash_nid,
777
                           const uint8_t *message_hash, size_t hash_size,
778
                           uint8_t *signature, size_t *sig_size,
779
                           int (*random_func)(void *, unsigned char *, size_t))
780
{
781
    int ret;
782
    mbedtls_ecdh_context *ctx;
783
    mbedtls_mpi bn_r;
784
    mbedtls_mpi bn_s;
785
    size_t r_size;
786
    size_t s_size;
787
    size_t half_size;
788
789
    if (ec_context == NULL || message_hash == NULL) {
790
        return false;
791
    }
792
793
    if (signature == NULL) {
794
        return false;
795
    }
796
797
    ctx = ec_context;
798
    switch (mbedtls_ecdh_get_grp_id(ctx)) {
799
    case MBEDTLS_ECP_DP_SECP256R1:
800
        half_size = 32;
801
        break;
802
    case MBEDTLS_ECP_DP_SECP384R1:
803
        half_size = 48;
804
        break;
805
    case MBEDTLS_ECP_DP_SECP521R1:
806
        half_size = 66;
807
        break;
808
    default:
809
        return false;
810
    }
811
    if (*sig_size < (size_t)(half_size * 2)) {
812
        *sig_size = half_size * 2;
813
        return false;
814
    }
815
    *sig_size = half_size * 2;
816
    libspdm_zero_mem(signature, *sig_size);
817
818
    switch (hash_nid) {
819
    case LIBSPDM_CRYPTO_NID_SHA256:
820
        if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
821
            return false;
822
        }
823
        break;
824
825
    case LIBSPDM_CRYPTO_NID_SHA384:
826
        if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
827
            return false;
828
        }
829
        break;
830
831
    case LIBSPDM_CRYPTO_NID_SHA512:
832
        if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
833
            return false;
834
        }
835
        break;
836
837
    case LIBSPDM_CRYPTO_NID_SHA3_256:
838
        if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
839
            return false;
840
        }
841
        break;
842
843
    case LIBSPDM_CRYPTO_NID_SHA3_384:
844
        if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
845
            return false;
846
        }
847
        break;
848
849
    case LIBSPDM_CRYPTO_NID_SHA3_512:
850
        if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
851
            return false;
852
        }
853
        break;
854
855
    default:
856
        return false;
857
    }
858
859
    mbedtls_mpi_init(&bn_r);
860
    mbedtls_mpi_init(&bn_s);
861
862
    /*retrieve random number*/
863
    ret = mbedtls_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &bn_r, &bn_s,
864
                             &ctx->MBEDTLS_PRIVATE(d), message_hash,
865
                             hash_size, random_func, NULL);
866
    if (ret != 0) {
867
        return false;
868
    }
869
870
    r_size = mbedtls_mpi_size(&bn_r);
871
    s_size = mbedtls_mpi_size(&bn_s);
872
    LIBSPDM_ASSERT(r_size <= half_size && s_size <= half_size);
873
874
    ret = mbedtls_mpi_write_binary(
875
        &bn_r, &signature[0 + half_size - r_size], r_size);
876
    if (ret != 0) {
877
        mbedtls_mpi_free(&bn_r);
878
        mbedtls_mpi_free(&bn_s);
879
        return false;
880
    }
881
    ret = mbedtls_mpi_write_binary(
882
        &bn_s, &signature[half_size + half_size - s_size], s_size);
883
    if (ret != 0) {
884
        mbedtls_mpi_free(&bn_r);
885
        mbedtls_mpi_free(&bn_s);
886
        return false;
887
    }
888
889
    mbedtls_mpi_free(&bn_r);
890
    mbedtls_mpi_free(&bn_s);
891
892
    return true;
893
}
894
#endif/*LIBSPDM_FIPS_MODE*/