Coverage Report

Created: 2025-06-13 06:56

/src/openssl/crypto/evp/e_sm4.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
3
 * Copyright 2017 Ribose Inc. All Rights Reserved.
4
 * Ported from Ribose contributions from Botan.
5
 *
6
 * Licensed under the Apache License 2.0 (the "License").  You may not use
7
 * this file except in compliance with the License.  You can obtain a copy
8
 * in the file LICENSE in the source distribution or at
9
 * https://www.openssl.org/source/license.html
10
 */
11
12
#include "internal/deprecated.h"
13
14
#include "internal/cryptlib.h"
15
#ifndef OPENSSL_NO_SM4
16
# include <openssl/evp.h>
17
# include <openssl/modes.h>
18
# include "crypto/sm4.h"
19
# include "crypto/evp.h"
20
# include "crypto/sm4_platform.h"
21
# include "evp_local.h"
22
23
typedef struct {
24
    union {
25
        OSSL_UNION_ALIGN;
26
        SM4_KEY ks;
27
    } ks;
28
    block128_f block;
29
    union {
30
        ecb128_f ecb;
31
        cbc128_f cbc;
32
        ctr128_f ctr;
33
    } stream;
34
} EVP_SM4_KEY;
35
36
# define BLOCK_CIPHER_generic(nid,blocksize,ivlen,nmode,mode,MODE,flags) \
37
static const EVP_CIPHER sm4_##mode = { \
38
        nid##_##nmode,blocksize,128/8,ivlen, \
39
        flags|EVP_CIPH_##MODE##_MODE,   \
40
        EVP_ORIG_GLOBAL,                \
41
        sm4_init_key,                   \
42
        sm4_##mode##_cipher,            \
43
        NULL,                           \
44
        sizeof(EVP_SM4_KEY),            \
45
        NULL,NULL,NULL,NULL }; \
46
5
const EVP_CIPHER *EVP_sm4_##mode(void) \
47
5
{ return &sm4_##mode; }
EVP_sm4_cbc
Line
Count
Source
46
1
const EVP_CIPHER *EVP_sm4_##mode(void) \
47
1
{ return &sm4_##mode; }
EVP_sm4_ecb
Line
Count
Source
46
1
const EVP_CIPHER *EVP_sm4_##mode(void) \
47
1
{ return &sm4_##mode; }
EVP_sm4_ofb
Line
Count
Source
46
1
const EVP_CIPHER *EVP_sm4_##mode(void) \
47
1
{ return &sm4_##mode; }
EVP_sm4_cfb128
Line
Count
Source
46
1
const EVP_CIPHER *EVP_sm4_##mode(void) \
47
1
{ return &sm4_##mode; }
EVP_sm4_ctr
Line
Count
Source
46
1
const EVP_CIPHER *EVP_sm4_##mode(void) \
47
1
{ return &sm4_##mode; }
48
49
#define DEFINE_BLOCK_CIPHERS(nid,flags)             \
50
        BLOCK_CIPHER_generic(nid,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)     \
51
        BLOCK_CIPHER_generic(nid,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)      \
52
        BLOCK_CIPHER_generic(nid,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \
53
        BLOCK_CIPHER_generic(nid,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \
54
        BLOCK_CIPHER_generic(nid,1,16,ctr,ctr,CTR,flags)
55
56
static int sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
57
                        const unsigned char *iv, int enc)
58
0
{
59
0
    int mode;
60
0
    EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
61
62
0
    mode = EVP_CIPHER_CTX_get_mode(ctx);
63
0
    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
64
0
        && !enc) {
65
#ifdef HWSM4_CAPABLE
66
        if (HWSM4_CAPABLE) {
67
            HWSM4_set_decrypt_key(key, &dat->ks.ks);
68
            dat->block = (block128_f) HWSM4_decrypt;
69
            dat->stream.cbc = NULL;
70
# ifdef HWSM4_cbc_encrypt
71
            if (mode == EVP_CIPH_CBC_MODE)
72
                dat->stream.cbc = (cbc128_f) HWSM4_cbc_encrypt;
73
# endif
74
# ifdef HWSM4_ecb_encrypt
75
            if (mode == EVP_CIPH_ECB_MODE)
76
                dat->stream.ecb = (ecb128_f) HWSM4_ecb_encrypt;
77
# endif
78
        } else
79
#endif
80
#ifdef VPSM4_CAPABLE
81
        if (VPSM4_CAPABLE) {
82
            vpsm4_set_decrypt_key(key, &dat->ks.ks);
83
            dat->block = (block128_f) vpsm4_decrypt;
84
            dat->stream.cbc = NULL;
85
            if (mode == EVP_CIPH_CBC_MODE)
86
                dat->stream.cbc = (cbc128_f) vpsm4_cbc_encrypt;
87
            else if (mode == EVP_CIPH_ECB_MODE)
88
                dat->stream.ecb = (ecb128_f) vpsm4_ecb_encrypt;
89
        } else
90
#endif
91
0
        {
92
0
            dat->block = (block128_f) ossl_sm4_decrypt;
93
0
            ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx));
94
0
        }
95
0
    } else
96
#ifdef HWSM4_CAPABLE
97
    if (HWSM4_CAPABLE) {
98
        HWSM4_set_encrypt_key(key, &dat->ks.ks);
99
        dat->block = (block128_f) HWSM4_encrypt;
100
        dat->stream.cbc = NULL;
101
# ifdef HWSM4_cbc_encrypt
102
        if (mode == EVP_CIPH_CBC_MODE)
103
            dat->stream.cbc = (cbc128_f) HWSM4_cbc_encrypt;
104
        else
105
# endif
106
# ifdef HWSM4_ecb_encrypt
107
        if (mode == EVP_CIPH_ECB_MODE)
108
            dat->stream.ecb = (ecb128_f) HWSM4_ecb_encrypt;
109
        else
110
# endif
111
# ifdef HWSM4_ctr32_encrypt_blocks
112
        if (mode == EVP_CIPH_CTR_MODE)
113
            dat->stream.ctr = (ctr128_f) HWSM4_ctr32_encrypt_blocks;
114
        else
115
# endif
116
            (void)0;            /* terminate potentially open 'else' */
117
    } else
118
#endif
119
#ifdef VPSM4_CAPABLE
120
    if (VPSM4_CAPABLE) {
121
        vpsm4_set_encrypt_key(key, &dat->ks.ks);
122
        dat->block = (block128_f) vpsm4_encrypt;
123
        dat->stream.cbc = NULL;
124
        if (mode == EVP_CIPH_CBC_MODE)
125
            dat->stream.cbc = (cbc128_f) vpsm4_cbc_encrypt;
126
        else if (mode == EVP_CIPH_ECB_MODE)
127
            dat->stream.ecb = (ecb128_f) vpsm4_ecb_encrypt;
128
        else if (mode == EVP_CIPH_CTR_MODE)
129
            dat->stream.ctr = (ctr128_f) vpsm4_ctr32_encrypt_blocks;
130
    } else
131
#endif
132
0
    {
133
0
        dat->block = (block128_f) ossl_sm4_encrypt;
134
0
        ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx));
135
0
    }
136
0
    return 1;
137
0
}
138
139
static int sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
140
                          const unsigned char *in, size_t len)
141
0
{
142
0
    EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
143
144
0
    if (dat->stream.cbc)
145
0
        (*dat->stream.cbc) (in, out, len, &dat->ks.ks, ctx->iv,
146
0
                            EVP_CIPHER_CTX_is_encrypting(ctx));
147
0
    else if (EVP_CIPHER_CTX_is_encrypting(ctx))
148
0
        CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv,
149
0
                              dat->block);
150
0
    else
151
0
        CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
152
0
                              ctx->iv, dat->block);
153
0
    return 1;
154
0
}
155
156
static int sm4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
157
                          const unsigned char *in, size_t len)
158
0
{
159
0
    EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
160
0
    int num = EVP_CIPHER_CTX_get_num(ctx);
161
162
0
    CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
163
0
                          ctx->iv, &num,
164
0
                          EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
165
0
    EVP_CIPHER_CTX_set_num(ctx, num);
166
0
    return 1;
167
0
}
168
169
static int sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
170
                          const unsigned char *in, size_t len)
171
0
{
172
0
    size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
173
0
    size_t i;
174
0
    EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
175
176
0
    if (len < bl)
177
0
        return 1;
178
179
0
    if (dat->stream.ecb != NULL)
180
0
        (*dat->stream.ecb) (in, out, len, &dat->ks.ks,
181
0
                            EVP_CIPHER_CTX_is_encrypting(ctx));
182
0
    else
183
0
        for (i = 0, len -= bl; i <= len; i += bl)
184
0
            (*dat->block) (in + i, out + i, &dat->ks);
185
186
0
    return 1;
187
0
}
188
189
static int sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
190
                          const unsigned char *in, size_t len)
191
0
{
192
0
    EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
193
0
    int num = EVP_CIPHER_CTX_get_num(ctx);
194
195
0
    CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
196
0
                          ctx->iv, &num, dat->block);
197
0
    EVP_CIPHER_CTX_set_num(ctx, num);
198
0
    return 1;
199
0
}
200
201
static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
202
                          const unsigned char *in, size_t len)
203
0
{
204
0
    int n = EVP_CIPHER_CTX_get_num(ctx);
205
0
    unsigned int num;
206
0
    EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx);
207
208
0
    if (n < 0)
209
0
        return 0;
210
0
    num = (unsigned int)n;
211
212
0
    if (dat->stream.ctr)
213
0
        CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
214
0
                                    ctx->iv,
215
0
                                    EVP_CIPHER_CTX_buf_noconst(ctx),
216
0
                                    &num, dat->stream.ctr);
217
0
    else
218
0
        CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
219
0
                              ctx->iv,
220
0
                              EVP_CIPHER_CTX_buf_noconst(ctx), &num,
221
0
                              dat->block);
222
0
    EVP_CIPHER_CTX_set_num(ctx, num);
223
0
    return 1;
224
0
}
225
226
DEFINE_BLOCK_CIPHERS(NID_sm4, 0)
227
#endif