• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-mcu / 1642556678

27 Jan 2025 01:30PM UTC coverage: 25.749%. First build
1642556678

push

gitlab-ci

vpodzime
feat: Support platform-specific or custom allocators

And use Zephyr-specific allocation functions on Zephyr by
default, using either a separate heap (default) or the system
heap.

This means we have to use our memory management functions instead
of the standard ones everywhere, even if they can actually just
call the standard ones.

Ticket: MEN-7808
Changelog: none
Signed-off-by: Vratislav Podzimek <vratislav.podzimek@northern.tech>

64 of 184 new or added lines in 12 files covered. (34.78%)

731 of 2839 relevant lines covered (25.75%)

8.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/platform/tls/generic/mbedtls/src/mender-tls.c
1
/**
2
 * @file      mender-tls.c
3
 * @brief     Mender TLS interface for mbedTLS platform
4
 *
5
 * Copyright joelguittet and mender-mcu-client contributors
6
 * Copyright Northern.tech AS
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
#include <mbedtls/base64.h>
22
#include <mbedtls/bignum.h>
23
#include <mbedtls/ctr_drbg.h>
24
#include <mbedtls/entropy.h>
25
#ifdef MBEDTLS_ERROR_C
26
#include <mbedtls/error.h>
27
#endif /* MBEDTLS_ERROR_C */
28
#include <mbedtls/pk.h>
29
#include <mbedtls/ecdsa.h>
30
#include <mbedtls/x509.h>
31
#include "mender-alloc.h"
32
#include "mender-log.h"
33
#include "mender-storage.h"
34
#include "mender-tls.h"
35

36
#include "mender-utils.h"
37

38
/**
39
 * @brief Keys buffer length
40
 */
41
#define MENDER_TLS_PRIVATE_KEY_LENGTH (2048)
42
#define MENDER_TLS_PUBLIC_KEY_LENGTH  (768)
43

44
/**
45
 * @brief Signature buffer length (base64 encoded)
46
 * @note base64 produces 4 bytes of output per 3 bytes of input (padded to be
47
 *       divisible), see RFC-4648 or man:EVP_EncodeBlock(3)
48
 */
49
#define MENDER_TLS_SIGNATURE_LENGTH (((MBEDTLS_PK_SIGNATURE_MAX_SIZE + 2) / 3) * 4)
50

51
#ifdef MBEDTLS_ERROR_C
52
#define MBEDTLS_ERR_BUF char err[128]
53

54
/**
55
 * @brief Macro for logging errors coming from mbedtls
56
 * @note  Make sure to declare the buffer using the #MBEDTLS_ERR_BUF macro above
57
 */
58
#define LOG_MBEDTLS_ERROR(msg, ret)                        \
59
    do {                                                   \
60
        mbedtls_strerror(ret, err, sizeof(err));           \
61
        mender_log_error(msg " (-0x%04x: %s)", -ret, err); \
62
    } while (0)
63
#else
64
#define MBEDTLS_ERR_BUF
65
#define LOG_MBEDTLS_ERROR(msg, ret) mender_log_error(msg " (-0x%04x)", -ret)
66
#endif /* MBEDTLS_ERROR_C */
67

68
/**
69
 * @brief Private and public keys of the device
70
 */
71
static unsigned char *mender_tls_private_key        = NULL;
72
static size_t         mender_tls_private_key_length = 0;
73
static unsigned char *mender_tls_public_key         = NULL;
74
static size_t         mender_tls_public_key_length  = 0;
75

76
/**
77
 * @brief Generate authentication keys
78
 * @param pk_context PK context
79
 * @return MENDER_OK if the function succeeds, error code otherwise
80
 */
81
static mender_err_t mender_tls_generate_authentication_keys(mbedtls_pk_context *pk_context);
82

83
/**
84
 * @brief Get user provided authentication keys
85
 * @param pk_context PK context
86
 * @param user_provided_key Buffer of user provided key
87
 * @param user_provided_key_length Length of buffer of user provided key
88
 * @return MENDER_OK if the function succeeds, error code otherwise
89
 */
90
static mender_err_t mender_tls_user_provided_authentication_keys(mbedtls_pk_context *pk_context,
91
                                                                 const char         *user_provided_key,
92
                                                                 size_t              user_provided_key_length);
93

94
/**
95
 * @brief Generate authentication keys
96
 * @param private_key Private key generated
97
 * @param private_key_length Private key length
98
 * @param public_key Public key generated
99
 * @param public_key_length Public key length
100
 * @param user_provided_key Path to user-provided key
101
 * @param user_provided_key_length Length of buffer of user provided key
102
 * @return MENDER_OK if the function succeeds, error code otherwise
103
 */
104
static mender_err_t mender_tls_get_authentication_keys(unsigned char **private_key,
105
                                                       size_t         *private_key_length,
106
                                                       unsigned char **public_key,
107
                                                       size_t         *public_key_length,
108
                                                       const char     *user_provided_key,
109
                                                       size_t          user_provided_key_length);
110

111
/**
112
 * @brief Write a buffer of PEM information from a DER encoded buffer
113
 * @note This function is derived from mbedtls_pem_write_buffer with const header and footer
114
 * @param der_data The DER data to encode
115
 * @param der_len The length of the DER data
116
 * @param buf The buffer to write to
117
 * @param buf_len The length of the output buffer
118
 * @param olen The address at which to store the total length written or required output buffer length is not enough
119
 * @return MENDER_OK if the function succeeds, error code otherwise
120
 */
121
static mender_err_t mender_tls_pem_write_buffer(const unsigned char *der_data, size_t der_len, char *buf, size_t buf_len, size_t *olen);
122

123
mender_err_t
124
mender_tls_init(void) {
×
125

126
    /* Nothing to do */
127
    return MENDER_OK;
×
128
}
129

130
mender_err_t
131
mender_tls_init_authentication_keys(mender_err_t (*get_user_provided_keys)(char **user_provided_key, size_t *user_provided_key_length), bool recommissioning) {
×
132

133
    /* Release memory */
134
    FREE_AND_NULL(mender_tls_private_key);
×
135
    mender_tls_private_key_length = 0;
×
136
    FREE_AND_NULL(mender_tls_public_key);
×
137
    mender_tls_public_key_length = 0;
×
138

139
    /* Check if recommissioning is forced */
140
    if (recommissioning) {
×
141
        /* Erase authentication keys */
142
        mender_log_debug("Deleting authentication keys");
143
        if (MENDER_OK != mender_storage_delete_authentication_keys()) {
×
144
            mender_log_warning("Unable to delete authentication keys");
×
145
        }
146
    }
147

148
    /* Get user provided key (callback is optional) */
149
    if (NULL != get_user_provided_keys) {
×
150
        char  *user_provided_key        = NULL;
×
151
        size_t user_provided_key_length = 0;
×
152

153
        mender_log_debug("Retrieving user provided authentication keys");
154

155
        if (MENDER_OK != get_user_provided_keys(&user_provided_key, &user_provided_key_length)) {
×
156
            mender_log_error("Unable to get user provided authentication key");
×
157
            return MENDER_FAIL;
×
158
        }
159

160
        if ((NULL == user_provided_key) || (0 == user_provided_key_length)) {
×
161
            mender_log_error("User provided authentication key is empty");
×
162
            return MENDER_FAIL;
×
163
        }
164

165
        if (MENDER_OK
×
166
            != mender_tls_get_authentication_keys(&mender_tls_private_key,
×
167
                                                  &mender_tls_private_key_length,
168
                                                  &mender_tls_public_key,
169
                                                  &mender_tls_public_key_length,
170
                                                  user_provided_key,
171
                                                  user_provided_key_length)) {
172
            mender_log_error("Unable to get user provided authentication key");
×
NEW
173
            mender_free(user_provided_key);
×
174
            return MENDER_FAIL;
×
175
        }
176

NEW
177
        mender_free(user_provided_key);
×
178
        return MENDER_OK;
×
179
    }
180

181
    /* Get keys from store */
182
    mender_log_debug("Trying to read authentication keys from store");
183
    switch (mender_storage_get_authentication_keys(
×
184
        &mender_tls_private_key, &mender_tls_private_key_length, &mender_tls_public_key, &mender_tls_public_key_length)) {
185
        case MENDER_OK:
×
186
            /* Keys found! */
187
            return MENDER_OK;
×
188
        case MENDER_NOT_FOUND:
×
189
            mender_log_debug("Authentication keys not found in store");
190
            break;
×
191
        case MENDER_DONE:
×
192
            /* fallthrough */
193
        case MENDER_NOT_IMPLEMENTED:
194
            assert(false && "Unexpected return value");
×
195
            /* fallthrough */
196
        case MENDER_LOOP_DETECTED:
197
            assert(false && "Unexpected return value");
×
198
            /* fallthrough */
199
        case MENDER_LOCK_FAILED:
200
            assert(false && "Unexpected return value");
×
201
            /* fallthrough */
202
        case MENDER_ABORTED:
203
            assert(false && "Unexpected return value");
×
204
            /* fallthrough */
205
        case MENDER_FAIL:
206
            mender_log_error("Unable to get authentication keys from store");
×
207
            return MENDER_FAIL;
×
208
    }
209

210
    /* We failed to get keys from store. Hence, we need to generate them */
211
    mender_log_info("Generating authentication keys");
×
212
    if (MENDER_OK
×
213
        != mender_tls_get_authentication_keys(
×
214
            &mender_tls_private_key, &mender_tls_private_key_length, &mender_tls_public_key, &mender_tls_public_key_length, NULL, 0)) {
215
        mender_log_error("Unable to generate authentication keys");
×
216
        return MENDER_FAIL;
×
217
    }
218

219
    /* Store newly generated keys */
220
    mender_log_debug("Writing authentication keys to store");
221
    if (MENDER_OK
×
222
        != mender_storage_set_authentication_keys(mender_tls_private_key, mender_tls_private_key_length, mender_tls_public_key, mender_tls_public_key_length)) {
×
223
        mender_log_error("Unable to store authentication keys");
×
224
        return MENDER_FAIL;
×
225
    }
226

227
    return MENDER_OK;
×
228
}
229

230
mender_err_t
231
mender_tls_get_public_key_pem(char **public_key) {
×
232

233
    assert(NULL != public_key);
×
234
    mender_err_t ret;
235

236
    /* Compute size of the public key */
237
    size_t olen = 0;
×
238
    mender_tls_pem_write_buffer(mender_tls_public_key, mender_tls_public_key_length, NULL, 0, &olen);
×
239
    if (0 == olen) {
×
240
        mender_log_error("Unable to compute public key size");
×
241
        return MENDER_FAIL;
×
242
    }
NEW
243
    if (NULL == (*public_key = (char *)mender_malloc(olen))) {
×
244
        mender_log_error("Unable to allocate memory");
×
245
        return MENDER_FAIL;
×
246
    }
247

248
    /* Convert public key from DER to PEM format */
249
    if (MENDER_OK != (ret = mender_tls_pem_write_buffer(mender_tls_public_key, mender_tls_public_key_length, *public_key, olen, &olen))) {
×
250
        mender_log_error("Unable to convert public key");
×
251
        return ret;
×
252
    }
253

254
    return MENDER_OK;
×
255
}
256

257
mender_err_t
258
mender_tls_sign_payload(char *payload, char **signature, size_t *signature_length) {
×
259

260
    assert(NULL != payload);
×
261
    assert(NULL != signature);
×
262
    assert(NULL != signature_length);
×
263
    int                       ret;
264
    mbedtls_pk_context       *pk_context = NULL;
×
265
    mbedtls_ctr_drbg_context *ctr_drbg   = NULL;
×
266
    mbedtls_entropy_context  *entropy    = NULL;
×
267
    unsigned char            *sig        = NULL;
×
268
    size_t                    sig_length;
269
    MBEDTLS_ERR_BUF;
270

271
    /* Initialize mbedtls */
NEW
272
    if (NULL == (pk_context = (mbedtls_pk_context *)mender_malloc(sizeof(mbedtls_pk_context)))) {
×
273
        mender_log_error("Unable to allocate memory");
×
274
        ret = -1;
×
275
        goto END;
×
276
    }
277
    mbedtls_pk_init(pk_context);
×
NEW
278
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)mender_malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
279
        mender_log_error("Unable to allocate memory");
×
280
        ret = -1;
×
281
        goto END;
×
282
    }
283
    mbedtls_ctr_drbg_init(ctr_drbg);
×
NEW
284
    if (NULL == (entropy = (mbedtls_entropy_context *)mender_malloc(sizeof(mbedtls_entropy_context)))) {
×
285
        mender_log_error("Unable to allocate memory");
×
286
        ret = -1;
×
287
        goto END;
×
288
    }
289
    mbedtls_entropy_init(entropy);
×
290

291
    /* Setup CRT DRBG */
292
    if (0 != (ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)"mender", strlen("mender")))) {
×
293
        LOG_MBEDTLS_ERROR("Unable to initialize ctr drbg", ret);
×
294
        goto END;
×
295
    }
296

297
    /* Parse private key (IMPORTANT NOTE: length must include the ending \0 character) */
298
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
299
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, mender_tls_private_key, mender_tls_private_key_length, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
300
#else
301
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, mender_tls_private_key, mender_tls_private_key_length, NULL, 0))) {
302
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
303
        LOG_MBEDTLS_ERROR("Unable to parse private key", ret);
×
304
        goto END;
×
305
    }
306

307
    /* Generate digest */
308
    uint8_t digest[32];
309
    if (0 != (ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), (unsigned char *)payload, strlen(payload), digest))) {
×
310
        LOG_MBEDTLS_ERROR("Unable to generate digest", ret);
×
311
        goto END;
×
312
    }
313

314
    /* Compute signature */
NEW
315
    if (NULL == (sig = (unsigned char *)mender_malloc(MBEDTLS_PK_SIGNATURE_MAX_SIZE))) {
×
316
        mender_log_error("Unable to allocate memory");
×
317
        ret = -1;
×
318
        goto END;
×
319
    }
320
    sig_length = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
×
321
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
322
    if (0 != (ret = mbedtls_pk_sign(pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), sig, sig_length, &sig_length, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
323
#else
324
    if (0 != (ret = mbedtls_pk_sign(pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), sig, &sig_length, mbedtls_ctr_drbg_random, ctr_drbg))) {
325
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
326
        LOG_MBEDTLS_ERROR("Unable to compute signature", ret);
×
327
        goto END;
×
328
    }
329

330
    /* Encode signature to base64 (1 extra byte for the NUL character) */
NEW
331
    if (NULL == (*signature = (char *)mender_malloc(MENDER_TLS_SIGNATURE_LENGTH + 1))) {
×
332
        mender_log_error("Unable to allocate memory");
×
333
        ret = -1;
×
334
        goto END;
×
335
    }
336
    *signature_length = MENDER_TLS_SIGNATURE_LENGTH + 1;
×
337
    if (0 != (ret = mbedtls_base64_encode((unsigned char *)*signature, *signature_length, signature_length, sig, sig_length))) {
×
338
        LOG_MBEDTLS_ERROR("Unable to encode signature", ret);
×
339
        if (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL == ret) {
×
340
            mender_log_error("This is a bug, please report it");
×
341
        }
342
        FREE_AND_NULL(*signature);
×
343
        *signature_length = 0;
×
344
        goto END;
×
345
    }
346

347
END:
×
348

349
    /* Release mbedtls */
350
    mbedtls_entropy_free(entropy);
×
NEW
351
    mender_free(entropy);
×
352
    mbedtls_ctr_drbg_free(ctr_drbg);
×
NEW
353
    mender_free(ctr_drbg);
×
354
    mbedtls_pk_free(pk_context);
×
NEW
355
    mender_free(pk_context);
×
356

357
    /* Release memory */
NEW
358
    mender_free(sig);
×
359

360
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
361
}
362

363
mender_err_t
364
mender_tls_exit(void) {
×
365

366
    /* Release memory */
367
    FREE_AND_NULL(mender_tls_private_key);
×
368
    mender_tls_private_key_length = 0;
×
369
    FREE_AND_NULL(mender_tls_public_key);
×
370
    mender_tls_public_key_length = 0;
×
371

372
    return MENDER_OK;
×
373
}
374

375
static mender_err_t
376
mender_tls_generate_authentication_keys(mbedtls_pk_context *pk_context) {
×
377

378
    mbedtls_ctr_drbg_context     *ctr_drbg   = NULL;
×
379
    mbedtls_entropy_context      *entropy    = NULL;
×
380
    const mbedtls_ecp_curve_info *curve_info = NULL;
×
381
    int                           ret;
382
    MBEDTLS_ERR_BUF;
383

NEW
384
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)mender_malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
385
        mender_log_error("Unable to allocate memory");
×
386
        ret = -1;
×
387
        goto END;
×
388
    }
389
    mbedtls_ctr_drbg_init(ctr_drbg);
×
NEW
390
    if (NULL == (entropy = (mbedtls_entropy_context *)mender_malloc(sizeof(mbedtls_entropy_context)))) {
×
391
        mender_log_error("Unable to allocate memory");
×
392
        ret = -1;
×
393
        goto END;
×
394
    }
395
    mbedtls_entropy_init(entropy);
×
396

397
    /* Setup CRT DRBG */
398
    if (0 != (ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)"mender", strlen("mender")))) {
×
399
        LOG_MBEDTLS_ERROR("Unable to initialize ctr drbg", ret);
×
400
        goto END;
×
401
    }
402

403
    /* PK setup */
404
    if (0 != (ret = mbedtls_pk_setup(pk_context, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)))) {
×
405
        LOG_MBEDTLS_ERROR("Unable to setup pk", ret);
×
406
        goto END;
×
407
    }
408

409
    /* Find a supported curve */
410
    for (curve_info = mbedtls_ecp_curve_list(); MBEDTLS_ECP_DP_NONE != curve_info->grp_id; curve_info++) {
×
411
        if (1 == mbedtls_ecdsa_can_do(curve_info->grp_id)) {
×
412
            mender_log_debug("Found supported ECDSA curve: %s", curve_info->name);
413
            break;
×
414
        }
415
    }
416
    if (MBEDTLS_ECP_DP_NONE == curve_info->grp_id) {
×
417
        mender_log_error("Unable to find a ECDSA valid curve");
×
418
        goto END;
×
419
    }
420

421
    /* Generate key pair */
422
    if (0 != (ret = mbedtls_ecdsa_genkey(mbedtls_pk_ec(*pk_context), curve_info->grp_id, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
423
        LOG_MBEDTLS_ERROR("Unable to generate key", ret);
×
424
        goto END;
×
425
    }
426

427
END:
×
428
    /* Release mbedtls */
429
    mbedtls_entropy_free(entropy);
×
NEW
430
    mender_free(entropy);
×
431
    mbedtls_ctr_drbg_free(ctr_drbg);
×
NEW
432
    mender_free(ctr_drbg);
×
433

434
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
435
}
436

437
static mender_err_t
438
mender_tls_user_provided_authentication_keys(mbedtls_pk_context *pk_context, const char *user_provided_key, size_t user_provided_key_length) {
×
439

440
    assert(NULL != user_provided_key);
×
441
    assert(0 != user_provided_key_length);
×
442

443
    mbedtls_ctr_drbg_context *ctr_drbg = NULL;
×
444
    mbedtls_entropy_context  *entropy  = NULL;
×
445
    int                       ret;
446
    MBEDTLS_ERR_BUF;
447

NEW
448
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)mender_malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
449
        mender_log_error("Unable to allocate memory");
×
450
        ret = -1;
×
451
        goto END;
×
452
    }
453
    mbedtls_ctr_drbg_init(ctr_drbg);
×
NEW
454
    if (NULL == (entropy = (mbedtls_entropy_context *)mender_malloc(sizeof(mbedtls_entropy_context)))) {
×
455
        mender_log_error("Unable to allocate memory");
×
456
        ret = -1;
×
457
        goto END;
×
458
    }
459
    mbedtls_entropy_init(entropy);
×
460

461
    /* Setup CRT DRBG */
462
    if (0 != (ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)"mender", strlen("mender")))) {
×
463
        LOG_MBEDTLS_ERROR("Unable to initialize ctr drbg", ret);
×
464
        goto END;
×
465
    }
466

467
    /* Load and parse the private key buffer */
468
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
469
    if (0
×
470
        != (ret = mbedtls_pk_parse_key(
×
471
                pk_context, (const unsigned char *)user_provided_key, user_provided_key_length, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg))) {
472
#else
473
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, (const unsigned char *)user_provided_key, user_provided_key_length, NULL, 0))) {
474
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
475
        LOG_MBEDTLS_ERROR("Unable to parse private key", ret);
×
476
        goto END;
×
477
    }
478

479
END:
×
480
    /* Release mbedtls */
481
    mbedtls_entropy_free(entropy);
×
NEW
482
    mender_free(entropy);
×
483
    mbedtls_ctr_drbg_free(ctr_drbg);
×
NEW
484
    mender_free(ctr_drbg);
×
485

486
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
487
}
488

489
static mender_err_t
490
mender_tls_get_authentication_keys(unsigned char **private_key,
×
491
                                   size_t         *private_key_length,
492
                                   unsigned char **public_key,
493
                                   size_t         *public_key_length,
494
                                   const char     *user_provided_key,
495
                                   size_t          user_provided_key_length) {
496

497
    assert(NULL != private_key);
×
498
    assert(NULL != private_key_length);
×
499
    assert(NULL != public_key);
×
500
    assert(NULL != public_key_length);
×
501

502
    int                 ret;
503
    mbedtls_pk_context *pk_context = NULL;
×
504
    unsigned char      *tmp;
505
    MBEDTLS_ERR_BUF;
506

507
    /* Initialize mbedtls */
NEW
508
    if (NULL == (pk_context = (mbedtls_pk_context *)mender_malloc(sizeof(mbedtls_pk_context)))) {
×
509
        mender_log_error("Unable to allocate memory");
×
510
        ret = -1;
×
511
        goto END;
×
512
    }
513
    mbedtls_pk_init(pk_context);
×
514
    /* Get user provided key, else generate key  */
515
    if (NULL != user_provided_key) {
×
516
        if (MENDER_OK != mender_tls_user_provided_authentication_keys(pk_context, user_provided_key, user_provided_key_length)) {
×
517
            ret = -1;
×
518
            goto END;
×
519
        }
520
    } else {
521
        /* Generate key */
522
        if (MENDER_OK != mender_tls_generate_authentication_keys(pk_context)) {
×
523
            ret = -1;
×
524
            goto END;
×
525
        }
526
    }
527

528
    /* Export private key */
NEW
529
    if (NULL == (*private_key = (unsigned char *)mender_malloc(MENDER_TLS_PRIVATE_KEY_LENGTH))) {
×
530
        mender_log_error("Unable to allocate memory");
×
531
        ret = -1;
×
532
        goto END;
×
533
    }
534
    if ((ret = mbedtls_pk_write_key_der(pk_context, *private_key, MENDER_TLS_PRIVATE_KEY_LENGTH)) < 0) {
×
535
        LOG_MBEDTLS_ERROR("Unable to write private key to PEM format", ret);
×
536
        FREE_AND_NULL(*private_key);
×
537
        goto END;
×
538
    }
539
    *private_key_length = (size_t)ret;
×
540
    memcpy(*private_key, *private_key + MENDER_TLS_PRIVATE_KEY_LENGTH - *private_key_length, *private_key_length);
×
NEW
541
    if (NULL == (tmp = mender_realloc(*private_key, *private_key_length))) {
×
542
        mender_log_error("Unable to allocate memory");
×
543
        FREE_AND_NULL(*private_key);
×
544
        ret = -1;
×
545
        goto END;
×
546
    }
547
    *private_key = tmp;
×
548

549
    /* Export public key */
NEW
550
    if (NULL == (*public_key = (unsigned char *)mender_malloc(MENDER_TLS_PUBLIC_KEY_LENGTH))) {
×
551
        mender_log_error("Unable to allocate memory");
×
552
        FREE_AND_NULL(*private_key);
×
553
        ret = -1;
×
554
        goto END;
×
555
    }
556
    if ((ret = mbedtls_pk_write_pubkey_der(pk_context, *public_key, MENDER_TLS_PUBLIC_KEY_LENGTH)) < 0) {
×
557
        LOG_MBEDTLS_ERROR("Unable to write public key to PEM format", ret);
×
558
        FREE_AND_NULL(*private_key);
×
559
        FREE_AND_NULL(*public_key);
×
560
        goto END;
×
561
    }
562
    *public_key_length = (size_t)ret;
×
563
    memcpy(*public_key, *public_key + MENDER_TLS_PUBLIC_KEY_LENGTH - *public_key_length, *public_key_length);
×
NEW
564
    if (NULL == (tmp = mender_realloc(*public_key, *public_key_length))) {
×
565
        mender_log_error("Unable to allocate memory");
×
566
        FREE_AND_NULL(*private_key);
×
567
        FREE_AND_NULL(*public_key);
×
568
        ret = -1;
×
569
        goto END;
×
570
    }
571
    *public_key = tmp;
×
572
    ret         = 0;
×
573

574
END:
×
575

576
    /* Release mbedtls */
577
    mbedtls_pk_free(pk_context);
×
NEW
578
    mender_free(pk_context);
×
579

580
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
581
}
582

583
static mender_err_t
584
mender_tls_pem_write_buffer(const unsigned char *der_data, size_t der_len, char *buf, size_t buf_len, size_t *olen) {
×
585

586
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----"
587
#define PEM_END_PUBLIC_KEY   "-----END PUBLIC KEY-----"
588

589
    mender_err_t   ret        = MENDER_OK;
×
590
    unsigned char *encode_buf = NULL;
×
591
    unsigned char *p          = (unsigned char *)buf;
×
592

593
    /* Compute length required to convert DER data */
594
    size_t use_len = 0;
×
595
    mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
×
596
    if (0 == use_len) {
×
597
        mender_log_error("Unable to compute length");
×
598
        ret = MENDER_FAIL;
×
599
        goto END;
×
600
    }
601

602
    /* Compute length required to format PEM */
603
    size_t add_len = strlen(PEM_BEGIN_PUBLIC_KEY) + 1 + strlen(PEM_END_PUBLIC_KEY) + ((use_len / 64) + 1);
×
604

605
    /* Check buffer length */
606
    if (use_len + add_len > buf_len) {
×
607
        *olen = use_len + add_len;
×
608
        ret   = MENDER_FAIL;
×
609
        goto END;
×
610
    }
611

612
    /* Check buffer */
613
    if (NULL == p) {
×
614
        ret = MENDER_FAIL;
×
615
        goto END;
×
616
    }
617

618
    /* Allocate memory to store PEM data */
NEW
619
    if (NULL == (encode_buf = (unsigned char *)mender_malloc(use_len))) {
×
620
        mender_log_error("Unable to allocate memory");
×
621
        ret = MENDER_FAIL;
×
622
        goto END;
×
623
    }
624

625
    /* Convert DER data */
626
    if (0 != mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data, der_len)) {
×
627
        mender_log_error("Unable to convert data to base64 format");
×
628
        ret = MENDER_FAIL;
×
629
        goto END;
×
630
    }
631

632
    /* Copy header */
633
    memcpy(p, PEM_BEGIN_PUBLIC_KEY, strlen(PEM_BEGIN_PUBLIC_KEY));
×
634
    p += strlen(PEM_BEGIN_PUBLIC_KEY);
×
635
    *p++ = '\n';
×
636

637
    /* Copy PEM data */
638
    unsigned char *c = encode_buf;
×
639
    while (use_len) {
×
640
        size_t len = (use_len > 64) ? 64 : use_len;
×
641
        memcpy(p, c, len);
×
642
        use_len -= len;
×
643
        p += len;
×
644
        c += len;
×
645
        *p++ = '\n';
×
646
    }
647

648
    /* Copy footer */
649
    memcpy(p, PEM_END_PUBLIC_KEY, strlen(PEM_END_PUBLIC_KEY));
×
650
    p += strlen(PEM_END_PUBLIC_KEY);
×
651
    *p++ = '\0';
×
652

653
    /* Compute output length */
654
    *olen = p - (unsigned char *)buf;
×
655

656
    /* Clean any remaining data previously written to the buffer */
657
    memset(buf + *olen, 0, buf_len - *olen);
×
658

659
END:
×
660

661
    /* Release memory */
NEW
662
    mender_free(encode_buf);
×
663

664
    return ret;
×
665
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc