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

mendersoftware / mender-mcu / 1565508264

29 Nov 2024 09:16AM UTC coverage: 9.235% (-0.2%) from 9.39%
1565508264

push

gitlab-ci

danielskinstad
fix: fail deployment when it's aborted

Changelog: Title
Ticket: MEN-7693

Signed-off-by: Daniel Skinstad Drabitzius <daniel.drabitzius@northern.tech>

0 of 11 new or added lines in 3 files covered. (0.0%)

420 existing lines in 2 files now uncovered.

251 of 2718 relevant lines covered (9.23%)

0.66 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-log.h"
32
#include "mender-storage.h"
33
#include "mender-tls.h"
34

35
#include "mender-utils.h"
36

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

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

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

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

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

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

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

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

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

122
mender_err_t
123
mender_tls_init(void) {
×
124

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

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

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

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

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

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

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

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

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

176
        free(user_provided_key);
×
177
        return MENDER_OK;
×
178
    }
179

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

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

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

226
    return MENDER_OK;
×
227
}
228

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

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

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

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

253
    return MENDER_OK;
×
254
}
255

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

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

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

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

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

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

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

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

346
END:
×
347

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

356
    /* Release memory */
357
    free(sig);
×
358

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

362
mender_err_t
363
mender_tls_exit(void) {
×
364

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

371
    return MENDER_OK;
×
372
}
373

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

573
END:
×
574

575
    /* Release mbedtls */
576
    mbedtls_pk_free(pk_context);
×
577
    free(pk_context);
×
578

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

658
END:
×
659

660
    /* Release memory */
661
    free(encode_buf);
×
662

663
    return ret;
×
664
}
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