Coverage Report

Created: 2025-06-22 06:56

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