Coverage Report

Created: 2026-09-13 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/providers/implementations/ciphers/cipher_rc2.c
Line
Count
Source
1
/*
2
 * Copyright 2019-2026 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
/* Dispatch functions for RC2 cipher modes ecb, cbc, ofb, cfb */
11
12
/*
13
 * RC2 low level APIs are deprecated for public use, but still ok for internal
14
 * use.
15
 */
16
#include "internal/deprecated.h"
17
18
#include <openssl/proverr.h>
19
#include "cipher_rc2.h"
20
#include "prov/implementations.h"
21
#include "prov/providercommon.h"
22
23
struct rc2_get_ctx_param_list_st {
24
    struct ossl_cipher_get_ctx_param_list_st common;
25
    OSSL_PARAM *bits;
26
    OSSL_PARAM *algid;
27
    OSSL_PARAM *oldid;
28
};
29
30
struct rc2_set_ctx_param_list_st {
31
    struct ossl_cipher_set_ctx_param_list_st common;
32
    OSSL_PARAM *bits;
33
    OSSL_PARAM *algid;
34
};
35
36
#define rc2_get_ctx_params_st rc2_get_ctx_param_list_st
37
#define rc2_set_ctx_params_st rc2_set_ctx_param_list_st
38
39
#include "providers/implementations/ciphers/cipher_rc2.inc"
40
41
0
#define RC2_40_MAGIC 0xa0
42
0
#define RC2_64_MAGIC 0x78
43
0
#define RC2_128_MAGIC 0x3a
44
#define RC2_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
45
46
static OSSL_FUNC_cipher_encrypt_init_fn rc2_einit;
47
static OSSL_FUNC_cipher_decrypt_init_fn rc2_dinit;
48
static OSSL_FUNC_cipher_freectx_fn rc2_freectx;
49
static OSSL_FUNC_cipher_dupctx_fn rc2_dupctx;
50
static OSSL_FUNC_cipher_gettable_ctx_params_fn rc2_gettable_ctx_params;
51
static OSSL_FUNC_cipher_settable_ctx_params_fn rc2_settable_ctx_params;
52
static OSSL_FUNC_cipher_set_ctx_params_fn rc2_set_ctx_params;
53
54
static void rc2_freectx(void *vctx)
55
0
{
56
0
    PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
57
58
0
    ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
59
0
    OPENSSL_clear_free(ctx, sizeof(*ctx));
60
0
}
61
62
static void *rc2_dupctx(void *ctx)
63
0
{
64
0
    PROV_RC2_CTX *in = (PROV_RC2_CTX *)ctx;
65
0
    PROV_RC2_CTX *ret;
66
67
0
    if (!ossl_prov_is_running())
68
0
        return NULL;
69
70
0
    ret = OPENSSL_malloc(sizeof(*ret));
71
0
    if (ret == NULL)
72
0
        return NULL;
73
0
    *ret = *in;
74
75
0
    return ret;
76
0
}
77
78
static int rc2_keybits_to_magic(int keybits)
79
0
{
80
0
    switch (keybits) {
81
0
    case 128:
82
0
        return RC2_128_MAGIC;
83
0
    case 64:
84
0
        return RC2_64_MAGIC;
85
0
    case 40:
86
0
        return RC2_40_MAGIC;
87
0
    }
88
0
    ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE);
89
0
    return 0;
90
0
}
91
92
static int rc2_magic_to_keybits(int magic)
93
0
{
94
0
    switch (magic) {
95
0
    case RC2_128_MAGIC:
96
0
        return 128;
97
0
    case RC2_64_MAGIC:
98
0
        return 64;
99
0
    case RC2_40_MAGIC:
100
0
        return 40;
101
0
    }
102
0
    ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE);
103
0
    return 0;
104
0
}
105
106
static int rc2_einit(void *ctx, const unsigned char *key, size_t keylen,
107
    const unsigned char *iv, size_t ivlen,
108
    const OSSL_PARAM params[])
109
0
{
110
0
    if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
111
0
        return 0;
112
0
    return rc2_set_ctx_params(ctx, params);
113
0
}
114
115
static int rc2_dinit(void *ctx, const unsigned char *key, size_t keylen,
116
    const unsigned char *iv, size_t ivlen,
117
    const OSSL_PARAM params[])
118
0
{
119
0
    if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
120
0
        return 0;
121
0
    return rc2_set_ctx_params(ctx, params);
122
0
}
123
124
static int rc2_get_ctx_params(void *vctx, OSSL_PARAM params[])
125
0
{
126
0
    PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
127
0
    struct rc2_get_ctx_param_list_st prms;
128
0
    OSSL_PARAM *p, *p1, *p2;
129
130
0
    if (ctx == NULL || !rc2_get_ctx_params_decoder(params, &prms))
131
0
        return 0;
132
0
    if (!ossl_cipher_common_get_ctx_params(&ctx->base, &prms.common))
133
0
        return 0;
134
0
    p = prms.bits;
135
0
    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_bits)) {
136
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
137
0
        return 0;
138
0
    }
139
0
    p1 = prms.algid;
140
0
    p2 = prms.oldid;
141
0
    if (p1 != NULL || p2 != NULL) {
142
0
        long num;
143
0
        int i;
144
0
        ASN1_TYPE *type;
145
0
        unsigned char *d1 = (p1 == NULL) ? NULL : p1->data;
146
0
        unsigned char *d2 = (p2 == NULL) ? NULL : p2->data;
147
0
        unsigned char **dd1 = d1 == NULL ? NULL : &d1;
148
0
        unsigned char **dd2 = d2 == NULL ? NULL : &d2;
149
150
0
        if ((p1 != NULL && p1->data_type != OSSL_PARAM_OCTET_STRING)
151
0
            || (p2 != NULL && p2->data_type != OSSL_PARAM_OCTET_STRING)) {
152
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
153
0
            return 0;
154
0
        }
155
0
        if ((type = ASN1_TYPE_new()) == NULL) {
156
0
            ERR_raise(ERR_LIB_PROV, ERR_R_ASN1_LIB);
157
0
            return 0;
158
0
        }
159
160
        /* Is this the original IV or the running IV? */
161
0
        num = rc2_keybits_to_magic((int)ctx->key_bits);
162
0
        if (!ASN1_TYPE_set_int_octetstring(type, num, ctx->base.iv,
163
0
                (int)ctx->base.ivlen)) {
164
0
            ASN1_TYPE_free(type);
165
0
            ERR_raise(ERR_LIB_PROV, ERR_R_ASN1_LIB);
166
0
            return 0;
167
0
        }
168
169
        /*
170
         * IF the caller has a buffer, we pray to the gods they got the
171
         * size right.  There's no way to tell the i2d functions...
172
         */
173
0
        i = i2d_ASN1_TYPE(type, dd1);
174
0
        if (p1 != NULL && i >= 0)
175
0
            p1->return_size = (size_t)i;
176
177
        /*
178
         * If the buffers differ, redo the i2d on the second buffer.
179
         * Otherwise, just use |i| as computed above
180
         */
181
0
        if (d1 != d2)
182
0
            i = i2d_ASN1_TYPE(type, dd2);
183
0
        if (p2 != NULL && i >= 0)
184
0
            p2->return_size = (size_t)i;
185
186
0
        ASN1_TYPE_free(type);
187
0
        if (i < 0) {
188
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
189
0
            return 0;
190
0
        }
191
0
    }
192
0
    return 1;
193
0
}
194
195
static int rc2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
196
0
{
197
0
    PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
198
0
    struct rc2_set_ctx_param_list_st prms;
199
0
    const OSSL_PARAM *p;
200
201
0
    if (ossl_param_is_empty(params))
202
0
        return 1;
203
204
0
    if (ctx == NULL || !rc2_set_ctx_params_decoder(params, &prms))
205
0
        return 0;
206
0
    if (!ossl_cipher_common_set_ctx_params(&ctx->base, &prms.common))
207
0
        return 0;
208
0
    p = prms.bits;
209
0
    if (p != NULL) {
210
0
        if (!OSSL_PARAM_get_size_t(p, &ctx->key_bits)) {
211
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
212
0
            return 0;
213
0
        }
214
0
    }
215
0
    p = prms.algid;
216
0
    if (p != NULL) {
217
0
        ASN1_TYPE *type = NULL;
218
0
        long num = 0;
219
0
        const unsigned char *d = p->data;
220
0
        int ret = 1;
221
0
        unsigned char iv[16];
222
223
0
        if (p->data_type != OSSL_PARAM_OCTET_STRING
224
0
            || ctx->base.ivlen > sizeof(iv)
225
0
            || (type = d2i_ASN1_TYPE(NULL, &d, (long)p->data_size)) == NULL
226
0
            || ((size_t)ASN1_TYPE_get_int_octetstring(type, &num, iv,
227
0
                    (int)ctx->base.ivlen)
228
0
                != ctx->base.ivlen)
229
0
            || !ossl_cipher_generic_initiv(&ctx->base, iv, ctx->base.ivlen)
230
0
            || (ctx->key_bits = rc2_magic_to_keybits(num)) == 0) {
231
0
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
232
0
            ret = 0;
233
0
        }
234
0
        ASN1_TYPE_free(type);
235
0
        if (ret == 0)
236
0
            return 0;
237
        /*
238
         * This code assumes that the caller will call
239
         * EVP_CipherInit_ex() with a non NULL key in order to setup a key that
240
         * uses the keylen and keybits that were set here.
241
         */
242
0
        ctx->base.keylen = ctx->key_bits / 8;
243
0
    }
244
0
    return 1;
245
0
}
246
247
static const OSSL_PARAM *rc2_gettable_ctx_params(ossl_unused void *cctx,
248
    ossl_unused void *provctx)
249
6
{
250
6
    return rc2_get_ctx_params_list;
251
6
}
252
253
static const OSSL_PARAM *rc2_settable_ctx_params(ossl_unused void *cctx,
254
    ossl_unused void *provctx)
255
0
{
256
0
    return rc2_set_ctx_params_list;
257
0
}
258
259
#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, blkbits,              \
260
    ivbits, typ)                                                                         \
261
    static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params;         \
262
    static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[])                \
263
6
    {                                                                                    \
264
6
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
6
            flags, kbits, blkbits, ivbits);                                              \
266
6
    }                                                                                    \
cipher_rc2.c:rc2_128_ecb_get_params
Line
Count
Source
263
1
    {                                                                                    \
264
1
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
1
            flags, kbits, blkbits, ivbits);                                              \
266
1
    }                                                                                    \
cipher_rc2.c:rc2_128_cbc_get_params
Line
Count
Source
263
1
    {                                                                                    \
264
1
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
1
            flags, kbits, blkbits, ivbits);                                              \
266
1
    }                                                                                    \
cipher_rc2.c:rc2_40_cbc_get_params
Line
Count
Source
263
1
    {                                                                                    \
264
1
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
1
            flags, kbits, blkbits, ivbits);                                              \
266
1
    }                                                                                    \
cipher_rc2.c:rc2_64_cbc_get_params
Line
Count
Source
263
1
    {                                                                                    \
264
1
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
1
            flags, kbits, blkbits, ivbits);                                              \
266
1
    }                                                                                    \
cipher_rc2.c:rc2_128_ofb128_get_params
Line
Count
Source
263
1
    {                                                                                    \
264
1
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
1
            flags, kbits, blkbits, ivbits);                                              \
266
1
    }                                                                                    \
cipher_rc2.c:rc2_128_cfb128_get_params
Line
Count
Source
263
1
    {                                                                                    \
264
1
        return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,          \
265
1
            flags, kbits, blkbits, ivbits);                                              \
266
1
    }                                                                                    \
267
    static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx;                 \
268
    static void *alg##_##kbits##_##lcmode##_newctx(void *provctx)                        \
269
0
    {                                                                                    \
270
0
        PROV_##UCALG##_CTX *ctx;                                                         \
271
0
        if (!ossl_prov_is_running())                                                     \
272
0
            return NULL;                                                                 \
273
0
        ctx = OPENSSL_zalloc(sizeof(*ctx));                                              \
274
0
        if (ctx != NULL) {                                                               \
275
0
            ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits,                     \
276
0
                EVP_CIPH_##UCMODE##_MODE, flags,                                         \
277
0
                ossl_prov_cipher_hw_##alg##_##lcmode(kbits),                             \
278
0
                NULL);                                                                   \
279
0
            ctx->key_bits = kbits;                                                       \
280
0
        }                                                                                \
281
0
        return ctx;                                                                      \
282
0
    }                                                                                    \
283
    const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = {                      \
284
        { OSSL_FUNC_CIPHER_NEWCTX,                                                       \
285
            (void (*)(void))alg##_##kbits##_##lcmode##_newctx },                         \
286
        { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_freectx },                     \
287
        { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))alg##_dupctx },                       \
288
        { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc2_einit },                    \
289
        { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc2_dinit },                    \
290
        { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update }, \
291
        { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final },   \
292
        { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher },         \
293
        { OSSL_FUNC_CIPHER_GET_PARAMS,                                                   \
294
            (void (*)(void))alg##_##kbits##_##lcmode##_get_params },                     \
295
        { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                              \
296
            (void (*)(void))ossl_cipher_generic_gettable_params },                       \
297
        { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                               \
298
            (void (*)(void))rc2_get_ctx_params },                                        \
299
        { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                          \
300
            (void (*)(void))rc2_gettable_ctx_params },                                   \
301
        { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                               \
302
            (void (*)(void))rc2_set_ctx_params },                                        \
303
        { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                          \
304
            (void (*)(void))rc2_settable_ctx_params },                                   \
305
        OSSL_DISPATCH_END                                                                \
306
    };
307
308
/* ossl_rc2128ecb_functions */
309
0
IMPLEMENT_cipher(rc2, RC2, ecb, ECB, RC2_FLAGS, 128, 64, 0, block)
310
/* ossl_rc2128cbc_functions */
311
0
IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 128, 64, 64, block)
312
/* ossl_rc240cbc_functions */
313
0
IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 40, 64, 64, block)
314
/* ossl_rc264cbc_functions */
315
0
IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 64, 64, 64, block)
316
317
/* ossl_rc2128ofb128_functions */
318
0
IMPLEMENT_cipher(rc2, RC2, ofb128, OFB, RC2_FLAGS, 128, 8, 64, stream)
319
/* ossl_rc2128cfb128_functions */
320
IMPLEMENT_cipher(rc2, RC2, cfb128, CFB, RC2_FLAGS, 128, 8, 64, stream)