Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/providers/implementations/macs/gmac_prov.c
Line
Count
Source
1
/*
2
 * Copyright 2018-2025 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
/* clang-format off */
10
11
/* clang-format on */
12
13
#include <stdlib.h>
14
#include <string.h>
15
#include <openssl/core_dispatch.h>
16
#include <openssl/core_names.h>
17
#include <openssl/params.h>
18
#include <openssl/evp.h>
19
#include <openssl/err.h>
20
#include <openssl/proverr.h>
21
22
#include "internal/cryptlib.h"
23
#include "prov/implementations.h"
24
#include "prov/provider_ctx.h"
25
#include "prov/provider_util.h"
26
#include "prov/providercommon.h"
27
28
/*
29
 * Forward declaration of everything implemented here.  This is not strictly
30
 * necessary for the compiler, but provides an assurance that the signatures
31
 * of the functions in the dispatch table are correct.
32
 */
33
static OSSL_FUNC_mac_newctx_fn gmac_new;
34
static OSSL_FUNC_mac_dupctx_fn gmac_dup;
35
static OSSL_FUNC_mac_freectx_fn gmac_free;
36
static OSSL_FUNC_mac_gettable_params_fn gmac_gettable_params;
37
static OSSL_FUNC_mac_get_params_fn gmac_get_params;
38
static OSSL_FUNC_mac_settable_ctx_params_fn gmac_settable_ctx_params;
39
static OSSL_FUNC_mac_set_ctx_params_fn gmac_set_ctx_params;
40
static OSSL_FUNC_mac_init_fn gmac_init;
41
static OSSL_FUNC_mac_update_fn gmac_update;
42
static OSSL_FUNC_mac_final_fn gmac_final;
43
44
/* local GMAC pkey structure */
45
46
struct gmac_data_st {
47
    void *provctx;
48
    EVP_CIPHER_CTX *ctx; /* Cipher context */
49
    PROV_CIPHER cipher;
50
};
51
52
static void gmac_free(void *vmacctx)
53
212
{
54
212
    struct gmac_data_st *macctx = vmacctx;
55
56
212
    if (macctx != NULL) {
57
212
        EVP_CIPHER_CTX_free(macctx->ctx);
58
212
        ossl_prov_cipher_reset(&macctx->cipher);
59
212
        OPENSSL_free(macctx);
60
212
    }
61
212
}
62
63
static void *gmac_new(void *provctx)
64
212
{
65
212
    struct gmac_data_st *macctx;
66
67
212
    if (!ossl_prov_is_running())
68
0
        return NULL;
69
70
212
    if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL
71
212
        || (macctx->ctx = EVP_CIPHER_CTX_new()) == NULL) {
72
0
        gmac_free(macctx);
73
0
        return NULL;
74
0
    }
75
212
    macctx->provctx = provctx;
76
77
212
    return macctx;
78
212
}
79
80
static void *gmac_dup(void *vsrc)
81
0
{
82
0
    struct gmac_data_st *src = vsrc;
83
0
    struct gmac_data_st *dst;
84
85
0
    if (!ossl_prov_is_running())
86
0
        return NULL;
87
88
0
    dst = gmac_new(src->provctx);
89
0
    if (dst == NULL)
90
0
        return NULL;
91
92
0
    if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx)
93
0
        || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
94
0
        gmac_free(dst);
95
0
        return NULL;
96
0
    }
97
0
    return dst;
98
0
}
99
100
static size_t gmac_size(void)
101
0
{
102
0
    return EVP_GCM_TLS_TAG_LEN;
103
0
}
104
105
static int gmac_setkey(struct gmac_data_st *macctx,
106
    const unsigned char *key, size_t keylen)
107
105
{
108
105
    EVP_CIPHER_CTX *ctx = macctx->ctx;
109
110
105
    if (keylen != (size_t)EVP_CIPHER_CTX_get_key_length(ctx)) {
111
55
        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
112
55
        return 0;
113
55
    }
114
50
    if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
115
0
        return 0;
116
50
    return 1;
117
50
}
118
119
static int gmac_init(void *vmacctx, const unsigned char *key,
120
    size_t keylen, const OSSL_PARAM params[])
121
208
{
122
208
    struct gmac_data_st *macctx = vmacctx;
123
124
208
    if (!ossl_prov_is_running() || !gmac_set_ctx_params(macctx, params))
125
184
        return 0;
126
24
    if (key != NULL)
127
24
        return gmac_setkey(macctx, key, keylen);
128
0
    return EVP_EncryptInit_ex(macctx->ctx, NULL, NULL, NULL, NULL);
129
24
}
130
131
static int gmac_update(void *vmacctx, const unsigned char *data,
132
    size_t datalen)
133
0
{
134
0
    struct gmac_data_st *macctx = vmacctx;
135
0
    EVP_CIPHER_CTX *ctx = macctx->ctx;
136
0
    int outlen;
137
138
0
    if (datalen == 0)
139
0
        return 1;
140
141
0
    while (datalen > INT_MAX) {
142
0
        if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX))
143
0
            return 0;
144
0
        data += INT_MAX;
145
0
        datalen -= INT_MAX;
146
0
    }
147
0
    return EVP_EncryptUpdate(ctx, NULL, &outlen, data, (int)datalen);
148
0
}
149
150
static int gmac_final(void *vmacctx, unsigned char *out, size_t *outl,
151
    size_t outsize)
152
0
{
153
0
    OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
154
0
    struct gmac_data_st *macctx = vmacctx;
155
0
    int hlen = 0;
156
157
0
    if (!ossl_prov_is_running())
158
0
        return 0;
159
160
0
    if (!EVP_EncryptFinal_ex(macctx->ctx, out, &hlen))
161
0
        return 0;
162
163
0
    hlen = (int)gmac_size();
164
0
    params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
165
0
        out, (size_t)hlen);
166
0
    if (!EVP_CIPHER_CTX_get_params(macctx->ctx, params))
167
0
        return 0;
168
169
0
    *outl = hlen;
170
0
    return 1;
171
0
}
172
173
/* clang-format off */
174
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
175
#ifndef gmac_get_params_list
176
static const OSSL_PARAM gmac_get_params_list[] = {
177
    OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
178
    OSSL_PARAM_END
179
};
180
#endif
181
182
#ifndef gmac_get_params_st
183
struct gmac_get_params_st {
184
    OSSL_PARAM *size;
185
};
186
#endif
187
188
#ifndef gmac_get_params_decoder
189
static int gmac_get_params_decoder
190
    (const OSSL_PARAM *p, struct gmac_get_params_st *r)
191
0
{
192
0
    const char *s;
193
194
0
    memset(r, 0, sizeof(*r));
195
0
    if (p != NULL)
196
0
        for (; (s = p->key) != NULL; p++)
197
0
            if (ossl_likely(strcmp("size", s + 0) == 0)) {
198
                /* OSSL_MAC_PARAM_SIZE */
199
0
                if (ossl_unlikely(r->size != NULL)) {
200
0
                    ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
201
0
                                   "param %s is repeated", s);
202
0
                    return 0;
203
0
                }
204
0
                r->size = (OSSL_PARAM *)p;
205
0
            }
206
0
    return 1;
207
0
}
208
#endif
209
/* End of machine generated */
210
/* clang-format on */
211
212
static const OSSL_PARAM *gmac_gettable_params(void *provctx)
213
0
{
214
0
    return gmac_get_params_list;
215
0
}
216
217
static int gmac_get_params(OSSL_PARAM params[])
218
0
{
219
0
    struct gmac_get_params_st p;
220
221
0
    if (!gmac_get_params_decoder(params, &p))
222
0
        return 0;
223
224
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, gmac_size()))
225
0
        return 0;
226
227
0
    return 1;
228
0
}
229
230
/* clang-format off */
231
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
232
#ifndef gmac_set_ctx_params_list
233
static const OSSL_PARAM gmac_set_ctx_params_list[] = {
234
    OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0),
235
    OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
236
    OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
237
    OSSL_PARAM_octet_string(OSSL_MAC_PARAM_IV, NULL, 0),
238
    OSSL_PARAM_END
239
};
240
#endif
241
242
#ifndef gmac_set_ctx_params_st
243
struct gmac_set_ctx_params_st {
244
    OSSL_PARAM *cipher;
245
    OSSL_PARAM *engine;
246
    OSSL_PARAM *iv;
247
    OSSL_PARAM *key;
248
    OSSL_PARAM *propq;
249
};
250
#endif
251
252
#ifndef gmac_set_ctx_params_decoder
253
static int gmac_set_ctx_params_decoder
254
    (const OSSL_PARAM *p, struct gmac_set_ctx_params_st *r)
255
45
{
256
45
    const char *s;
257
258
45
    memset(r, 0, sizeof(*r));
259
45
    if (p != NULL)
260
187
        for (; (s = p->key) != NULL; p++)
261
147
            switch(s[0]) {
262
7
            default:
263
7
                break;
264
34
            case 'c':
265
34
                if (ossl_likely(strcmp("ipher", s + 1) == 0)) {
266
                    /* OSSL_MAC_PARAM_CIPHER */
267
34
                    if (ossl_unlikely(r->cipher != NULL)) {
268
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
269
0
                                       "param %s is repeated", s);
270
0
                        return 0;
271
0
                    }
272
34
                    r->cipher = (OSSL_PARAM *)p;
273
34
                }
274
34
                break;
275
34
            case 'e':
276
0
                if (ossl_likely(strcmp("ngine", s + 1) == 0)) {
277
                    /* OSSL_ALG_PARAM_ENGINE */
278
0
                    if (ossl_unlikely(r->engine != NULL)) {
279
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
280
0
                                       "param %s is repeated", s);
281
0
                        return 0;
282
0
                    }
283
0
                    r->engine = (OSSL_PARAM *)p;
284
0
                }
285
0
                break;
286
33
            case 'i':
287
33
                if (ossl_likely(strcmp("v", s + 1) == 0)) {
288
                    /* OSSL_MAC_PARAM_IV */
289
33
                    if (ossl_unlikely(r->iv != NULL)) {
290
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
291
0
                                       "param %s is repeated", s);
292
0
                        return 0;
293
0
                    }
294
33
                    r->iv = (OSSL_PARAM *)p;
295
33
                }
296
33
                break;
297
33
            case 'k':
298
33
                if (ossl_likely(strcmp("ey", s + 1) == 0)) {
299
                    /* OSSL_MAC_PARAM_KEY */
300
33
                    if (ossl_unlikely(r->key != NULL)) {
301
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
302
0
                                       "param %s is repeated", s);
303
0
                        return 0;
304
0
                    }
305
33
                    r->key = (OSSL_PARAM *)p;
306
33
                }
307
33
                break;
308
40
            case 'p':
309
40
                if (ossl_likely(strcmp("roperties", s + 1) == 0)) {
310
                    /* OSSL_MAC_PARAM_PROPERTIES */
311
40
                    if (ossl_unlikely(r->propq != NULL)) {
312
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
313
0
                                       "param %s is repeated", s);
314
0
                        return 0;
315
0
                    }
316
40
                    r->propq = (OSSL_PARAM *)p;
317
40
                }
318
147
            }
319
45
    return 1;
320
45
}
321
#endif
322
/* End of machine generated */
323
/* clang-format on */
324
325
static const OSSL_PARAM *gmac_settable_ctx_params(ossl_unused void *ctx,
326
    ossl_unused void *provctx)
327
198
{
328
198
    return gmac_set_ctx_params_list;
329
198
}
330
331
/*
332
 * ALL parameters should be set before init().
333
 */
334
static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
335
125
{
336
125
    struct gmac_data_st *macctx = vmacctx;
337
125
    EVP_CIPHER_CTX *ctx;
338
125
    OSSL_LIB_CTX *provctx;
339
125
    struct gmac_set_ctx_params_st p;
340
341
125
    if (macctx == NULL || !gmac_set_ctx_params_decoder(params, &p))
342
0
        return 0;
343
344
125
    if ((ctx = macctx->ctx) == NULL)
345
0
        return 0;
346
125
    provctx = PROV_LIBCTX_OF(macctx->provctx);
347
348
125
    if (p.cipher != NULL) {
349
114
        if (!ossl_prov_cipher_load(&macctx->cipher, p.cipher, p.propq,
350
114
                p.engine, provctx))
351
72
            return 0;
352
42
        if (EVP_CIPHER_get_mode(ossl_prov_cipher_cipher(&macctx->cipher))
353
42
            != EVP_CIPH_GCM_MODE) {
354
5
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
355
5
            return 0;
356
5
        }
357
37
        if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher),
358
37
                ossl_prov_cipher_engine(&macctx->cipher), NULL,
359
37
                NULL))
360
0
            return 0;
361
37
    }
362
363
48
    if (p.key != NULL)
364
37
        if (p.key->data_type != OSSL_PARAM_OCTET_STRING
365
37
            || !gmac_setkey(macctx, p.key->data, p.key->data_size))
366
13
            return 0;
367
368
35
    if (p.iv != NULL) {
369
24
        if (p.iv->data_type != OSSL_PARAM_OCTET_STRING)
370
0
            return 0;
371
372
24
        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
373
24
                (int)p.iv->data_size, NULL)
374
24
                <= 0
375
8
            || !EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p.iv->data))
376
16
            return 0;
377
24
    }
378
19
    return 1;
379
35
}
380
381
const OSSL_DISPATCH ossl_gmac_functions[] = {
382
    { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))gmac_new },
383
    { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))gmac_dup },
384
    { OSSL_FUNC_MAC_FREECTX, (void (*)(void))gmac_free },
385
    { OSSL_FUNC_MAC_INIT, (void (*)(void))gmac_init },
386
    { OSSL_FUNC_MAC_UPDATE, (void (*)(void))gmac_update },
387
    { OSSL_FUNC_MAC_FINAL, (void (*)(void))gmac_final },
388
    { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))gmac_gettable_params },
389
    { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))gmac_get_params },
390
    { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
391
        (void (*)(void))gmac_settable_ctx_params },
392
    { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))gmac_set_ctx_params },
393
    OSSL_DISPATCH_END
394
};