[][openwrt][mt7988][fips][Develop gcm ccm tools]

[Description]
Add gcm ccm tools based on openssl api.
This tools is for CAVP test.

[Release-log]
N/A

Change-Id: I4363fa7a2f2d1a75c4c3ee4f445912b0551dc81d
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7512445
diff --git a/feed/openssl-fips-ext/Makefile b/feed/openssl-fips-ext/Makefile
new file mode 100644
index 0000000..8a5b558
--- /dev/null
+++ b/feed/openssl-fips-ext/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=openssl-fips-ext
+PKG_RELEASE:=1
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/openssl-fips-ext
+	CATEGORY:=MTK Properties
+	SECTION:=MTK Properties
+	SUBMENU:=Applications
+	TITLE:=openssl-fips-ext -- simple tool for gcm and ccm based on openssl api
+	DEPENDS:= libopenssl
+endef
+
+define Package/openssl-fips-ext/description
+	Simple tool for gcm and ccm
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+	mkdir -p $(PKG_BUILD_DIR)/src
+	$(CP) ./src/* $(PKG_BUILD_DIR)/src
+endef
+
+define Build/Compile
+	make -C ./src \
+		CC="$(TARGET_CC)" \
+		OPENSSL_INCS_LOCATION=-I$(STAGING_DIR)/usr/include/openssl \
+		OPENSSL_LIBS_LOCATION=-L$(STAGING_DIR)/usr/lib
+endef
+
+define Package/openssl-fips-ext/install
+	$(INSTALL_DIR) $(1)/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/openssl-fips-ext $(1)/bin/
+endef
+
+$(eval $(call BuildPackage,openssl-fips-ext))
+
diff --git a/feed/openssl-fips-ext/src/Makefile b/feed/openssl-fips-ext/src/Makefile
new file mode 100644
index 0000000..4d8282e
--- /dev/null
+++ b/feed/openssl-fips-ext/src/Makefile
@@ -0,0 +1,21 @@
+CFLAGS = $(OPENSSL_INCS_LOCATION)
+LDFLAGS = $(OPENSSL_LIBS_LOCATION) -lssl -lcrypto -ldl -lpthread
+
+all: main.out
+
+main.out: common.o main.o aesgcm.o aesccm.o
+	$(CC) $(CFLAGS) -o openssl-fips-ext $^ $(LDFLAGS)
+
+main.o: main.c
+	$(CC) $(CFLAGS) -c -o main.o $< $(LDFLAGS)
+aesgcm.o: aesgcm.c
+	$(CC) $(CFLAGS) -c -o aesgcm.o $< $(LDFLAGS)
+
+aesccm.o: aesccm.c
+	$(CC) $(CFLAGS) -c -o aesccm.o $< $(LDFLAGS)
+
+common.o: common.c
+	$(CC) $(CFLAGS) -c -o common.o $< $(LDFLAGS)
+
+clean:
+	$(RM) openssl-fips-ext
diff --git a/feed/openssl-fips-ext/src/aesccm.c b/feed/openssl-fips-ext/src/aesccm.c
new file mode 100644
index 0000000..2d8bf69
--- /dev/null
+++ b/feed/openssl-fips-ext/src/aesccm.c
@@ -0,0 +1,140 @@
+#include "aesccm.h"
+
+
+struct operator ccm_oper = {
+	.init = ccm_init,
+	.uninit = ccm_uninit,
+	.encrypt = ccm_encrypt,
+	.decrypt = ccm_decrypt,
+	.check = ccm_check,
+};
+
+static struct ccm_data data;
+
+int ccm_init(void)
+{
+	hex2bin(&data.key, input_data.key, &(data.key_size));
+	hex2bin(&data.nonce, input_data.nonce, &(data.nonce_size));
+	hex2bin(&data.adata, input_data.adata, &(data.adata_size));
+	hex2bin(&data.payload, input_data.payload, &(data.payload_size));
+	hex2bin(&data.ct, input_data.ct, &(data.ct_size));
+	if (input_data.oper == DECRYPT) {
+		hex2bin(&data.tag, input_data.tag, &(data.tag_size));
+	} else if (input_data.oper == ENCRYPT) {
+		if (input_data.tag != NULL)
+			data.tag_size = atoi(input_data.tag);
+		else
+			data.tag_size = 16;
+	}
+	return 0;
+}
+
+void init_ccm_evp_encrypt(EVP_CIPHER_CTX **ctx)
+{
+	if (data.key_size == 16)
+		EVP_EncryptInit_ex(*ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
+	else if (data.key_size == 24)
+		EVP_EncryptInit_ex(*ctx, EVP_aes_192_ccm(), NULL, NULL, NULL);
+	else if (data.key_size == 32)
+		EVP_EncryptInit_ex(*ctx, EVP_aes_256_ccm(), NULL, NULL, NULL);
+}
+
+void init_ccm_evp_decrypt(EVP_CIPHER_CTX **ctx)
+{
+	if (data.key_size == 16)
+		EVP_DecryptInit_ex(*ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
+	else if (data.key_size == 24)
+		EVP_DecryptInit_ex(*ctx, EVP_aes_192_ccm(), NULL, NULL, NULL);
+	else if (data.key_size == 32)
+		EVP_DecryptInit_ex(*ctx, EVP_aes_256_ccm(), NULL, NULL, NULL);
+}
+int ccm_encrypt(void)
+{
+	EVP_CIPHER_CTX *ctx;
+	int outlen;
+	unsigned char outbuf[1024];
+
+	ctx = EVP_CIPHER_CTX_new();
+	init_ccm_evp_encrypt(&ctx);
+
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, data.nonce_size, NULL);
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, data.tag_size, NULL);
+	EVP_EncryptInit_ex(ctx, NULL, NULL, data.key, data.nonce);
+
+	EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, data.payload_size);
+	if (data.adata != NULL)
+		EVP_EncryptUpdate(ctx, NULL, &outlen, data.adata, data.adata_size);
+	if (data.payload != NULL) {
+		EVP_EncryptUpdate(ctx, outbuf, &outlen, data.payload, data.payload_size);
+		printf("Ciphertext: ");
+		print_hex(outbuf, outlen);
+	}
+	EVP_EncryptFinal_ex(ctx, outbuf, &outlen);
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, data.tag_size, outbuf);
+	printf("Tags: ");
+	print_hex(outbuf, data.tag_size);
+	EVP_CIPHER_CTX_free(ctx);
+	return 0;
+}
+
+int ccm_decrypt(void)
+{
+	EVP_CIPHER_CTX *ctx;
+	int outlen, rv;
+	unsigned char outbuf[1024];
+
+	ctx = EVP_CIPHER_CTX_new();
+
+	init_ccm_evp_decrypt(&ctx);
+
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, data.nonce_size, NULL);
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, data.tag_size, data.tag);
+	EVP_DecryptInit_ex(ctx, NULL, NULL, data.key, data.nonce);
+	EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, data.ct_size);
+
+	if (data.adata != NULL)
+		EVP_DecryptUpdate(ctx, NULL, &outlen, data.adata, data.adata_size);
+
+	if (data.ct == NULL)
+		rv = EVP_DecryptUpdate(ctx, outbuf, &outlen, "", data.ct_size);
+	else
+		rv = EVP_DecryptUpdate(ctx, outbuf, &outlen, data.ct, data.ct_size);
+
+	if (rv > 0) {
+		printf("Tag Verify: Pass\n");
+		if (data.ct != NULL) {
+			printf("Plaintext: ");
+			print_hex(outbuf, outlen);
+		}
+	} else {
+		printf("Tag Verify: Fail\n");
+	}
+
+	EVP_CIPHER_CTX_free(ctx);
+	return 0;
+}
+int ccm_uninit(void)
+{
+	free_openssl_data(data.key);
+	free_openssl_data(data.nonce);
+	free_openssl_data(data.adata);
+	free_openssl_data(data.payload);
+	free_openssl_data(data.ct);
+	free_openssl_data(data.tag);
+	return 0;
+}
+
+int ccm_check(void)
+{
+	if (data.key == NULL || data.nonce == NULL) {
+		printf("ccm must have Key and IV\n");
+		return -1;
+	}
+
+	if (input_data.oper == DECRYPT && data.tag == NULL) {
+		printf("ccm decrypt must have Tag\n");
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/feed/openssl-fips-ext/src/aesccm.h b/feed/openssl-fips-ext/src/aesccm.h
new file mode 100644
index 0000000..c52fcc6
--- /dev/null
+++ b/feed/openssl-fips-ext/src/aesccm.h
@@ -0,0 +1,28 @@
+#ifndef AESCCM_H
+#define AESCCM_H
+#include "common.h"
+int ccm_init(void);
+int ccm_uninit(void);
+int ccm_encrypt(void);
+int ccm_decrypt(void);
+int ccm_check(void);
+
+struct ccm_data {
+	unsigned char *key;
+	unsigned char *nonce;
+	unsigned char *adata;
+	unsigned char *payload;
+	unsigned char *ct;
+	unsigned char *tag;
+	long key_size;
+	long nonce_size;
+	long adata_size;
+	long payload_size;
+	long ct_size;
+	int tag_output_size;
+	long tag_size;
+};
+
+extern struct operator ccm_oper;
+
+#endif
diff --git a/feed/openssl-fips-ext/src/aesgcm.c b/feed/openssl-fips-ext/src/aesgcm.c
new file mode 100644
index 0000000..5bbb2d9
--- /dev/null
+++ b/feed/openssl-fips-ext/src/aesgcm.c
@@ -0,0 +1,138 @@
+#include "aesgcm.h"
+#include "openssl/crypto.h"
+
+struct operator gcm_oper = {
+	.init = gcm_init,
+	.uninit = gcm_uninit,
+	.encrypt = gcm_encrypt,
+	.decrypt = gcm_decrypt,
+	.check = gcm_check,
+};
+
+static struct gcm_data data;
+
+int gcm_init(void)
+{
+	if (input_data.key == NULL || input_data.iv == NULL)
+		return -1;
+	hex2bin(&data.key, input_data.key, &(data.key_size));
+	hex2bin(&data.iv, input_data.iv, &(data.iv_size));
+	hex2bin(&data.pt, input_data.pt, &(data.pt_size));
+	hex2bin(&data.add, input_data.add, &(data.add_size));
+	hex2bin(&data.ct, input_data.ct, &(data.ct_size));
+	hex2bin(&data.tag, input_data.tag, &(data.tag_size));
+
+	if (input_data.tag_output_size != 0)
+		data.tag_output_size = input_data.tag_output_size;
+	else
+		data.tag_output_size = 16;
+
+	return 0;
+}
+
+void init_gcm_evp_encrypt(EVP_CIPHER_CTX **ctx)
+{
+	if (data.key_size == 16)
+		EVP_EncryptInit_ex(*ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+	else if (data.key_size == 24)
+		EVP_EncryptInit_ex(*ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
+	else if (data.key_size == 32)
+		EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
+}
+
+void init_gcm_evp_decrypt(EVP_CIPHER_CTX **ctx)
+{
+	if (data.key_size == 16)
+		EVP_DecryptInit_ex(*ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+	else if (data.key_size == 24)
+		EVP_DecryptInit_ex(*ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
+	else if (data.key_size == 32)
+		EVP_DecryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
+}
+
+int gcm_encrypt(void)
+{
+	EVP_CIPHER_CTX *ctx;
+	int outlen;
+	unsigned char outbuf[1024];
+
+	ctx = EVP_CIPHER_CTX_new();
+
+	init_gcm_evp_encrypt(&ctx);
+
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, data.iv_size, NULL);
+	EVP_EncryptInit_ex(ctx, NULL, NULL, data.key, data.iv);
+
+	if (data.add != NULL)
+		EVP_EncryptUpdate(ctx, NULL, &outlen, data.add, data.add_size);
+	if (data.pt != NULL) {
+		EVP_EncryptUpdate(ctx, outbuf, &outlen, data.pt, data.pt_size);
+		printf("Ciphertext: ");
+		print_hex(outbuf, outlen);
+	} else {
+		printf("Ciphertext: none\n");
+	}
+	EVP_EncryptFinal_ex(ctx, outbuf, &outlen);
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, data.tag_output_size, outbuf);
+
+	printf("Tag: ");
+	print_hex(outbuf, data.tag_output_size);
+
+	EVP_CIPHER_CTX_free(ctx);
+	return 0;
+}
+
+int gcm_decrypt(void)
+{
+	EVP_CIPHER_CTX *ctx;
+	int outlen, tmplen, rv;
+	unsigned char outbuf[1024];
+
+	ctx = EVP_CIPHER_CTX_new();
+
+	init_gcm_evp_decrypt(&ctx);
+
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, data.iv_size, NULL);
+	EVP_DecryptInit_ex(ctx, NULL, NULL, data.key, data.iv);
+
+	if (data.add != NULL)
+		EVP_DecryptUpdate(ctx, NULL, &outlen, data.add, data.add_size);
+	if (data.ct != NULL) {
+		EVP_DecryptUpdate(ctx, outbuf, &outlen, data.ct, data.ct_size);
+		printf("Plaintext: ");
+		print_hex(outbuf, outlen);
+	}
+
+	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, data.tag_size,
+			data.tag);
+	rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
+	printf("Tag Verify %s\n", rv > 0 ? "Pass" : "Fail");
+	EVP_CIPHER_CTX_free(ctx);
+	return 0;
+}
+
+int gcm_uninit(void)
+{
+	free_openssl_data(data.key);
+	free_openssl_data(data.iv);
+	free_openssl_data(data.pt);
+	free_openssl_data(data.add);
+	free_openssl_data(data.ct);
+	free_openssl_data(data.tag);
+	return 0;
+}
+
+int gcm_check(void)
+{
+	if (data.key == NULL || data.iv == NULL) {
+		printf("gcm must have Key and IV\n");
+		return -1;
+	}
+
+	if (input_data.oper == DECRYPT && data.tag == NULL) {
+		printf("gcm decrypt must have Tag\n");
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/feed/openssl-fips-ext/src/aesgcm.h b/feed/openssl-fips-ext/src/aesgcm.h
new file mode 100644
index 0000000..4cf6f2e
--- /dev/null
+++ b/feed/openssl-fips-ext/src/aesgcm.h
@@ -0,0 +1,28 @@
+#ifndef AESGCM_H
+#define AESGCM_H
+#include "common.h"
+int gcm_init(void);
+int gcm_encrypt(void);
+int gcm_decrypt(void);
+int gcm_uninit(void);
+int gcm_check(void);
+
+struct gcm_data {
+	unsigned char *key;
+	unsigned char *iv;
+	unsigned char *pt;
+	unsigned char *add;
+	unsigned char *ct;
+	unsigned char *tag;
+	long key_size;
+	long iv_size;
+	long pt_size;
+	long add_size;
+	long ct_size;
+	long tag_size;
+	int tag_output_size;
+};
+
+extern struct operator gcm_oper;
+
+#endif
diff --git a/feed/openssl-fips-ext/src/common.c b/feed/openssl-fips-ext/src/common.c
new file mode 100644
index 0000000..6ae5c11
--- /dev/null
+++ b/feed/openssl-fips-ext/src/common.c
@@ -0,0 +1,128 @@
+#include "common.h"
+#include "aesgcm.h"
+#include "aesccm.h"
+
+
+struct common_data input_data = {
+	.key = NULL,
+	.iv  = NULL,
+	.pt  = NULL,
+	.add = NULL,
+	.ct  = NULL,
+	.tag = NULL,
+	.nonce = NULL,
+	.adata = NULL,
+	.payload = NULL,
+	.key_len = 0,
+	.iv_len = 0,
+	.pt_len = 0,
+	.add_len = 0,
+	.ct_len = 0,
+	.tag_len = 0,
+	.nonce_len = 0,
+	.adata_len = 0,
+	.payload_len = 0,
+	.tag_output_size = 0,
+	.algo = -1,
+	.oper = -1,
+};
+
+ENGINE *setup_engine(void)
+{
+	ENGINE *e;
+
+	OpenSSL_add_all_algorithms();
+	ENGINE_load_builtin_engines();
+	e = ENGINE_by_id("devcrypto");
+
+	if (e == NULL) {
+		printf("engine error\n");
+		return NULL;
+	}
+	if (!ENGINE_init(e)) {
+		printf("error2\n");
+		ENGINE_free(e);
+		return NULL;
+	}
+	return e;
+}
+
+void usage(void)
+{
+	printf(
+		"gcm and gcm tool:\n"
+		"gcm Operations:\n"
+		"-e              - encrypt\n"
+		"-d              - decrypt\n"
+		"Common requirement parameters:\n"
+		"-k key(hex)     - key in hex (must)\n"
+		"-i iv(hex)      - initial vector in hex (must)\n"
+		"-p plain (hex)  - plain text in hex\n"
+		"-c cipher(hex)  - cipher text in hex\n"
+		"-a aad(hex)     - additional authentication data in hex\n"
+		"-t tag(hex)     - tag in hex (decrypt must)\n"
+		"-g tag size(dec)- tag output size (default 16)\n"
+		"ccm Operation:\n"
+		"-k key(hex)     - key in hex (must)\n"
+		"-n nonce(hex)   - nonce in hex (must)\n"
+		"-f adata(hex)   - adata in hex\n"
+		"-l payload(hex) - payload in hex\n"
+		"-t encrypt size - tag size (must)\n"
+		"   decrypt tag  - tag (must)\n"
+		"tools: gcm or ccm\n"
+		"example:\n"
+		"gcm encrypt ./openssl-fips-ext -e -k data -i data ... gcm\n"
+		"gcm decrypt ./openssl-fips-ext -d -k data -i data -t data ... gcm\n"
+		"gcm encrypt ./openssl-fips-ext -e -k data -n data -t size ... ccm\n"
+		"gcm encrypt ./openssl-fips-ext -d -k data -n data -t data ... ccm\n");
+}
+
+void init_algo_data(void)
+{
+	if (input_data.algo == GCM)
+		cur.oper = gcm_oper;
+	else if (input_data.algo == CCM)
+		cur.oper = ccm_oper;
+}
+
+void do_operation(void)
+{
+	cur.oper.init();
+
+	if (cur.oper.check()) {
+		printf("Input error\n");
+		return;
+	}
+
+	if (input_data.oper == ENCRYPT)
+		cur.oper.encrypt();
+	else if (input_data.oper == DECRYPT)
+		cur.oper.decrypt();
+
+	cur.oper.uninit();
+}
+
+void hex2bin(unsigned char **des, char *src, long *len)
+{
+	if (src != NULL) {
+		*des = OPENSSL_hexstr2buf(src, len);
+		if (*des == NULL)
+			printf("openssl str to buf error\n");
+	} else {
+		*des = NULL;
+		*len = 0;
+	}
+}
+
+void print_hex(unsigned char *str, int len)
+{
+	for (int i = 0; i < len; i++)
+		printf("%02x", str[i]);
+	printf("\n");
+}
+
+void free_openssl_data(unsigned char *data)
+{
+	if (data != NULL)
+		OPENSSL_free(data);
+}
diff --git a/feed/openssl-fips-ext/src/common.h b/feed/openssl-fips-ext/src/common.h
new file mode 100644
index 0000000..d0d3979
--- /dev/null
+++ b/feed/openssl-fips-ext/src/common.h
@@ -0,0 +1,69 @@
+#ifndef COMMON_H
+#define COMMON_H
+#include <stddef.h>
+#define DECRYPT 0
+#define ENCRYPT 1
+#define GCM 0
+#define CCM 1
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/engine.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/safestack.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+
+ENGINE *setup_engine(void);
+void init_alog_data(void);
+void usage(void);
+void init_algo_data(void);
+void do_operation(void);
+void hex2bin(unsigned char **des, char *src, long *len);
+void print_hex(unsigned char *str, int len);
+void free_openssl_data(unsigned char *data);
+
+struct common_data {
+	char *key;
+	char *iv;
+	char *pt;
+	char *add;
+	char *ct;
+	char *tag;
+	char *nonce;
+	char *adata;
+	char *payload;
+	int key_len;
+	int iv_len;
+	int pt_len;
+	int add_len;
+	int ct_len;
+	int tag_len;
+	int nonce_len;
+	int adata_len;
+	int payload_len;
+	int algo;
+	int oper;
+	int tag_output_size;
+};
+
+struct operator {
+	int (*init)(void);
+	int (*uninit)(void);
+	int (*encrypt)(void);
+	int (*decrypt)(void);
+	int (*check)(void);
+};
+
+struct algorithm_data {
+	struct operator oper;
+	void *data;
+} cur;
+
+extern struct common_data input_data;
+
+#endif
diff --git a/feed/openssl-fips-ext/src/main.c b/feed/openssl-fips-ext/src/main.c
new file mode 100644
index 0000000..548a9f3
--- /dev/null
+++ b/feed/openssl-fips-ext/src/main.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/engine.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/safestack.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "aesgcm.h"
+#include "aesccm.h"
+
+int main(int argc, char **argv)
+{
+	ENGINE *e;
+	int opt;
+
+	e = setup_engine();
+	if (e == NULL) {
+		printf("engine set error\n");
+		return 0;
+	}
+
+	while ((opt = getopt(argc, argv, "a:c:def:i:k:l:n:p:t:g:")) > 0) {
+		switch (opt) {
+		case 'a':
+			input_data.add = optarg;
+			input_data.add_len = strlen(optarg);
+			break;
+		case 'd':
+			input_data.oper = DECRYPT;
+			break;
+		case 'e':
+			input_data.oper = ENCRYPT;
+			break;
+		case 'i':
+			input_data.iv = optarg;
+			input_data.iv_len = strlen(optarg);
+			break;
+		case 'k':
+			input_data.key = optarg;
+			input_data.key_len = strlen(optarg);
+			if (!(input_data.key_len == 32 || input_data.key_len == 48
+					|| input_data.key_len == 64)) {
+				printf("Key size must be 128, 192 or 256 .\n");
+				return 0;
+			}
+		case 'n':
+			input_data.nonce = optarg;
+			input_data.nonce_len = strlen(optarg);
+			break;
+		case 'c':
+			input_data.ct = optarg;
+			input_data.ct_len = strlen(optarg);
+			break;
+		case 't':
+			input_data.tag = optarg;
+			input_data.tag_len = strlen(optarg);
+			break;
+		case 'f':
+			input_data.adata = optarg;
+			input_data.adata_len = strlen(optarg);
+			break;
+		case 'l':
+			input_data.payload = optarg;
+			input_data.payload_len = strlen(optarg);
+			break;
+		case 'p':
+			input_data.pt = optarg;
+			input_data.pt_len = strlen(optarg);
+			break;
+		case 'g':
+			input_data.tag_output_size = atoi(optarg);
+			break;
+		case '?':
+			usage();
+		default:
+			break;
+		}
+
+	}
+	if (argc > optind) {
+		if (strncmp("gcm", argv[optind], 3) == 0) {
+			input_data.algo = GCM;
+		} else if (strncmp("ccm", argv[optind], 3) == 0) {
+			input_data.algo = CCM;
+		} else {
+			printf("parameter error !!\n");
+			usage();
+			return 0;
+		}
+	} else {
+		printf("select algorithm gcm or ccm\n");
+		usage();
+		return 0;
+	}
+	init_algo_data();
+	do_operation();
+
+	return 0;
+}