Coverage Report

Created: 2025-07-11 06:57

/src/openssl/providers/implementations/ciphers/ciphercommon_ccm.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
11
/* Dispatch functions for ccm mode */
12
13
#include <openssl/proverr.h>
14
#include "prov/ciphercommon.h"
15
#include "prov/ciphercommon_ccm.h"
16
#include "prov/providercommon.h"
17
18
19
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
20
                               size_t *padlen, const unsigned char *in,
21
                               size_t len);
22
23
static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen)
24
0
{
25
0
    size_t len;
26
27
0
    if (!ossl_prov_is_running() || alen != EVP_AEAD_TLS1_AAD_LEN)
28
0
        return 0;
29
30
    /* Save the aad for later use. */
31
0
    memcpy(ctx->buf, aad, alen);
32
0
    ctx->tls_aad_len = alen;
33
34
0
    len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1];
35
0
    if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
36
0
        return 0;
37
38
    /* Correct length for explicit iv. */
39
0
    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
40
41
0
    if (!ctx->enc) {
42
0
        if (len < ctx->m)
43
0
            return 0;
44
        /* Correct length for tag. */
45
0
        len -= ctx->m;
46
0
    }
47
0
    ctx->buf[alen - 2] = (unsigned char)(len >> 8);
48
0
    ctx->buf[alen - 1] = (unsigned char)(len & 0xff);
49
50
    /* Extra padding: tag appended to record. */
51
0
    return (int)ctx->m;
52
0
}
53
54
static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed,
55
                                size_t flen)
56
0
{
57
0
    if (flen != EVP_CCM_TLS_FIXED_IV_LEN)
58
0
        return 0;
59
60
    /* Copy to first part of the iv. */
61
0
    memcpy(ctx->iv, fixed, flen);
62
0
    return 1;
63
0
}
64
65
static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx)
66
0
{
67
0
    return 15 - ctx->l;
68
0
}
69
70
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
71
#ifndef ossl_cipher_ccm_set_ctx_params_list
72
static const OSSL_PARAM ossl_cipher_ccm_set_ctx_params_list[] = {
73
    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
74
    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
75
    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
76
    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0),
77
    OSSL_PARAM_END
78
};
79
#endif
80
81
#ifndef ossl_cipher_ccm_set_ctx_params_st
82
struct ossl_cipher_ccm_set_ctx_params_st {
83
    OSSL_PARAM *aad;
84
    OSSL_PARAM *fixed;
85
    OSSL_PARAM *ivlen;
86
    OSSL_PARAM *tag;
87
};
88
#endif
89
90
#ifndef ossl_cipher_ccm_set_ctx_params_decoder
91
static struct ossl_cipher_ccm_set_ctx_params_st
92
0
ossl_cipher_ccm_set_ctx_params_decoder(const OSSL_PARAM params[]) {
93
0
    struct ossl_cipher_ccm_set_ctx_params_st r;
94
0
    const OSSL_PARAM *p;
95
0
    const char *s;
96
97
0
    memset(&r, 0, sizeof(r));
98
0
    for (p = params; (s = p->key) != NULL; p++)
99
0
        switch(s[0]) {
100
0
        default:
101
0
            break;
102
0
        case 'i':
103
0
            if (ossl_likely(r.ivlen == NULL && strcmp("vlen", s + 1) == 0))
104
0
                r.ivlen = (OSSL_PARAM *)p;
105
0
            break;
106
0
        case 't':
107
0
            switch(s[1]) {
108
0
            default:
109
0
                break;
110
0
            case 'a':
111
0
                if (ossl_likely(r.tag == NULL && strcmp("g", s + 2) == 0))
112
0
                    r.tag = (OSSL_PARAM *)p;
113
0
                break;
114
0
            case 'l':
115
0
                switch(s[2]) {
116
0
                default:
117
0
                    break;
118
0
                case 's':
119
0
                    switch(s[3]) {
120
0
                    default:
121
0
                        break;
122
0
                    case 'a':
123
0
                        if (ossl_likely(r.aad == NULL && strcmp("ad", s + 4) == 0))
124
0
                            r.aad = (OSSL_PARAM *)p;
125
0
                        break;
126
0
                    case 'i':
127
0
                        if (ossl_likely(r.fixed == NULL && strcmp("vfixed", s + 4) == 0))
128
0
                            r.fixed = (OSSL_PARAM *)p;
129
0
                    }
130
0
                }
131
0
            }
132
0
        }
133
0
    return r;
134
0
}
135
#endif
136
/* End of machine generated */
137
138
const OSSL_PARAM *ossl_ccm_settable_ctx_params(
139
        ossl_unused void *cctx, ossl_unused void *provctx
140
    )
141
0
{
142
0
    return ossl_cipher_ccm_set_ctx_params_list;
143
0
}
144
145
int ossl_ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
146
0
{
147
0
    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
148
0
    size_t sz, ivlen;
149
0
    struct ossl_cipher_ccm_set_ctx_params_st p;
150
151
0
    if (ossl_param_is_empty(params))
152
0
        return 1;
153
154
0
    p = ossl_cipher_ccm_set_ctx_params_decoder(params);
155
156
0
    if (p.tag != NULL) {
157
0
        if (p.tag->data_type != OSSL_PARAM_OCTET_STRING) {
158
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
159
0
            return 0;
160
0
        }
161
0
        if ((p.tag->data_size & 1) || (p.tag->data_size < 4) || p.tag->data_size > 16) {
162
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
163
0
            return 0;
164
0
        }
165
166
0
        if (p.tag->data != NULL) {
167
0
            if (ctx->enc) {
168
0
                ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
169
0
                return 0;
170
0
            }
171
0
            memcpy(ctx->buf, p.tag->data, p.tag->data_size);
172
0
            ctx->tag_set = 1;
173
0
        }
174
0
        ctx->m = p.tag->data_size;
175
0
    }
176
177
0
    if (p.ivlen != NULL) {
178
0
        if (!OSSL_PARAM_get_size_t(p.ivlen, &sz)) {
179
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
180
0
            return 0;
181
0
        }
182
0
        ivlen = 15 - sz;
183
0
        if (ivlen < 2 || ivlen > 8) {
184
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
185
0
            return 0;
186
0
        }
187
0
        if (ctx->l != ivlen) {
188
0
            ctx->l = ivlen;
189
0
            ctx->iv_set = 0;
190
0
        }
191
0
    }
192
193
0
    if (p.aad != NULL) {
194
0
        if (p.aad->data_type != OSSL_PARAM_OCTET_STRING) {
195
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
196
0
            return 0;
197
0
        }
198
0
        sz = ccm_tls_init(ctx, p.aad->data, p.aad->data_size);
199
0
        if (sz == 0) {
200
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
201
0
            return 0;
202
0
        }
203
0
        ctx->tls_aad_pad_sz = sz;
204
0
    }
205
206
0
    if (p.fixed != NULL) {
207
0
        if (p.fixed->data_type != OSSL_PARAM_OCTET_STRING) {
208
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
209
0
            return 0;
210
0
        }
211
0
        if (ccm_tls_iv_set_fixed(ctx, p.fixed->data, p.fixed->data_size) == 0) {
212
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
213
0
            return 0;
214
0
        }
215
0
    }
216
0
    return 1;
217
0
}
218
219
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
220
#ifndef ossl_cipher_ccm_get_ctx_params_list
221
static const OSSL_PARAM ossl_cipher_ccm_get_ctx_params_list[] = {
222
    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
223
    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
224
    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
225
    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
226
    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
227
    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
228
    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
229
    OSSL_PARAM_END
230
};
231
#endif
232
233
#ifndef ossl_cipher_ccm_get_ctx_params_st
234
struct ossl_cipher_ccm_get_ctx_params_st {
235
    OSSL_PARAM *iv;
236
    OSSL_PARAM *ivlen;
237
    OSSL_PARAM *keylen;
238
    OSSL_PARAM *pad;
239
    OSSL_PARAM *tag;
240
    OSSL_PARAM *taglen;
241
    OSSL_PARAM *updiv;
242
};
243
#endif
244
245
#ifndef ossl_cipher_ccm_get_ctx_params_decoder
246
static struct ossl_cipher_ccm_get_ctx_params_st
247
0
ossl_cipher_ccm_get_ctx_params_decoder(const OSSL_PARAM params[]) {
248
0
    struct ossl_cipher_ccm_get_ctx_params_st r;
249
0
    const OSSL_PARAM *p;
250
0
    const char *s;
251
252
0
    memset(&r, 0, sizeof(r));
253
0
    for (p = params; (s = p->key) != NULL; p++)
254
0
        switch(s[0]) {
255
0
        default:
256
0
            break;
257
0
        case 'i':
258
0
            switch(s[1]) {
259
0
            default:
260
0
                break;
261
0
            case 'v':
262
0
                switch(s[2]) {
263
0
                default:
264
0
                    break;
265
0
                case 'l':
266
0
                    if (ossl_likely(r.ivlen == NULL && strcmp("en", s + 3) == 0))
267
0
                        r.ivlen = (OSSL_PARAM *)p;
268
0
                    break;
269
0
                case '\0':
270
0
                    r.iv = ossl_likely(r.iv == NULL) ? (OSSL_PARAM *)p : r.iv;
271
0
                }
272
0
            }
273
0
            break;
274
0
        case 'k':
275
0
            if (ossl_likely(r.keylen == NULL && strcmp("eylen", s + 1) == 0))
276
0
                r.keylen = (OSSL_PARAM *)p;
277
0
            break;
278
0
        case 't':
279
0
            switch(s[1]) {
280
0
            default:
281
0
                break;
282
0
            case 'a':
283
0
                switch(s[2]) {
284
0
                default:
285
0
                    break;
286
0
                case 'g':
287
0
                    switch(s[3]) {
288
0
                    default:
289
0
                        break;
290
0
                    case 'l':
291
0
                        if (ossl_likely(r.taglen == NULL && strcmp("en", s + 4) == 0))
292
0
                            r.taglen = (OSSL_PARAM *)p;
293
0
                        break;
294
0
                    case '\0':
295
0
                        r.tag = ossl_likely(r.tag == NULL) ? (OSSL_PARAM *)p : r.tag;
296
0
                    }
297
0
                }
298
0
                break;
299
0
            case 'l':
300
0
                if (ossl_likely(r.pad == NULL && strcmp("saadpad", s + 2) == 0))
301
0
                    r.pad = (OSSL_PARAM *)p;
302
0
            }
303
0
            break;
304
0
        case 'u':
305
0
            if (ossl_likely(r.updiv == NULL && strcmp("pdated-iv", s + 1) == 0))
306
0
                r.updiv = (OSSL_PARAM *)p;
307
0
        }
308
0
    return r;
309
0
}
310
#endif
311
/* End of machine generated */
312
313
const OSSL_PARAM *ossl_ccm_gettable_ctx_params(
314
        ossl_unused void *cctx, ossl_unused void *provctx
315
    )
316
112
{
317
112
    return ossl_cipher_ccm_get_ctx_params_list;
318
112
}
319
320
int ossl_ccm_get_ctx_params(void *vctx, OSSL_PARAM params[])
321
0
{
322
0
    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
323
0
    struct ossl_cipher_ccm_get_ctx_params_st p;
324
325
0
    p = ossl_cipher_ccm_get_ctx_params_decoder(params);
326
327
0
    if (p.ivlen != NULL && !OSSL_PARAM_set_size_t(p.ivlen, ccm_get_ivlen(ctx))) {
328
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
329
0
        return 0;
330
0
    }
331
332
0
    if (p.taglen != NULL && !OSSL_PARAM_set_size_t(p.taglen, ctx->m)) {
333
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
334
0
        return 0;
335
0
    }
336
337
0
    if (p.iv != NULL) {
338
0
        if (ccm_get_ivlen(ctx) > p.iv->data_size) {
339
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
340
0
            return 0;
341
0
        }
342
0
        if (!OSSL_PARAM_set_octet_string_or_ptr(p.iv, ctx->iv, p.iv->data_size)) {
343
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
344
0
            return 0;
345
0
        }
346
0
    }
347
348
0
    if (p.updiv != NULL) {
349
0
        if (ccm_get_ivlen(ctx) > p.updiv->data_size) {
350
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
351
0
            return 0;
352
0
        }
353
0
        if (!OSSL_PARAM_set_octet_string_or_ptr(p.updiv, ctx->iv, p.updiv->data_size)) {
354
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
355
0
            return 0;
356
0
        }
357
0
    }
358
359
0
    if (p.keylen != NULL && !OSSL_PARAM_set_size_t(p.keylen, ctx->keylen)) {
360
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
361
0
        return 0;
362
0
    }
363
364
0
    if (p.pad != NULL && !OSSL_PARAM_set_size_t(p.pad, ctx->tls_aad_pad_sz)) {
365
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
366
0
        return 0;
367
0
    }
368
369
0
    if (p.tag != NULL) {
370
0
        if (!ctx->enc || !ctx->tag_set) {
371
0
            ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET);
372
0
            return 0;
373
0
        }
374
0
        if (p.tag->data_type != OSSL_PARAM_OCTET_STRING) {
375
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
376
0
            return 0;
377
0
        }
378
0
        if (!ctx->hw->gettag(ctx, p.tag->data, p.tag->data_size))
379
0
            return 0;
380
0
        ctx->tag_set = 0;
381
0
        ctx->iv_set = 0;
382
0
        ctx->len_set = 0;
383
0
    }
384
385
0
    return 1;
386
0
}
387
388
static int ccm_init(void *vctx, const unsigned char *key, size_t keylen,
389
                    const unsigned char *iv, size_t ivlen,
390
                    const OSSL_PARAM params[], int enc)
391
0
{
392
0
    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
393
394
0
    if (!ossl_prov_is_running())
395
0
        return 0;
396
397
0
    ctx->enc = enc;
398
399
0
    if (iv != NULL) {
400
0
        if (ivlen != ccm_get_ivlen(ctx)) {
401
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
402
0
            return 0;
403
0
        }
404
0
        memcpy(ctx->iv, iv, ivlen);
405
0
        ctx->iv_set = 1;
406
0
    }
407
0
    if (key != NULL) {
408
0
        if (keylen != ctx->keylen) {
409
0
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
410
0
            return 0;
411
0
        }
412
0
        if (!ctx->hw->setkey(ctx, key, keylen))
413
0
            return 0;
414
0
    }
415
0
    return ossl_ccm_set_ctx_params(ctx, params);
416
0
}
417
418
int ossl_ccm_einit(void *vctx, const unsigned char *key, size_t keylen,
419
                   const unsigned char *iv, size_t ivlen,
420
                   const OSSL_PARAM params[])
421
0
{
422
0
    return ccm_init(vctx, key, keylen, iv, ivlen, params, 1);
423
0
}
424
425
int ossl_ccm_dinit(void *vctx, const unsigned char *key, size_t keylen,
426
                   const unsigned char *iv, size_t ivlen,
427
                   const OSSL_PARAM params[])
428
0
{
429
0
    return ccm_init(vctx, key, keylen, iv, ivlen, params, 0);
430
0
}
431
432
int ossl_ccm_stream_update(void *vctx, unsigned char *out, size_t *outl,
433
                           size_t outsize, const unsigned char *in,
434
                           size_t inl)
435
0
{
436
0
    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
437
438
0
    if (outsize < inl) {
439
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
440
0
        return 0;
441
0
    }
442
443
0
    if (!ccm_cipher_internal(ctx, out, outl, in, inl)) {
444
0
        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
445
0
        return 0;
446
0
    }
447
0
    return 1;
448
0
}
449
450
int ossl_ccm_stream_final(void *vctx, unsigned char *out, size_t *outl,
451
                          size_t outsize)
452
0
{
453
0
    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
454
0
    int i;
455
456
0
    if (!ossl_prov_is_running())
457
0
        return 0;
458
459
0
    i = ccm_cipher_internal(ctx, out, outl, NULL, 0);
460
0
    if (i <= 0)
461
0
        return 0;
462
463
0
    *outl = 0;
464
0
    return 1;
465
0
}
466
467
int ossl_ccm_cipher(void *vctx, unsigned char *out, size_t *outl, size_t outsize,
468
                    const unsigned char *in, size_t inl)
469
0
{
470
0
    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
471
472
0
    if (!ossl_prov_is_running())
473
0
        return 0;
474
475
0
    if (outsize < inl) {
476
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
477
0
        return 0;
478
0
    }
479
480
0
    if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0)
481
0
        return 0;
482
483
0
    *outl = inl;
484
0
    return 1;
485
0
}
486
487
/* Copy the buffered iv */
488
static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen)
489
0
{
490
0
    const PROV_CCM_HW *hw = ctx->hw;
491
492
0
    if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen))
493
0
        return 0;
494
0
    ctx->len_set = 1;
495
0
    return 1;
496
0
}
497
498
static int ccm_tls_cipher(PROV_CCM_CTX *ctx,
499
                          unsigned char *out, size_t *padlen,
500
                          const unsigned char *in, size_t len)
501
0
{
502
0
    int rv = 0;
503
0
    size_t olen = 0;
504
505
0
    if (!ossl_prov_is_running())
506
0
        goto err;
507
508
    /* Encrypt/decrypt must be performed in place */
509
0
    if (in == NULL || out != in || len < EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m)
510
0
        goto err;
511
512
    /* If encrypting set explicit IV from sequence number (start of AAD) */
513
0
    if (ctx->enc)
514
0
        memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
515
    /* Get rest of IV from explicit IV */
516
0
    memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
517
    /* Correct length value */
518
0
    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
519
0
    if (!ccm_set_iv(ctx, len))
520
0
        goto err;
521
522
    /* Use saved AAD */
523
0
    if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len))
524
0
        goto err;
525
526
    /* Fix buffer to point to payload */
527
0
    in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
528
0
    out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
529
0
    if (ctx->enc) {
530
0
        if (!ctx->hw->auth_encrypt(ctx, in, out, len,  out + len, ctx->m))
531
0
            goto err;
532
0
        olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
533
0
    } else {
534
0
        if (!ctx->hw->auth_decrypt(ctx, in, out, len,
535
0
                                   (unsigned char *)in + len, ctx->m))
536
0
            goto err;
537
0
        olen = len;
538
0
    }
539
0
    rv = 1;
540
0
err:
541
0
    *padlen = olen;
542
0
    return rv;
543
0
}
544
545
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
546
                               size_t *padlen, const unsigned char *in,
547
                               size_t len)
548
0
{
549
0
    int rv = 0;
550
0
    size_t olen = 0;
551
0
    const PROV_CCM_HW *hw = ctx->hw;
552
553
    /* If no key set, return error */
554
0
    if (!ctx->key_set)
555
0
        return 0;
556
557
0
    if (ctx->tls_aad_len != UNINITIALISED_SIZET)
558
0
        return ccm_tls_cipher(ctx, out, padlen, in, len);
559
560
    /* EVP_*Final() doesn't return any data */
561
0
    if (in == NULL && out != NULL)
562
0
        goto finish;
563
564
0
    if (!ctx->iv_set)
565
0
        goto err;
566
567
0
    if (out == NULL) {
568
0
        if (in == NULL) {
569
0
            if (!ccm_set_iv(ctx, len))
570
0
                goto err;
571
0
        } else {
572
            /* If we have AAD, we need a message length */
573
0
            if (!ctx->len_set && len)
574
0
                goto err;
575
0
            if (!hw->setaad(ctx, in, len))
576
0
                goto err;
577
0
        }
578
0
    } else {
579
        /* If not set length yet do it */
580
0
        if (!ctx->len_set && !ccm_set_iv(ctx, len))
581
0
            goto err;
582
583
0
        if (ctx->enc) {
584
0
            if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0))
585
0
                goto err;
586
0
            ctx->tag_set = 1;
587
0
        } else {
588
            /* The tag must be set before actually decrypting data */
589
0
            if (!ctx->tag_set)
590
0
                goto err;
591
592
0
            if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m))
593
0
                goto err;
594
            /* Finished - reset flags so calling this method again will fail */
595
0
            ctx->iv_set = 0;
596
0
            ctx->tag_set = 0;
597
0
            ctx->len_set = 0;
598
0
        }
599
0
    }
600
0
    olen = len;
601
0
finish:
602
0
    rv = 1;
603
0
err:
604
0
    *padlen = olen;
605
0
    return rv;
606
0
}
607
608
void ossl_ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw)
609
0
{
610
0
    ctx->keylen = keybits / 8;
611
0
    ctx->key_set = 0;
612
0
    ctx->iv_set = 0;
613
0
    ctx->tag_set = 0;
614
0
    ctx->len_set = 0;
615
0
    ctx->l = 8;
616
0
    ctx->m = 12;
617
0
    ctx->tls_aad_len = UNINITIALISED_SIZET;
618
0
    ctx->hw = hw;
619
0
}