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/pem/pem.c
Line
Count
Source
1
/**
2
 *  Copyright Notice:
3
 *  Copyright 2021-2024 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
 * PEM (Privacy Enhanced Mail) format Handler Wrapper Implementation.
9
 **/
10
11
#include "internal_crypt_lib.h"
12
#include <mbedtls/pem.h>
13
#include <mbedtls/pk.h>
14
#include <mbedtls/rsa.h>
15
#include <mbedtls/ecp.h>
16
#include <mbedtls/ecdh.h>
17
#include <mbedtls/ecdsa.h>
18
19
static size_t ascii_str_len(const char *string)
20
0
{
21
0
    size_t length;
22
23
0
    LIBSPDM_ASSERT(string != NULL);
24
0
    if (string == NULL) {
25
0
        return 0;
26
0
    }
27
28
0
    for (length = 0; *string != '\0'; string++, length++) {
29
0
        ;
30
0
    }
31
0
    return length;
32
0
}
33
34
#if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
35
/**
36
 * Retrieve the RSA Private key from the password-protected PEM key data.
37
 *
38
 * @param[in]  pem_data      Pointer to the PEM-encoded key data to be retrieved.
39
 * @param[in]  pem_size      size of the PEM key data in bytes.
40
 * @param[in]  password     NULL-terminated passphrase used for encrypted PEM key data.
41
 * @param[out] rsa_context   Pointer to newly generated RSA context which contain the retrieved
42
 *                         RSA private key component. Use libspdm_rsa_free() function to free the
43
 *                         resource.
44
 *
45
 * If pem_data is NULL, then return false.
46
 * If rsa_context is NULL, then return false.
47
 *
48
 * @retval  true   RSA Private key was retrieved successfully.
49
 * @retval  false  Invalid PEM key data or incorrect password.
50
 *
51
 **/
52
bool libspdm_rsa_get_private_key_from_pem(const uint8_t *pem_data,
53
                                          size_t pem_size,
54
                                          const char *password,
55
                                          void **rsa_context)
56
152
{
57
152
    int ret;
58
152
    mbedtls_pk_context pk;
59
152
    mbedtls_rsa_context *rsa;
60
152
    uint8_t *new_pem_data;
61
152
    size_t password_len;
62
63
152
    if (pem_data == NULL || rsa_context == NULL || pem_size > INT_MAX) {
64
0
        return false;
65
0
    }
66
67
152
    new_pem_data = NULL;
68
152
    if (pem_data[pem_size - 1] != 0) {
69
152
        new_pem_data = allocate_pool(pem_size + 1);
70
152
        if (new_pem_data == NULL) {
71
0
            return false;
72
0
        }
73
152
        libspdm_copy_mem(new_pem_data, pem_size + 1, pem_data, pem_size);
74
152
        new_pem_data[pem_size] = 0;
75
152
        pem_data = new_pem_data;
76
152
        pem_size += 1;
77
152
    }
78
79
152
    mbedtls_pk_init(&pk);
80
81
152
    if (password != NULL) {
82
0
        password_len = ascii_str_len(password);
83
152
    } else {
84
152
        password_len = 0;
85
152
    }
86
87
152
    ret = mbedtls_pk_parse_key(&pk, pem_data, pem_size,
88
152
                               (const uint8_t *)password, password_len,
89
152
                               libspdm_myrand, NULL);
90
91
152
    if (new_pem_data != NULL) {
92
152
        free_pool(new_pem_data);
93
152
        new_pem_data = NULL;
94
152
    }
95
96
152
    if (ret != 0) {
97
0
        mbedtls_pk_free(&pk);
98
0
        return false;
99
0
    }
100
101
152
    if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
102
0
        mbedtls_pk_free(&pk);
103
0
        return false;
104
0
    }
105
106
152
    rsa = libspdm_rsa_new();
107
152
    if (rsa == NULL) {
108
0
        return false;
109
0
    }
110
152
    ret = mbedtls_rsa_copy(rsa, mbedtls_pk_rsa(pk));
111
152
    if (ret != 0) {
112
0
        libspdm_rsa_free(rsa);
113
0
        mbedtls_pk_free(&pk);
114
0
        return false;
115
0
    }
116
152
    mbedtls_pk_free(&pk);
117
118
152
    *rsa_context = rsa;
119
152
    return true;
120
152
}
121
#endif /* (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT) */
122
123
/**
124
 * Retrieve the EC Private key from the password-protected PEM key data.
125
 *
126
 * @param[in]  pem_data      Pointer to the PEM-encoded key data to be retrieved.
127
 * @param[in]  pem_size      size of the PEM key data in bytes.
128
 * @param[in]  password     NULL-terminated passphrase used for encrypted PEM key data.
129
 * @param[out] ec_context    Pointer to newly generated EC DSA context which contain the retrieved
130
 *                         EC private key component. Use libspdm_ec_free() function to free the
131
 *                         resource.
132
 *
133
 * If pem_data is NULL, then return false.
134
 * If ec_context is NULL, then return false.
135
 *
136
 * @retval  true   EC Private key was retrieved successfully.
137
 * @retval  false  Invalid PEM key data or incorrect password.
138
 *
139
 **/
140
bool libspdm_ec_get_private_key_from_pem(const uint8_t *pem_data, size_t pem_size,
141
                                         const char *password,
142
                                         void **ec_context)
143
232
{
144
232
    int ret;
145
232
    mbedtls_pk_context pk;
146
232
    mbedtls_ecdh_context *ecdh;
147
232
    uint8_t *new_pem_data;
148
232
    size_t password_len;
149
150
232
    if (pem_data == NULL || ec_context == NULL || pem_size > INT_MAX) {
151
0
        return false;
152
0
    }
153
154
232
    new_pem_data = NULL;
155
232
    if (pem_data[pem_size - 1] != 0) {
156
232
        new_pem_data = allocate_pool(pem_size + 1);
157
232
        if (new_pem_data == NULL) {
158
0
            return false;
159
0
        }
160
232
        libspdm_copy_mem(new_pem_data, pem_size + 1, pem_data, pem_size);
161
232
        new_pem_data[pem_size] = 0;
162
232
        pem_data = new_pem_data;
163
232
        pem_size += 1;
164
232
    }
165
166
232
    mbedtls_pk_init(&pk);
167
168
232
    if (password != NULL) {
169
0
        password_len = ascii_str_len(password);
170
232
    } else {
171
232
        password_len = 0;
172
232
    }
173
174
232
    ret = mbedtls_pk_parse_key(&pk, pem_data, pem_size,
175
232
                               (const uint8_t *)password, password_len,
176
232
                               libspdm_myrand, NULL);
177
178
232
    if (new_pem_data != NULL) {
179
232
        free_pool(new_pem_data);
180
232
        new_pem_data = NULL;
181
232
    }
182
183
232
    if (ret != 0) {
184
0
        mbedtls_pk_free(&pk);
185
0
        return false;
186
0
    }
187
188
232
    if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_ECKEY) {
189
0
        mbedtls_pk_free(&pk);
190
0
        return false;
191
0
    }
192
193
232
    ecdh = allocate_zero_pool(sizeof(mbedtls_ecdh_context));
194
232
    if (ecdh == NULL) {
195
0
        mbedtls_pk_free(&pk);
196
0
        return false;
197
0
    }
198
232
    mbedtls_ecdh_init(ecdh);
199
200
232
    ret = mbedtls_ecdh_get_params(ecdh, mbedtls_pk_ec(pk),
201
232
                                  MBEDTLS_ECDH_OURS);
202
232
    if (ret != 0) {
203
0
        mbedtls_ecdh_free(ecdh);
204
0
        free_pool(ecdh);
205
0
        mbedtls_pk_free(&pk);
206
0
        return false;
207
0
    }
208
232
    mbedtls_pk_free(&pk);
209
210
232
    *ec_context = ecdh;
211
232
    return true;
212
232
}
213
214
/**
215
 * Retrieve the Ed Private key from the password-protected PEM key data.
216
 *
217
 * @param[in]  pem_data      Pointer to the PEM-encoded key data to be retrieved.
218
 * @param[in]  pem_size      size of the PEM key data in bytes.
219
 * @param[in]  password     NULL-terminated passphrase used for encrypted PEM key data.
220
 * @param[out] ecd_context    Pointer to newly generated Ed DSA context which contain the retrieved
221
 *                         Ed private key component. Use libspdm_ecd_free() function to free the
222
 *                         resource.
223
 *
224
 * If pem_data is NULL, then return false.
225
 * If ecd_context is NULL, then return false.
226
 *
227
 * @retval  true   Ed Private key was retrieved successfully.
228
 * @retval  false  Invalid PEM key data or incorrect password.
229
 *
230
 **/
231
bool libspdm_ecd_get_private_key_from_pem(const uint8_t *pem_data,
232
                                          size_t pem_size,
233
                                          const char *password,
234
                                          void **ecd_context)
235
0
{
236
0
    return false;
237
0
}
238
239
/**
240
 * Retrieve the sm2 Private key from the password-protected PEM key data.
241
 *
242
 * @param[in]  pem_data      Pointer to the PEM-encoded key data to be retrieved.
243
 * @param[in]  pem_size      size of the PEM key data in bytes.
244
 * @param[in]  password     NULL-terminated passphrase used for encrypted PEM key data.
245
 * @param[out] sm2_context   Pointer to newly generated sm2 context which contain the retrieved
246
 *                         sm2 private key component. Use sm2_free() function to free the
247
 *                         resource.
248
 *
249
 * If pem_data is NULL, then return false.
250
 * If sm2_context is NULL, then return false.
251
 *
252
 * @retval  true   sm2 Private key was retrieved successfully.
253
 * @retval  false  Invalid PEM key data or incorrect password.
254
 *
255
 **/
256
bool libspdm_sm2_get_private_key_from_pem(const uint8_t *pem_data,
257
                                          size_t pem_size,
258
                                          const char *password,
259
                                          void **sm2_context)
260
0
{
261
    return false;
262
0
}