Rate This Document
Findability
Accuracy
Completeness
Readability

SM4-ECB Algorithm Calling Example

Save the following code as sm4_ecb_demo.c, and then compile and run the code.

gcc -o sm4_ecb_demo sm4_ecb_demo.c -lssl -lcrypto -ldl
./sm4_ecb_demo
/**
 * sm4_ecb_demo.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#define ENGINE_SO_PATH   "/usr/lib64/libsdf_engine.so"
#define SDF_LIB_PATH     "/usr/lib64/libsdf.so"
static ENGINE *g_engine = NULL;
static const unsigned char g_key16[] = {
    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
    0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
static ENGINE* load_engine(const char *so_path, const char *sdf_lib_path) {
    ENGINE_load_dynamic();
    ENGINE *e = ENGINE_by_id("dynamic");
    if (!e) {
        fprintf(stderr, "Failed to get dynamic ENGINE\n");
        return NULL;
    }
    if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", so_path, 0)) goto err;
    if (!ENGINE_ctrl_cmd_string(e, "ID", "sdf", 0)) goto err;
    if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) goto err;
    if (!ENGINE_ctrl_cmd_string(e, "SDF_LIB_PATH", sdf_lib_path, 0)) goto err;
    if (!ENGINE_init(e)) goto err;
    return e;
err:
    ENGINE_free(e);
    return NULL;
}
static void test_sm4_ecb(void) {
    unsigned char pt[16] = "0123456789abcdef";
    unsigned char ct[32] = {0};
    unsigned char dt[32] = {0};
    int outl = 0, totl = 0;
    /* Encryption */
    EVP_CIPHER_CTX *ectx = EVP_CIPHER_CTX_new();
    if (!ectx) {
        fprintf(stderr, "EVP_CIPHER_CTX_new failed\n");
        exit(EXIT_FAILURE);
    }
    if (EVP_EncryptInit_ex(ectx, EVP_sm4_ecb(), g_engine, g_key16, NULL) != 1) {
        fprintf(stderr, "EncryptInit failed\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    if (EVP_EncryptUpdate(ectx, ct, &outl, pt, 16) != 1) {
        fprintf(stderr, "EncryptUpdate failed\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    totl = outl;
    if (EVP_EncryptFinal_ex(ectx, ct + totl, &outl) != 1) {
        fprintf(stderr, "EncryptFinal failed\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    totl += outl;
    if (totl != 32) {
        fprintf(stderr, "ECB ciphertext length wrong\n");
        EVP_CIPHER_CTX_free(ectx);
        exit(EXIT_FAILURE);
    }
    EVP_CIPHER_CTX_free(ectx);
    /* Decryption */
    EVP_CIPHER_CTX *dctx = EVP_CIPHER_CTX_new();
    if (!dctx) {
        fprintf(stderr, "Decrypt ctx new failed\n");
        exit(EXIT_FAILURE);
    }
    if (EVP_DecryptInit_ex(dctx, EVP_sm4_ecb(), g_engine, g_key16, NULL) != 1) {
        fprintf(stderr, "DecryptInit failed\n");
        EVP_CIPHER_CTX_free(dctx);
        exit(EXIT_FAILURE);
    }
    if (EVP_DecryptUpdate(dctx, dt, &outl, ct, 32) != 1) {
        fprintf(stderr, "DecryptUpdate failed\n");
        EVP_CIPHER_CTX_free(dctx);
        exit(EXIT_FAILURE);
    }
    totl = outl;
    if (EVP_DecryptFinal_ex(dctx, dt + totl, &outl) != 1) {
        fprintf(stderr, "DecryptFinal failed\n");
        EVP_CIPHER_CTX_free(dctx);
        exit(EXIT_FAILURE);
    }
    totl += outl;
    EVP_CIPHER_CTX_free(dctx);
    if (totl != 16 || memcmp(dt, pt, 16) != 0) {
        fprintf(stderr, "ECB round-trip failed\n");
        exit(EXIT_FAILURE);
    }
    printf("SM4-ECB encryption/decryption: OK\n");
}
int main(void) {
    printf("Loading ENGINE...\n");
    g_engine = load_engine(ENGINE_SO_PATH, SDF_LIB_PATH);
    if (!g_engine) {
        fprintf(stderr, "Engine load failed\n");
        return EXIT_FAILURE;
    }
    printf("Engine loaded.\n");
    test_sm4_ecb();
    ENGINE_free(g_engine);

    printf("SM4-ECB test passed.\n");
    return EXIT_SUCCESS;
}