SmartAudio/package/libs/openssl/patches/201-openssl_add_af_alg.patch

3476 lines
91 KiB
Diff

diff -Naur openssl-1.0.2h/engines/e_af_alg.c openssl-1.0.2h-new/engines/e_af_alg.c
--- openssl-1.0.2h/engines/e_af_alg.c 1970-01-01 08:00:00.000000000 +0800
+++ openssl-1.0.2h-new/engines/e_af_alg.c 2018-01-06 15:30:56.000000000 +0800
@@ -0,0 +1,3415 @@
+/* Written by Markus Koetter (nepenthesdev@gmail.com) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+#include <memory.h>
+#include <errno.h>
+
+#include <openssl/aes.h>
+#include <openssl/engine.h>
+#include <sys/socket.h>
+#include <linux/if_alg.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#include "openssl/md5.h"
+#include "openssl/des.h"
+#include "openssl/ecdh.h"
+#include "openssl/ossl_typ.h"
+#include "../crypto/ecdh/ech_locl.h"
+#include "../crypto/ec/ec_lcl.h"
+#include "../crypto/ecdsa/ecs_locl.h"
+
+#ifdef SUPPORT_CE_V3_2
+#pragma message("The version of CE is V3.2.")
+#endif
+
+/* Define the capability of SS controller. */
+
+#define SS_CTR_MODE_ENABLE 1
+//#define SS_CTS_MODE_ENABLE 1
+#define SS_OFB_MODE_ENABLE 1
+#define SS_CFB_MODE_ENABLE 1
+#define SS_XTS_MODE_ENABLE 1
+#define SS_SHA224_ENABLE 1
+#define SS_SHA256_ENABLE 1
+#define SS_SHA384_ENABLE 1
+#define SS_SHA512_ENABLE 1
+#define SS_HMAC_SHA1_ENABLE 1
+#define SS_HMAC_SHA256_ENABLE 1
+#define SS_RSA_ENABLE 1
+#define SS_DH_ENABLE 1
+#define SS_ECC_ENABLE 1
+
+#if 0
+#define E_DEBUG_FLAG
+#define E_DBG(string, args...) \
+ do { \
+ printf("%s()%u---", __func__, __LINE__); \
+ printf(string, ##args); \
+ } while (0)
+#else
+#define E_DBG(string, args...) \
+ do { \
+ } while (0)
+#endif
+
+#define E_ERR(string, args...) \
+ do { \
+ printf("%s()%u---", __func__, __LINE__); \
+ printf(string, ##args); \
+ } while (0)
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+/* Socket options */
+#define ALG_SET_KEY 1
+#define ALG_SET_IV 2
+#define ALG_SET_OP 3
+
+/* Operations */
+#define ALG_OP_DECRYPT 0
+#define ALG_OP_ENCRYPT 1
+
+#define AES_KEY_SIZE_128 16
+#define AES_KEY_SIZE_192 24
+#define AES_KEY_SIZE_256 32
+
+#define RSA_MAX_LEN 4096
+
+static const EVP_MD af_alg_md_hmac_sha1;
+static const EVP_MD af_alg_md_hmac_sha256;
+
+static int af_alg_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+static int af_alg_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
+
+#define DYNAMIC_ENGINE
+#define AF_ALG_ENGINE_ID "af_alg"
+#define AF_ALG_ENGINE_NAME "use AF_ALG for AES crypto"
+
+void print_hex(void *_data, int _len, int _addr)
+{
+#ifdef E_DEBUG_FLAG
+ int i;
+ unsigned char *data = (unsigned char *)_data;
+
+ printf("-------------------- The valid len = %d ----------------------- \n", _len);
+ for (i=0; i<(_len+7)/8; i++) {
+ printf("0x%08X: %02X %02X %02X %02X %02X %02X %02X %02X \n", i*8 + _addr,
+ data[i*8+0], data[i*8+1], data[i*8+2], data[i*8+3],
+ data[i*8+4], data[i*8+5], data[i*8+6], data[i*8+7]);
+ }
+ printf("-------------------------------------------------------------- \n");
+#endif
+}
+
+static bool nid_in_nids(int nid, int nids[], int num)
+{
+ int i=0;
+ for( i=0;i<num;i++ )
+ if( nids[i] == nid )
+ return true;
+ return false;
+}
+
+struct af_alg_cipher_data
+{
+ int tfmfd;
+ int op;
+ __u32 type;
+};
+
+struct af_alg_digest_data
+{
+#if defined(SS_HMAC_SHA1_ENABLE) || defined(SS_HMAC_SHA256_ENABLE)
+ char key[SHA_CBLOCK];
+ int keylen;
+#endif
+ int tfmfd;
+ int opfd;
+};
+
+static int af_alg_cipher_all_nids[] = {
+ NID_aes_128_ecb,
+ NID_aes_192_ecb,
+ NID_aes_256_ecb,
+ NID_aes_128_cbc,
+ NID_aes_192_cbc,
+ NID_aes_256_cbc,
+#ifdef SS_CTR_MODE_ENABLE
+ NID_aes_128_ctr,
+ NID_aes_192_ctr,
+ NID_aes_256_ctr,
+#endif
+#ifdef SS_CTS_MODE_ENABLE
+ NID_aes_128_cts,
+ NID_aes_192_cts,
+ NID_aes_256_cts,
+#endif
+#ifdef SS_XTS_MODE_ENABLE
+ NID_aes_128_xts,
+ NID_aes_256_xts,
+#endif
+#ifdef SS_CFB_MODE_ENABLE
+ NID_aes_128_cfb1,
+ NID_aes_192_cfb1,
+ NID_aes_256_cfb1,
+ NID_aes_128_cfb8,
+ NID_aes_192_cfb8,
+ NID_aes_256_cfb8,
+ NID_aes_128_cfb128,
+ NID_aes_192_cfb128,
+ NID_aes_256_cfb128,
+#endif
+#ifdef SS_OFB_MODE_ENABLE
+ NID_aes_128_ofb128,
+ NID_aes_192_ofb128,
+ NID_aes_256_ofb128,
+#endif
+ NID_des_ecb,
+ NID_des_cbc,
+ NID_des_ede3_ecb,
+ NID_des_ede3_cbc,
+};
+static int af_alg_cipher_all_nids_num = (sizeof(af_alg_cipher_all_nids)/sizeof(af_alg_cipher_all_nids[0]));
+static int *af_alg_cipher_nids = NULL;
+static int af_alg_cipher_nids_num = 0;
+
+static int af_alg_digest_all_nids[] = {
+ NID_sha1,
+ NID_sha224,
+ NID_sha256,
+ NID_sha384,
+ NID_sha512,
+ NID_md5,
+ NID_hmac_sha1,
+ NID_hmacWithSHA256,
+};
+static int af_alg_digest_all_nids_num = sizeof(af_alg_digest_all_nids)/sizeof(af_alg_digest_all_nids[0]);
+static int *af_alg_digest_nids = NULL;
+static int af_alg_digest_nids_num = 0;
+
+#define SS_RAND_SEED_DEFAULT_LEN 24
+struct af_alg_digest_data af_alg_rand_ctx;
+
+void af_alg_rand_init(char *buf, int num)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "rng",
+ .salg_name = "prng",
+ };
+
+ memset(&af_alg_rand_ctx, 0, sizeof(struct af_alg_digest_data));
+ af_alg_rand_ctx.tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if(af_alg_rand_ctx.tfmfd == -1) {
+ E_ERR("socket() failed! [%d]: %s\n", errno, strerror(errno));
+ return;
+ }
+
+ if (bind(af_alg_rand_ctx.tfmfd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
+ E_ERR("bind() failed! [%d]: %s\n", errno, strerror(errno));
+ return;
+ }
+
+ if (buf != NULL)
+ if (setsockopt(af_alg_rand_ctx.tfmfd, SOL_ALG, ALG_SET_KEY, buf, num) == -1) {
+ E_ERR("setsockopt() failed! [%d]: %s\n", errno, strerror(errno));
+ return;
+ }
+
+ af_alg_rand_ctx.opfd = accept(af_alg_rand_ctx.tfmfd, NULL, 0);
+ if (af_alg_rand_ctx.opfd == -1 ) {
+ E_ERR("accept() failed! [%d]: %s\n", errno, strerror(errno));
+ return;
+ }
+
+}
+
+void af_alg_rand_exit(void)
+{
+ close(af_alg_rand_ctx.opfd);
+ af_alg_rand_ctx.opfd = -1;
+
+ close(af_alg_rand_ctx.tfmfd);
+ af_alg_rand_ctx.tfmfd = -1;
+}
+
+void af_alg_seed(const void *buf, int num)
+{
+ E_DBG("Seed len = %d\n", num);
+ if (af_alg_rand_ctx.opfd < 2)
+ af_alg_rand_init((char *)buf, num);
+}
+
+static int af_alg_rand(unsigned char *buf, int len)
+{
+ ssize_t r = 0;
+
+ if (af_alg_rand_ctx.opfd < 2)
+ af_alg_rand_init(NULL, SS_RAND_SEED_DEFAULT_LEN);
+
+ r = read(af_alg_rand_ctx.opfd, buf, len);
+ E_DBG("read(%d) return %zd \n", len, r);
+ if (r != len) {
+ E_ERR("read() return %d. [%d]: %s\n", (int)r, errno, strerror(errno));
+// return 0;
+ }
+ E_DBG("%02x %02x %02x %02x %02x %02x %02x %02x \n",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+ af_alg_rand_exit();
+ return 1;
+}
+
+static int af_alg_rand_status(void)
+{
+ return 1;
+}
+
+static RAND_METHOD af_alg_random =
+{
+ af_alg_seed,
+ af_alg_rand,
+ NULL,
+ NULL,
+ af_alg_rand,
+ af_alg_rand_status,
+};
+
+#if defined(SS_RSA_ENABLE) || defined(SS_DH_ENABLE) || defined(SS_ECC_ENABLE)
+#define ECC521_SIZE (((521+31)/32)*4)
+#define ECC256_SIZE (((256+31)/32)*4)
+#define ECC224_SIZE (((224+31)/32)*4)
+#define ECC160_SIZE (((160+31)/32)*4)
+
+void af_alg_convert_byte(unsigned char *data, int len)
+{
+ int i;
+ unsigned char *buf = NULL;
+
+ buf = OPENSSL_malloc(len);
+ if (buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", len);
+ return;
+ }
+
+ for (i=0; i<len; i++)
+ buf[i] = data[len - 1 - i];
+
+ memcpy(data, buf, len);
+ OPENSSL_free(buf);
+}
+
+int af_alg_asym_sock_init(struct af_alg_cipher_data *ctx, const BIGNUM *key, int size, char *name, int type)
+{
+ char key_str[RSA_MAX_LEN/8] = {0};
+
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ };
+
+ E_DBG("name = %s, size = %d, type = %d \n", name, size, type);
+ if (size > RSA_MAX_LEN/8) {
+ E_ERR("The len is too large: %d\n", size);
+ return -1;
+ }
+
+ if (type == NID_secp521r1)
+ snprintf((char *)sa.salg_name, 20, "%s(%d)", name, 521);
+ else
+ snprintf((char *)sa.salg_name, 20, "%s(%d)", name, size*8);
+
+ ctx->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if(ctx->tfmfd == -1) {
+ E_ERR("socket() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ if (bind(ctx->tfmfd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
+ E_ERR("bind(%s) failed! [%d]: %s\n", sa.salg_name, errno, strerror(errno));
+ return 0;
+ }
+
+ if (key != NULL) {
+ memcpy(key_str, (char *)key->d, BN_num_bytes(key));
+ if (setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_KEY, key_str, size) == -1) {
+ E_ERR("setsockopt() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+ }
+
+ ctx->op = accept(ctx->tfmfd, NULL, 0);
+ if (ctx->op == -1) {
+ E_ERR("accept() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifdef SS_RSA_ENABLE
+
+struct af_alg_cipher_data af_alg_rsa_ctx = {0, 0, 0};
+
+int af_alg_rsa_padding(unsigned char *out, int olen,
+ const unsigned char *in, int ilen, int padding)
+{
+ int ret = 0;
+
+ memset(out, 0, olen);
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ ret = RSA_padding_add_PKCS1_type_2(out, olen, in, ilen);
+ break;
+#ifndef OPENSSL_NO_SHA
+ case RSA_PKCS1_OAEP_PADDING:
+ ret = RSA_padding_add_PKCS1_OAEP(out, olen, in, ilen, NULL, 0);
+ break;
+#endif
+ case RSA_SSLV23_PADDING:
+ ret = RSA_padding_add_SSLv23(out, olen, in, ilen);
+ break;
+ case RSA_NO_PADDING:
+ ret = RSA_padding_add_none(out, ilen, in, ilen);
+ break;
+ default:
+ E_ERR("Invalid padding type: %d \n", padding);
+ break;
+ }
+
+ if (ret == 1)
+ af_alg_convert_byte(out, olen);
+
+ return ret;
+}
+
+int af_alg_rsa_unpadding(unsigned char *out, int olen,
+ const unsigned char *in, int ilen, int padding)
+{
+ int ret = 0;
+
+ switch (padding) {
+ case RSA_PKCS1_PADDING:
+ ret = RSA_padding_check_PKCS1_type_2(out, olen, in, ilen, olen);
+ break;
+#ifndef OPENSSL_NO_SHA
+ case RSA_PKCS1_OAEP_PADDING:
+ ret = RSA_padding_check_PKCS1_OAEP(out, olen, in, ilen, olen,NULL,0);
+ break;
+#endif
+ case RSA_SSLV23_PADDING:
+ ret = RSA_padding_check_SSLv23(out, olen, in, ilen, olen);
+ break;
+ case RSA_NO_PADDING:
+ ret = RSA_padding_check_none(out, olen, in, ilen, olen);
+ break;
+ default:
+ E_ERR("Invalid padding type: %d \n", padding);
+ break;
+ }
+
+ return ret;
+}
+
+#ifdef SUPPORT_CE_V3_2
+
+/* to = (from ^ rsa->e) mod rsa->n */
+int af_alg_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+{
+ int ret = 0;
+ int n_len = 0;
+ int n_len_align = 0;
+ unsigned char *inbuf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_rsa_ctx.type))];
+
+ if ((rsa->e == NULL) || (rsa->n == NULL)) {
+ E_ERR("Invalid e 0x%p or n 0x%p\n", rsa->e, rsa->n);
+ return 0;
+ }
+
+ n_len = BN_num_bytes(rsa->n);
+ n_len_align = ((n_len + 3)/4)*4;
+ if (flen > n_len) {
+ E_ERR("The input data is too long: %d/%d\n", flen, n_len);
+ return 0;
+ }
+
+ /* Key: NULL */
+ if (af_alg_asym_sock_init(&af_alg_rsa_ctx, NULL, n_len_align, "rsa", 0) == 0)
+ return 0;
+
+ /* Src: e-n-from */
+ inbuf = OPENSSL_malloc(n_len_align*3);
+ if (inbuf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", n_len_align*3);
+ return 0;
+ }
+ memset(inbuf, 0, n_len_align*3);
+ memcpy(inbuf, (char *)rsa->e->d, BN_num_bytes(rsa->e));
+ memcpy(&inbuf[n_len_align], (char *)rsa->n->d, BN_num_bytes(rsa->n));
+
+ af_alg_rsa_padding(&inbuf[n_len_align*2], n_len_align, from, flen, padding);
+
+ af_alg_rsa_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf);
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg),&af_alg_rsa_ctx.type, 4);
+
+ /* IV: NULL */
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ iov.iov_base = (void *)inbuf;
+ iov.iov_len = n_len_align*3;
+
+ ret = sendmsg(af_alg_rsa_ctx.op, &msg, 0);
+ if (ret == -1) {
+ OPENSSL_free(inbuf);
+ E_ERR("sendmsg(%d) failed! return %d\n", af_alg_rsa_ctx.op, ret);
+ return 0;
+ }
+
+ OPENSSL_free(inbuf);
+ ret = read(af_alg_rsa_ctx.op, to, n_len);
+ if (ret != n_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, n_len);
+ return 0;
+ }
+
+ af_alg_convert_byte(to, n_len);
+ return ret;
+}
+
+/* to = (from ^ rsa->d) mod rsa->n */
+int af_alg_rsa_priv_dec(int flen,const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+{
+ int ret = 0;
+ int n_len = 0;
+ int n_len_align = 0;
+ unsigned char *inbuf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_rsa_ctx.type))];
+
+ if ((rsa->d == NULL) || (rsa->n == NULL)) {
+ E_ERR("Invalid e 0x%p or n 0x%p\n", rsa->e, rsa->n);
+ return 0;
+ }
+
+ n_len = BN_num_bytes(rsa->n);
+ n_len_align = ((n_len + 3)/4)*4;
+ if (flen > n_len) {
+ E_ERR("The input data is too long: %d/%d\n", flen, n_len);
+ return 0;
+ }
+
+ /* Key: NULL */
+ if (af_alg_asym_sock_init(&af_alg_rsa_ctx, NULL, n_len_align, "rsa", 0) == 0)
+ return 0;
+
+ /* Src: d-n-from */
+ inbuf = OPENSSL_malloc(n_len_align*3);
+ if (inbuf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", n_len_align*3);
+ return 0;
+ }
+ memset(inbuf, 0, n_len_align*3);
+ memcpy(inbuf, (char *)rsa->d->d, BN_num_bytes(rsa->d));
+ memcpy(&inbuf[n_len_align], (char *)rsa->n->d, BN_num_bytes(rsa->n));
+ memcpy(&inbuf[n_len_align*2], from, n_len_align);
+ af_alg_convert_byte(&inbuf[n_len_align*2], n_len_align);
+
+ af_alg_rsa_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf);
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg),&af_alg_rsa_ctx.type, 4);
+
+ /* IV: NULL */
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ iov.iov_base = (void *)inbuf;
+ iov.iov_len = n_len_align*3;
+
+ ret = sendmsg(af_alg_rsa_ctx.op, &msg, 0);
+ if (ret == -1) {
+ OPENSSL_free(inbuf);
+ E_ERR("sendmsg(%d) failed! return %d\n", af_alg_rsa_ctx.op, ret);
+ return 0;
+ }
+
+ OPENSSL_free(inbuf);
+ ret = read(af_alg_rsa_ctx.op, to, n_len);
+ if (ret != n_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, n_len);
+ return 0;
+ }
+
+ af_alg_convert_byte(to, n_len);
+ return ret;
+}
+
+#else
+
+/* to = (from ^ rsa->e) mod rsa->n */
+int af_alg_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+{
+ int ret = 0;
+ int n_len = 0;
+ unsigned char *inbuf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = RSA_MAX_LEN/8; /* Maximum length of RSA key. */
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_rsa_ctx.type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+
+ if ((rsa->e == NULL) || (rsa->n == NULL)) {
+ E_ERR("Invalid e 0x%p or n 0x%p\n", rsa->e, rsa->n);
+ return 0;
+ }
+
+ n_len = BN_num_bytes(rsa->n);
+ if (flen > n_len) {
+ E_ERR("The input data is too long: %d/%d\n", flen, n_len);
+ return 0;
+ }
+
+ /* Key: rsa->e */
+ if (af_alg_asym_sock_init(&af_alg_rsa_ctx, rsa->e, n_len, "rsa", 0) == 0)
+ return 0;
+
+ /* Src: from */
+ inbuf = OPENSSL_malloc(n_len);
+ if (inbuf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", n_len);
+ return 0;
+ }
+ af_alg_rsa_padding(inbuf, n_len, from, flen, padding);
+
+ af_alg_rsa_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf) - iv_len + n_len;
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg),&af_alg_rsa_ctx.type, 4);
+
+ /* Set IV: rsa->n */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + n_len);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = n_len;
+ memcpy(ivm->iv, rsa->n->d, n_len);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)inbuf;
+ iov.iov_len = n_len;
+
+ ret = sendmsg(af_alg_rsa_ctx.op, &msg, 0);
+ if (ret == -1) {
+ OPENSSL_free(inbuf);
+ E_ERR("sendmsg(%d) failed! return %d\n", af_alg_rsa_ctx.op, ret);
+ return 0;
+ }
+
+ OPENSSL_free(inbuf);
+ ret = read(af_alg_rsa_ctx.op, to, n_len);
+ if (ret != n_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, n_len);
+ return 0;
+ }
+
+ af_alg_convert_byte(to, n_len);
+ return ret;
+}
+
+/* to = (from ^ rsa->d) mod rsa->n */
+int af_alg_rsa_priv_dec(int flen,const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+{
+ int ret = 0;
+ int n_len = 0;
+ unsigned char *inbuf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = RSA_MAX_LEN/8; /* Maximum length of RSA key. */
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_rsa_ctx.type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+
+ if ((rsa->d == NULL) || (rsa->n == NULL)) {
+ E_ERR("Invalid e 0x%p or n 0x%p\n", rsa->e, rsa->n);
+ return 0;
+ }
+
+ n_len = BN_num_bytes(rsa->n);
+ if (flen > n_len) {
+ E_ERR("The input data is too long: %d/%d\n", flen, n_len);
+ return 0;
+ }
+
+ /* Key: rsa->d */
+ if (af_alg_asym_sock_init(&af_alg_rsa_ctx, rsa->d, n_len, "rsa", 0) == 0)
+ return 0;
+
+ /* Src: from */
+ inbuf = OPENSSL_malloc(n_len);
+ if (inbuf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", n_len);
+ return 0;
+ }
+ memcpy(inbuf, from, n_len);
+ af_alg_convert_byte(inbuf, n_len);
+
+ af_alg_rsa_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf) - iv_len + n_len;
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg),&af_alg_rsa_ctx.type, 4);
+
+ /* Set IV: rsa->n */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + n_len);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = n_len;
+ memcpy(ivm->iv, rsa->n->d, n_len);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)inbuf;
+ iov.iov_len = n_len;
+
+ ret = sendmsg(af_alg_rsa_ctx.op, &msg, 0);
+ if (ret == -1) {
+ OPENSSL_free(inbuf);
+ E_ERR("sendmsg(%d) failed! return %d\n", af_alg_rsa_ctx.op, ret);
+ return 0;
+ }
+
+ OPENSSL_free(inbuf);
+ ret = read(af_alg_rsa_ctx.op, to, n_len);
+ if (ret != n_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, n_len);
+ return 0;
+ }
+ af_alg_convert_byte(to, n_len);
+
+ return ret;
+}
+#endif
+
+int af_alg_rsa_init(RSA *rsa)
+{
+ memset(&af_alg_rsa_ctx, 0, sizeof(struct af_alg_cipher_data));
+ return 1;
+}
+
+int af_alg_rsa_finish(RSA *rsa)
+{
+ if (af_alg_rsa_ctx.tfmfd > 0)
+ close(af_alg_rsa_ctx.tfmfd);
+ if (af_alg_rsa_ctx.op > 0)
+ close(af_alg_rsa_ctx.op);
+ return 1;
+}
+
+static RSA_METHOD af_alg_rsa =
+ {
+ "Af_alg RSA method",
+ af_alg_rsa_pub_enc,
+ NULL,
+ NULL,
+ af_alg_rsa_priv_dec,
+ NULL,
+ NULL,
+ af_alg_rsa_init,
+ af_alg_rsa_finish,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+#endif
+
+#ifdef SS_DH_ENABLE
+
+struct af_alg_cipher_data af_alg_dh_ctx = {0, 0, 0};
+
+static int af_alg_dh_generate_key(DH *dh)
+{
+ DH_METHOD *dh_pub = (DH_METHOD *)DH_OpenSSL();
+ return dh_pub->generate_key(dh);
+}
+
+static int af_alg_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+{
+ DH_METHOD *dh_pub = (DH_METHOD *)DH_OpenSSL();
+ return dh_pub->compute_key(key, pub_key, dh);
+}
+
+int af_alg_dh_init(DH *dh)
+{
+ memset(&af_alg_dh_ctx, 0, sizeof(struct af_alg_cipher_data));
+ return 1;
+}
+
+int af_alg_dh_finish(DH *dh)
+{
+ if (af_alg_dh_ctx.tfmfd > 0) {
+ close(af_alg_dh_ctx.tfmfd);
+ af_alg_dh_ctx.tfmfd = 0;
+ }
+ if (af_alg_dh_ctx.op > 0) {
+ close(af_alg_dh_ctx.op);
+ af_alg_dh_ctx.op = 0;
+ }
+ return 1;
+}
+
+#ifdef SUPPORT_CE_V3_2
+/* r = (a ^ p) mod m */
+static int af_alg_dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx)
+{
+ int ret = 0;
+ int m_len = 0;
+ int m_len_align = 0;
+ unsigned char *inbuf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_dh_ctx.type))];
+
+ if ((r == NULL) || (a == NULL) || (p == NULL) || (m == NULL)) {
+ E_ERR("Invalid parameter: r: 0x%p, a: 0x%p, p: 0x%p, m: 0x%p\n", r, a, p, m);
+ return 0;
+ }
+
+ /* Key: NULL */
+ m_len = BN_num_bytes(m);
+ m_len_align = ((m_len + 3)/4)*4;
+ E_DBG("Len: r %d, a %d, p %d, m %d \n", BN_num_bytes(r), BN_num_bytes(a), BN_num_bytes(p), BN_num_bytes(m));
+
+ if (af_alg_asym_sock_init(&af_alg_dh_ctx, NULL, m_len_align, "dh", 0) == 0)
+ return 0;
+
+ /* Src: p-m-a */
+ inbuf = OPENSSL_malloc(m_len_align*3);
+ if (inbuf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", m_len);
+ return 0;
+ }
+ memset(inbuf, 0, m_len_align*3);
+ memcpy(inbuf, p->d, BN_num_bytes(p));
+ memcpy(&inbuf[m_len_align], (char *)m->d, BN_num_bytes(m));
+ memcpy(&inbuf[m_len_align*2], (char *)a->d, BN_num_bytes(a));
+
+ af_alg_dh_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf);
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_dh_ctx.type, 4);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)inbuf;
+ iov.iov_len = m_len_align*3;
+
+ ret = sendmsg(af_alg_dh_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ OPENSSL_free(inbuf);
+ return 0;
+ }
+
+ BN_copy(r, p);
+ ret = read(af_alg_dh_ctx.op, r->d, m_len);
+ if (ret != m_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, m_len);
+ return 0;
+ }
+ af_alg_dh_finish(NULL);
+
+ OPENSSL_free(inbuf);
+ return 1;
+}
+#else
+static int af_alg_dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx)
+{
+ int ret = 0;
+ int p_len = 0;
+ unsigned char *a_buf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = RSA_MAX_LEN/8; /* Maximum length of RSA key. */
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_dh_ctx.type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+
+ if ((r == NULL) || (a == NULL) || (p == NULL) || (m == NULL)) {
+ E_ERR("Invalid parameter: r: 0x%p, a: 0x%p, p: 0x%p, m: 0x%p\n", r, a, p, m);
+ return 0;
+ }
+ E_DBG("Len: r %d, a %d, p %d, m %d \n", BN_num_bytes(r), BN_num_bytes(a),
+ BN_num_bytes(p), BN_num_bytes(m));
+
+ /* Key: p */
+ p_len = BN_num_bytes(p);
+ if (af_alg_asym_sock_init(&af_alg_dh_ctx, p, p_len, "dh", 0) == 0)
+ return 0;
+
+ /* Src: a */
+ a_buf = OPENSSL_malloc(p_len);
+ if (a_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", p_len);
+ return 0;
+ }
+ memset(a_buf, 0, p_len);
+ memcpy(a_buf, a->d, BN_num_bytes(a));
+
+ af_alg_dh_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf) - iv_len + p_len;
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_dh_ctx.type, 4);
+
+ /* Set IV: m */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + p_len);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = p_len;
+ memcpy(ivm->iv, m->d, p_len);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)a_buf;
+ iov.iov_len = p_len;
+
+ ret = sendmsg(af_alg_dh_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ OPENSSL_free(a_buf);
+ return 0;
+ }
+
+ BN_copy(r, p);
+ ret = read(af_alg_dh_ctx.op, r->d, p_len);
+ if (ret != p_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, p_len);
+ return 0;
+ }
+
+ af_alg_dh_finish(NULL);
+
+ OPENSSL_free(a_buf);
+ return 1;
+}
+#endif
+
+static DH_METHOD af_alg_dh = {
+ "Af_alg DH method",
+ af_alg_dh_generate_key,
+ af_alg_dh_compute_key,
+ af_alg_dh_bn_mod_exp,
+ af_alg_dh_init,
+ af_alg_dh_finish,
+ 0,
+ NULL,
+ NULL
+};
+#endif
+
+#ifdef SS_ECC_ENABLE
+
+struct af_alg_cipher_data af_alg_ecc_ctx = {0, 0, 0};
+
+static void af_alg_point2bin(const EC_GROUP *group, unsigned char *buf, const EC_POINT *p, BN_CTX *ctx, int step)
+{
+ BIGNUM *x_p = NULL;
+ BIGNUM *y_p = NULL;
+
+ x_p = BN_new();
+ y_p = BN_new();
+ if ((x_p == NULL) || (y_p == NULL)) {
+ E_ERR("Failed to malloc BN: x 0x%p, y 0x%p\n", x_p, y_p);
+ return;
+ }
+
+ if (!EC_POINT_get_affine_coordinates_GF2m(group, p, x_p, y_p, ctx)) {
+ E_ERR("Failed to get (X,Y) coordinate.\n");
+ return;
+ }
+ memcpy(buf, x_p->d, BN_num_bytes(x_p));
+ memcpy(buf+step, y_p->d, BN_num_bytes(y_p));
+
+ BN_free(x_p);
+ BN_free(y_p);
+}
+
+void af_alg_ecc_finish(void)
+{
+ if (af_alg_ecc_ctx.tfmfd > 0) {
+ close(af_alg_ecc_ctx.tfmfd);
+ af_alg_ecc_ctx.tfmfd = 0;
+ }
+ if (af_alg_ecc_ctx.op > 0) {
+ close(af_alg_ecc_ctx.op);
+ af_alg_ecc_ctx.op = 0;
+ }
+}
+
+int af_alg_get_ecc_size(int nid)
+{
+ switch (nid) {
+ case NID_secp160k1:
+ case NID_secp160r1:
+ case NID_secp160r2:
+ return ECC160_SIZE;
+ case NID_secp224k1:
+ case NID_secp224r1:
+ return ECC224_SIZE;
+ case NID_secp256k1:
+ case NID_X9_62_prime256v1:
+ return ECC256_SIZE;
+ case NID_secp521r1:
+ return ECC521_SIZE;
+ default:
+ E_ERR("Unsupported curve NID: %d\n", nid);
+ return 13; // make it failure quickly
+ }
+}
+
+#ifdef SUPPORT_CE_V3_2
+/* r = point * scalar */
+static int af_alg_POINT_mul(const EC_GROUP *group, EC_POINT *r,
+ const EC_POINT *point, const BIGNUM *scalar, BN_CTX *ctx)
+{
+ int ret = 0;
+ int ecc_size = 0;
+ unsigned char *src_buf = NULL;
+ unsigned char *dst_buf = NULL;
+ int src_len = 0;
+ int dst_len = 0;
+ BIGNUM *p=NULL, *a=NULL,*b=NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_ecc_ctx.type))];
+
+ /* Key: NULL */
+ ecc_size = af_alg_get_ecc_size(group->curve_name);
+ if (af_alg_asym_sock_init(&af_alg_ecc_ctx, NULL, ecc_size, "ecdh", group->curve_name) == 0) {
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_ECDH_LIB);
+ goto engine_err;
+ }
+ /* Src buf: field + scalar + group->a + point->x + point->y */
+ if ((ecc_size == ECC160_SIZE) || (ecc_size == ECC224_SIZE))
+ ecc_size +=4;
+ src_len = ecc_size*5;
+ src_buf = OPENSSL_malloc(src_len);
+ if (src_buf == NULL) {
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ goto buf_err;
+ }
+ if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || (b = BN_new()) == NULL)
+ {
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ goto bn_malloc_err;
+ }
+ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx))
+ {
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE);
+ goto bn_malloc_err;
+ }
+ memset(src_buf, 0, src_len);
+ memcpy(src_buf, p->d, BN_num_bytes(p));
+ memcpy(src_buf+ecc_size, scalar->d, BN_num_bytes(scalar));
+ memcpy(src_buf+ecc_size*2, a->d, BN_num_bytes(a));
+ af_alg_point2bin(group, src_buf+ecc_size*3, point, ctx, ecc_size);
+
+ /* Dst buf: r->x + r->y */
+ dst_len = ecc_size*2;
+ dst_buf = OPENSSL_malloc(dst_len);
+ if (dst_buf == NULL) {
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
+ goto dst_buf_err;
+ }
+ memset(dst_buf, 0, dst_len);
+
+ af_alg_ecc_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf);
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_ecc_ctx.type, 4);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)src_buf;
+ iov.iov_len = src_len;
+
+ ret = sendmsg(af_alg_ecc_ctx.op, &msg, 0);
+ if (ret == -1) {
+ ret = 0;
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE);
+ goto err;
+ }
+
+ ret = read(af_alg_ecc_ctx.op, dst_buf, dst_len);
+ if (ret != dst_len) {
+ ret = 0;
+ ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE);
+ goto err;
+ }
+ af_alg_convert_byte(dst_buf, ecc_size);
+ BN_bin2bn(dst_buf, ecc_size, &r->X);
+ af_alg_convert_byte(dst_buf+ecc_size, ecc_size);
+ BN_bin2bn(dst_buf+ecc_size, ecc_size, &r->Y);
+ ret = 1;
+
+err:
+ OPENSSL_free(dst_buf);
+dst_buf_err:
+ OPENSSL_free(src_buf);
+bn_malloc_err:
+ if (p)
+ BN_free(p);
+ if (a)
+ BN_free(a);
+ if (b)
+ BN_free(b);
+buf_err:
+ af_alg_ecc_finish();
+engine_err:
+ return ret;
+}
+
+#else
+/* r = point * scalar */
+static int af_alg_POINT_mul(const EC_GROUP *group, EC_POINT *r,
+ const EC_POINT *point, const BIGNUM *scalar, BN_CTX *ctx)
+{
+ int ret = 1;
+ int ecc_size = 0;
+ unsigned char *src_buf = NULL;
+ unsigned char *dst_buf = NULL;
+ int src_len = 0;
+ int dst_len = 0;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = RSA_MAX_LEN/8; /* Maximum length of RSA key. */
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_ecc_ctx.type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+
+ /* Key: p_scalar */
+ ecc_size = af_alg_get_ecc_size(group->curve_name);
+ if (af_alg_asym_sock_init(&af_alg_ecc_ctx, scalar, ecc_size, "ecdh", group->curve_name) == 0)
+ return 0;
+
+ /* Src buf: group->a + point->x + point->y */
+ src_len = ecc_size*3;
+ src_buf = OPENSSL_malloc(src_len);
+ if (src_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", src_len);
+ af_alg_ecc_finish();
+ return 0;
+ }
+ memset(src_buf, 0, src_len);
+ memcpy(src_buf, group->a.d, BN_num_bytes(&group->a));
+ af_alg_point2bin(group, src_buf+ecc_size, point, ctx, ecc_size);
+
+ /* Dst buf: r->x + r->y */
+ dst_len = ecc_size*2;
+ dst_buf = OPENSSL_malloc(dst_len);
+ if (dst_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", dst_len);
+ OPENSSL_free(src_buf);
+ af_alg_ecc_finish();
+ return 0;
+ }
+ memset(dst_buf, 0, dst_len);
+
+ af_alg_ecc_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf) - iv_len + ecc_size;
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_ecc_ctx.type, 4);
+
+ /* Set IV: group->field */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + ecc_size);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = ecc_size;
+ memcpy(ivm->iv, group->field.d, BN_num_bytes(&group->field));
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)src_buf;
+ iov.iov_len = src_len;
+
+ ret = sendmsg(af_alg_ecc_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ OPENSSL_free(src_buf);
+ OPENSSL_free(dst_buf);
+ af_alg_ecc_finish();
+ return 0;
+ }
+
+ ret = read(af_alg_ecc_ctx.op, dst_buf, dst_len);
+ if (ret != dst_len)
+ E_ERR("read() failed! return %d / %d\n", ret, dst_len);
+
+ af_alg_convert_byte(dst_buf, ecc_size);
+ BN_bin2bn(dst_buf, ecc_size, &r->X);
+ af_alg_convert_byte(dst_buf+ecc_size, ecc_size);
+ BN_bin2bn(dst_buf+ecc_size, ecc_size, &r->Y);
+
+ OPENSSL_free(src_buf);
+ OPENSSL_free(dst_buf);
+ af_alg_ecc_finish();
+ return 1;
+}
+#endif
+
+/** Computes r = generator * g_scalar + point * p_scalar
+ * r = point * p_scalar, if g_scalar = 0
+ * \param group underlying EC_GROUP object
+ * \param r EC_POINT object for the result
+ * \param g_scalar BIGNUM with the multiplier for the group generator (optional)
+ * \param point EC_POINT object with the first factor of the second summand
+ * \param p_scalar BIGNUM with the second factor of the second summand
+ * \param ctx BN_CTX object (optional)
+ * \return 1 on success and 0 if an error occured
+ */
+static int af_alg_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
+ const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
+{
+ int ret = 1;
+ EC_POINT *tmp = NULL;
+
+ if ((group == NULL) || (r == NULL) || (point == NULL) || (p_scalar == NULL)) {
+ E_ERR("Invalid parameter: group: 0x%p, r: 0x%p, point: 0x%p, p_scalar: 0x%p\n",
+ group, r, point, p_scalar);
+ return 0;
+ }
+ E_DBG("len: a: %d, b: %d, order: %d, point(%d, %d, %d), p_scalar: %d\n",
+ BN_num_bytes(&group->a), BN_num_bytes(&group->b), BN_num_bytes(&group->order),
+ BN_num_bytes(&point->X), BN_num_bytes(&point->Y), BN_num_bytes(&point->Z),
+ BN_num_bytes(p_scalar));
+
+ if ((tmp = EC_POINT_new(group)) == NULL) {
+ E_ERR("Failed to create point.\n");
+ return 1;
+ }
+
+ /* 1. tmp = point * p_scalar */
+ ret = af_alg_POINT_mul(group, tmp, point, p_scalar, ctx);
+ if (ret != 1)
+ return 0;
+
+ if (g_scalar == NULL) {
+ EC_POINT_copy(r, tmp);
+ EC_POINT_free(tmp);
+ return 1;
+ }
+
+ /* 2. r = group->generator * g_scalar */
+ ret = af_alg_POINT_mul(group, r, group->generator, g_scalar, ctx);
+ if (ret != 1)
+ goto af_alg_POINTs_mul_err;
+
+ EC_POINT_set_affine_coordinates_GF2m(group, r, &r->X, &r->Y, ctx);
+ EC_POINT_set_affine_coordinates_GF2m(group, tmp, &tmp->X, &tmp->Y, ctx);
+
+ /* 3. r = r + tmp */
+ ret = EC_POINT_add(group, r, r, tmp, ctx);
+ if (ret != 1)
+ goto af_alg_POINTs_mul_err;
+
+ EC_POINT_free(tmp);
+ return 1;
+
+af_alg_POINTs_mul_err:
+ EC_POINT_free(tmp);
+ return 0;
+}
+
+static int af_alg_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
+ EC_KEY *ecdh,
+ void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
+{
+ int ret = 1;
+ BN_CTX *ctx;
+ EC_POINT *tmp=NULL;
+ BIGNUM *x=NULL, *y=NULL;
+ const BIGNUM *priv_key;
+ const EC_GROUP* group;
+ size_t buflen, len;
+ unsigned char *buf=NULL;
+
+ if (outlen > INT_MAX)
+ {
+ E_ERR("The outlen is too large: %zd\n", outlen);
+ return -1;
+ }
+
+ if ((ctx = BN_CTX_new()) == NULL)
+ goto ecdh_err;
+ BN_CTX_start(ctx);
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+
+ priv_key = EC_KEY_get0_private_key(ecdh);
+ if (priv_key == NULL) {
+ E_ERR("Fail to call EC_KEY_get0_private_key()\n");
+ goto ecdh_err;
+ }
+
+ group = EC_KEY_get0_group(ecdh);
+ if ((tmp=EC_POINT_new(group)) == NULL) {
+ E_ERR("Failed to create point.\n");
+ goto ecdh_err;
+ }
+
+ if (!af_alg_POINTs_mul(group, tmp, NULL, pub_key, priv_key, ctx))
+ {
+ E_ERR("---\n");
+ goto ecdh_err;
+ }
+ BN_copy(x, &tmp->X);
+ BN_copy(y, &tmp->Y);
+
+ buflen = (EC_GROUP_get_degree(group) + 7)/8;
+ len = BN_num_bytes(x);
+ if (len > buflen)
+ {
+ E_ERR("---\n");
+ goto ecdh_err;
+ }
+ if ((buf = OPENSSL_malloc(buflen)) == NULL)
+ {
+ E_ERR("---\n");
+ goto ecdh_err;
+ }
+
+ memset(buf, 0, buflen - len);
+ if (len != (size_t)BN_bn2bin(x, buf + buflen - len))
+ {
+ E_ERR("---\n");
+ goto ecdh_err;
+ }
+
+ if (KDF != 0)
+ {
+ if (KDF(buf, buflen, out, &outlen) == NULL)
+ {
+ E_ERR("---\n");
+ goto ecdh_err;
+ }
+ ret = outlen;
+ }
+ else
+ {
+ /* no KDF, just copy as much as we can */
+ if (outlen > buflen)
+ outlen = buflen;
+ memcpy(out, buf, outlen);
+ ret = outlen;
+ }
+
+ecdh_err:
+ if (tmp) EC_POINT_free(tmp);
+ if (ctx) BN_CTX_end(ctx);
+ if (ctx) BN_CTX_free(ctx);
+ if (buf) OPENSSL_free(buf);
+ return ret;
+}
+
+static ECDH_METHOD af_alg_ecdh = {
+ "Af_alg ECDH method",
+ af_alg_ecdh_compute_key,
+ 0,
+ NULL
+};
+
+#ifdef SUPPORT_CE_V3_2
+
+/* r = (a * b) mod m */
+int af_alg_BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+ BN_CTX *ctx)
+{
+ int ret = 0;
+ int mod_mul_size = 0;
+ int src_len = 0;
+ unsigned char *src_buf = NULL;
+ unsigned char *dst_buf = NULL;
+
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_ecc_ctx.type))];
+
+ if ((r == NULL) || (a == NULL) || (b == NULL) || (m == NULL)) {
+ E_ERR("Invalid parameter: r: 0x%p, a: 0x%p, b: 0x%p, m: 0x%p\n", r, a, b, m);
+ return 0;
+ }
+ E_DBG("Len: r %d, a %d, b %d, m %d \n", BN_num_bytes(r), BN_num_bytes(a),
+ BN_num_bytes(b), BN_num_bytes(m));
+ bn_check_top(a);
+ bn_check_top(b);
+ bn_check_top(m);
+
+ mod_mul_size = BN_num_bytes(m) > 64 ? 128 : 64;
+
+ /* Key: NULL */
+ if (af_alg_asym_sock_init(&af_alg_ecc_ctx, NULL, mod_mul_size, "ecc_verify", 0) == 0)
+ return 0;
+
+ af_alg_ecc_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf);
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_ecc_ctx.type, 4);
+
+ /* Src: m + a + b */
+ src_len = mod_mul_size*3;
+ src_buf = OPENSSL_malloc(src_len);
+ if (src_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", src_len);
+ return 0;
+ }
+ memset(src_buf, 0, src_len);
+ memcpy(src_buf, m->d, BN_num_bytes(m));
+ memcpy(src_buf+mod_mul_size, a->d, BN_num_bytes(a));
+ memcpy(src_buf+mod_mul_size*2, b->d, BN_num_bytes(b));
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)src_buf;
+ iov.iov_len = src_len;
+
+ /* Dst: r */
+ dst_buf = OPENSSL_malloc(mod_mul_size);
+ if (dst_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", mod_mul_size);
+ return 0;
+ }
+ memset(dst_buf, 0, mod_mul_size);
+
+ ret = sendmsg(af_alg_ecc_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ return 0;
+ }
+
+ ret = read(af_alg_ecc_ctx.op, dst_buf, mod_mul_size);
+ if (ret != mod_mul_size) {
+ E_ERR("read() failed! return %d / %d\n", ret, mod_mul_size);
+ return 0;
+ }
+
+ BN_copy(r, m);
+ memcpy(r->d, dst_buf, BN_num_bytes(r));
+
+ OPENSSL_free(src_buf);
+ OPENSSL_free(dst_buf);
+ af_alg_ecc_finish();
+ bn_check_top(r);
+ return 1;
+}
+
+static ECDSA_SIG *af_alg_ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
+{
+ int ok = 0, i;
+ BIGNUM *kinv=NULL, *m=NULL,*tmp=NULL,*order=NULL;
+ BIGNUM *p=NULL, *a=NULL,*b=NULL;
+ const BIGNUM *ckinv;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group = NULL;
+ ECDSA_SIG *sig;
+ ECDSA_DATA *ecdsa;
+ const BIGNUM *priv_key;
+
+ int ret = 0;
+ int ecc_size = 0;
+ int src_len = 0;
+ int dst_len = 0;
+ unsigned char *src_buf = NULL;
+ unsigned char *dst_buf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_ecc_ctx.type))];
+
+ E_DBG("dgst: 0x%p, dgst_len: %d, in_kinv: 0x%p, in_r: 0x%p, eckey: 0x%p\n",
+ dgst, dgst_len, in_kinv, in_r, eckey);
+
+ ecdsa = ecdsa_check(eckey);
+ group = EC_KEY_get0_group(eckey);
+ priv_key = EC_KEY_get0_private_key(eckey);
+
+ if (group == NULL || priv_key == NULL || ecdsa == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ E_DBG("Len: priv_key %d, generator %d, a %d, order %d, field %d \n",
+ BN_num_bytes(priv_key), BN_num_bytes(&group->generator->X),
+ BN_num_bytes(&group->a), BN_num_bytes(&group->order), BN_num_bytes(&group->field));
+
+ sig = ECDSA_SIG_new();
+ if (!sig)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL
+ || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL
+ || (kinv = BN_new()) == NULL || (p = BN_new()) == NULL
+ || (a = BN_new()) == NULL || (b = BN_new()) == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_GROUP_get_order(group, order, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+ goto err;
+ }
+ if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+ goto err;
+ }
+ i = BN_num_bits(order);
+ E_DBG("order bits: %d\n", i);
+ /* Need to truncate digest if it is too long: first truncate whole
+ * bytes.
+ */
+ if (8 * dgst_len > i)
+ dgst_len = (i + 7)/8;
+ if (!BN_bin2bn(dgst, dgst_len, m))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* If still too long truncate remaining bits with a shift */
+ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (in_kinv == NULL || in_r == NULL) {
+ /* get random k */
+ do {
+ if (!BN_rand_range(kinv, order)) {
+ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
+ ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto err;
+ }
+ } while (BN_is_zero(kinv));
+ ckinv = kinv;
+ }
+ else {
+ ckinv = in_kinv;
+ if (BN_copy(sig->r, in_r) == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ ecc_size = af_alg_get_ecc_size(group->curve_name);
+
+ /* Key: NULL */
+ if (af_alg_asym_sock_init(&af_alg_ecc_ctx, NULL, ecc_size, "ecc_sign", group->curve_name) == 0)
+ return 0;
+
+ /* Src buf: kinv + group->field + group->a + generator->x + generator->y
+ + group->order + priv_key + dgst */
+ if ((ecc_size == ECC160_SIZE) || (ecc_size == ECC224_SIZE))
+ ecc_size +=4;
+ src_len = ecc_size*8;
+ src_buf = OPENSSL_malloc(src_len);
+ if (src_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", src_len);
+ goto err;
+ }
+ memset(src_buf, 0, src_len);
+ memcpy(src_buf, ckinv->d, BN_num_bytes(ckinv));
+ memcpy(src_buf+ecc_size, p->d, BN_num_bytes(p));
+ memcpy(src_buf+ecc_size*2, a->d, BN_num_bytes(a));
+ af_alg_point2bin(group, src_buf+ecc_size*3, group->generator, ctx, ecc_size);
+ memcpy(src_buf+ecc_size*5, order->d, BN_num_bytes(order));
+ memcpy(src_buf+ecc_size*6, priv_key->d, BN_num_bytes(priv_key));
+ if (ecc_size > dgst_len)
+ memcpy(src_buf+ecc_size*7, m->d, dgst_len); // Zero the high bit
+ else
+ memcpy(src_buf+ecc_size*7, m->d, ecc_size);
+
+ /* Dst buf: sig->r + sig->s */
+ dst_len = ecc_size*2;
+ dst_buf = OPENSSL_malloc(dst_len);
+ if (dst_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", dst_len);
+ goto err;
+ }
+ memset(dst_buf, 0, dst_len);
+
+ af_alg_ecc_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf);
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_ecc_ctx.type, 4);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)src_buf;
+ iov.iov_len = src_len;
+
+ ret = sendmsg(af_alg_ecc_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ goto err;
+ }
+
+ ret = read(af_alg_ecc_ctx.op, dst_buf, dst_len);
+ if (ret != dst_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, dst_len);
+ goto err;
+ }
+
+ E_DBG("The dst data: \n");
+ print_hex(dst_buf, dst_len, 0);
+
+ af_alg_convert_byte(dst_buf, ecc_size);
+ BN_bin2bn(dst_buf, ecc_size, sig->r);
+ af_alg_convert_byte(dst_buf+ecc_size, ecc_size);
+ BN_bin2bn(dst_buf+ecc_size, ecc_size, sig->s);
+
+ ok = 1;
+err:
+ if (src_buf)
+ OPENSSL_free(src_buf);
+ if (dst_buf)
+ OPENSSL_free(dst_buf);
+ af_alg_ecc_finish();
+
+ if (!ok)
+ {
+ ECDSA_SIG_free(sig);
+ sig = NULL;
+ }
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (m)
+ BN_clear_free(m);
+ if (tmp)
+ BN_clear_free(tmp);
+ if (order)
+ BN_free(order);
+ if (p)
+ BN_free(p);
+ if (a)
+ BN_free(a);
+ if (b)
+ BN_free(b);
+ if (kinv)
+ BN_clear_free(kinv);
+ return sig;
+}
+
+#else
+
+/* r = (a * b) mod m */
+int af_alg_BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+ BN_CTX *ctx)
+{
+ int ret = 0;
+ int mod_mul_size = 0;
+ int src_len = 0;
+ unsigned char *src_buf = NULL;
+ unsigned char *dst_buf = NULL;
+
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = RSA_MAX_LEN/8; /* Maximum length of RSA key. */
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_ecc_ctx.type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+
+ if ((r == NULL) || (a == NULL) || (b == NULL) || (m == NULL)) {
+ E_ERR("Invalid parameter: r: 0x%p, a: 0x%p, b: 0x%p, m: 0x%p\n", r, a, b, m);
+ return 0;
+ }
+ E_DBG("Len: r %d, a %d, b %d, m %d \n", BN_num_bytes(r), BN_num_bytes(a),
+ BN_num_bytes(b), BN_num_bytes(m));
+ bn_check_top(a);
+ bn_check_top(b);
+ bn_check_top(m);
+
+ mod_mul_size = BN_num_bytes(m) > 64 ? 128 : 64;
+
+ /* Key: NULL */
+ if (af_alg_asym_sock_init(&af_alg_ecc_ctx, NULL, mod_mul_size, "ecc_verify", 0) == 0)
+ return 0;
+
+ af_alg_ecc_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf) - iv_len + mod_mul_size;
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_ecc_ctx.type, 4);
+
+ /* Set IV: m */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + mod_mul_size);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = mod_mul_size;
+ memcpy(ivm->iv, m->d, BN_num_bytes(m));
+
+ /* Src: a + b */
+ src_len = mod_mul_size*2;
+ src_buf = OPENSSL_malloc(src_len);
+ if (src_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", src_len);
+ return 0;
+ }
+ memset(src_buf, 0, src_len);
+ memcpy(src_buf, a->d, BN_num_bytes(a));
+ memcpy(src_buf+mod_mul_size, b->d, BN_num_bytes(b));
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)src_buf;
+ iov.iov_len = src_len;
+
+ /* Dst: r */
+ dst_buf = OPENSSL_malloc(mod_mul_size);
+ if (dst_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", mod_mul_size);
+ return 0;
+ }
+ memset(dst_buf, 0, mod_mul_size);
+
+ ret = sendmsg(af_alg_ecc_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ return 0;
+ }
+
+ ret = read(af_alg_ecc_ctx.op, dst_buf, mod_mul_size);
+ if (ret != mod_mul_size) {
+ E_ERR("read() failed! return %d / %d\n", ret, mod_mul_size);
+ return 0;
+ }
+
+ BN_copy(r, m);
+ memcpy(r->d, dst_buf, BN_num_bytes(r));
+
+ OPENSSL_free(src_buf);
+ OPENSSL_free(dst_buf);
+ af_alg_ecc_finish();
+ bn_check_top(r);
+ return 1;
+}
+
+static ECDSA_SIG *af_alg_ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
+ const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
+{
+ int ok = 0, i;
+ BIGNUM *kinv=NULL, *m=NULL,*tmp=NULL,*order=NULL;
+ const BIGNUM *ckinv;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group = NULL;
+ ECDSA_SIG *sig;
+ ECDSA_DATA *ecdsa;
+ const BIGNUM *priv_key;
+
+ int ret = 0;
+ int ecc_size = 0;
+ int src_len = 0;
+ int dst_len = 0;
+ unsigned char *src_buf = NULL;
+ unsigned char *dst_buf = NULL;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = RSA_MAX_LEN/8; /* Maximum length of RSA key. */
+ char ivbuf[CMSG_SPACE(sizeof(af_alg_ecc_ctx.type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+
+ E_DBG("dgst: 0x%p, dgst_len: %d, in_kinv: 0x%p, in_r: 0x%p, eckey: 0x%p\n",
+ dgst, dgst_len, in_kinv, in_r, eckey);
+
+ ecdsa = ecdsa_check(eckey);
+ group = EC_KEY_get0_group(eckey);
+ priv_key = EC_KEY_get0_private_key(eckey);
+
+ if (group == NULL || priv_key == NULL || ecdsa == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ E_DBG("Len: priv_key %d, generator %d, a %d, order %d, field %d \n",
+ BN_num_bytes(priv_key), BN_num_bytes(&group->generator->X),
+ BN_num_bytes(&group->a), BN_num_bytes(&group->order), BN_num_bytes(&group->field));
+
+ sig = ECDSA_SIG_new();
+ if (!sig)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL
+ || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL
+ || (kinv = BN_new()) == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_GROUP_get_order(group, order, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+ goto err;
+ }
+ i = BN_num_bits(order);
+ E_DBG("order bits: %d\n", i);
+ /* Need to truncate digest if it is too long: first truncate whole
+ * bytes.
+ */
+ if (8 * dgst_len > i)
+ dgst_len = (i + 7)/8;
+ if (!BN_bin2bn(dgst, dgst_len, m))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* If still too long truncate remaining bits with a shift */
+ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (in_kinv == NULL || in_r == NULL) {
+ /* get random k */
+ do {
+ if (!BN_rand_range(kinv, order)) {
+ ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
+ ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto err;
+ }
+ } while (BN_is_zero(kinv));
+ ckinv = kinv;
+ }
+ else {
+ ckinv = in_kinv;
+ if (BN_copy(sig->r, in_r) == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ ecc_size = af_alg_get_ecc_size(group->curve_name);
+
+ /* Key: ckinv */
+ if (af_alg_asym_sock_init(&af_alg_ecc_ctx, ckinv, ecc_size, "ecc_sign", group->curve_name) == 0)
+ return 0;
+
+ /* Src buf: group->a + generator->x + generator->y + dgst + priv_key */
+ src_len = ecc_size*5;
+ src_buf = OPENSSL_malloc(src_len);
+ if (src_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", src_len);
+ goto err;
+ }
+ memset(src_buf, 0, src_len);
+ memcpy(src_buf, group->a.d, BN_num_bytes(&group->a));
+ af_alg_point2bin(group, src_buf+ecc_size, group->generator, ctx, ecc_size);
+ if (ecc_size > dgst_len)
+ memcpy(src_buf+ecc_size*3, m->d, dgst_len); // Zero the high bit
+ else
+ memcpy(src_buf+ecc_size*3, m->d, ecc_size);
+
+ memcpy(src_buf+ecc_size*4, priv_key->d, BN_num_bytes(priv_key));
+
+ /* Dst buf: (ckinv*generator)->x + (ckinv*generator)->y + sig->r + sig->s */
+ dst_len = ecc_size*4;
+ dst_buf = OPENSSL_malloc(dst_len);
+ if (dst_buf == NULL) {
+ E_ERR("Failed to OPENSSL_malloc(%d). \n", dst_len);
+ goto err;
+ }
+ memset(dst_buf, 0, dst_len);
+
+ af_alg_ecc_ctx.type = ALG_OP_ENCRYPT;
+ memset(ivbuf, 0, sizeof(ivbuf));
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = ivbuf;
+ msg.msg_controllen = sizeof(ivbuf) - iv_len + ecc_size*2;
+
+ /* Set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &af_alg_ecc_ctx.type, 4);
+
+ /* IV: group->order + group->field */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + ecc_size*2);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = ecc_size*2;
+ memcpy(ivm->iv, order->d, BN_num_bytes(order));
+ memcpy(ivm->iv+ecc_size, group->field.d, BN_num_bytes(&group->field));
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ iov.iov_base = (void *)src_buf;
+ iov.iov_len = src_len;
+
+ ret = sendmsg(af_alg_ecc_ctx.op, &msg, 0);
+ if (ret == -1) {
+ E_ERR("sendmsg() failed! return %d \n", ret);
+ goto err;
+ }
+
+ ret = read(af_alg_ecc_ctx.op, dst_buf, dst_len);
+ if (ret != dst_len) {
+ E_ERR("read() failed! return %d / %d\n", ret, dst_len);
+ goto err;
+ }
+
+ E_DBG("The dst data: \n");
+ print_hex(dst_buf, dst_len, 0);
+
+ af_alg_convert_byte(dst_buf+ecc_size*2, ecc_size);
+ BN_bin2bn(dst_buf+ecc_size*2, ecc_size, sig->r);
+ af_alg_convert_byte(dst_buf+ecc_size*3, ecc_size);
+ BN_bin2bn(dst_buf+ecc_size*3, ecc_size, sig->s);
+
+ ok = 1;
+err:
+ if (src_buf)
+ OPENSSL_free(src_buf);
+ if (dst_buf)
+ OPENSSL_free(dst_buf);
+ af_alg_ecc_finish();
+
+ if (!ok)
+ {
+ ECDSA_SIG_free(sig);
+ sig = NULL;
+ }
+ if (ctx)
+ BN_CTX_free(ctx);
+ if (m)
+ BN_clear_free(m);
+ if (tmp)
+ BN_clear_free(tmp);
+ if (order)
+ BN_free(order);
+ if (kinv)
+ BN_clear_free(kinv);
+ return sig;
+}
+
+#endif
+
+static int af_alg_ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
+ const ECDSA_SIG *sig, EC_KEY *eckey)
+{
+ int ret = -1, i;
+ BN_CTX *ctx;
+ BIGNUM *order, *u1, *u2, *m, *X;
+ EC_POINT *point = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *pub_key;
+
+ E_DBG("Enter \n");
+
+ /* check input values */
+ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
+ (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
+ return -1;
+ }
+
+ ctx = BN_CTX_new();
+ if (!ctx)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ BN_CTX_start(ctx);
+ order = BN_CTX_get(ctx);
+ u1 = BN_CTX_get(ctx);
+ u2 = BN_CTX_get(ctx);
+ m = BN_CTX_get(ctx);
+ X = BN_CTX_get(ctx);
+ if (!X)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (!EC_GROUP_get_order(group, order, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
+ BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
+ BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
+ ret = 0; /* signature is invalid */
+ goto err;
+ }
+ /* calculate tmp1 = inv(S) mod order */
+ if (!BN_mod_inverse(u2, sig->s, order, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+ /* digest -> m */
+ i = BN_num_bits(order);
+ /* Need to truncate digest if it is too long: first truncate whole
+ * bytes.
+ */
+ if (8 * dgst_len > i)
+ dgst_len = (i + 7)/8;
+ if (!BN_bin2bn(dgst, dgst_len, m))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+ /* If still too long truncate remaining bits with a shift */
+ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* u1 = m * tmp mod order */
+#ifdef SUPPORT_CE_V3_2
+ if (!af_alg_BN_mod_mul(u1, m, u2, order, ctx))
+#else
+ if (!BN_mod_mul(u1, m, u2, order, ctx))
+#endif
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* u2 = r * w mod q */
+#ifdef SUPPORT_CE_V3_2
+ if (!af_alg_BN_mod_mul(u2, sig->r, u2, order, ctx))
+#else
+ if (!BN_mod_mul(u2, sig->r, u2, order, ctx))
+#endif
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if ((point = EC_POINT_new(group)) == NULL)
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!af_alg_POINTs_mul(group, point, u1, pub_key, u2, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
+ {
+ if (!EC_POINT_get_affine_coordinates_GFp(group,
+ point, X, NULL, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+#ifndef OPENSSL_NO_EC2M
+ else /* NID_X9_62_characteristic_two_field */
+ {
+ if (!EC_POINT_get_affine_coordinates_GF2m(group,
+ point, X, NULL, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+#endif
+ if (!BN_nnmod(u1, X, order, ctx))
+ {
+ ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+ goto err;
+ }
+ /* if the signature is correct u1 is equal to sig->r */
+ ret = (BN_ucmp(u1, sig->r) == 0);
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ if (point)
+ EC_POINT_free(point);
+ return ret;
+}
+
+static ECDSA_METHOD af_alg_ecdsa = {
+ "Af_alg ECDSA method",
+ af_alg_ecdsa_do_sign,
+ NULL,
+ af_alg_ecdsa_do_verify,
+ 0,
+ NULL
+};
+
+#endif
+
+int af_alg_init(ENGINE * engine)
+{
+ int sock;
+ if((sock = socket(AF_ALG, SOCK_SEQPACKET, 0)) == -1)
+ return 0;
+ close(sock);
+
+ return 1;
+}
+
+int af_alg_finish(ENGINE * engine)
+{
+ return 1;
+}
+/* The definitions for control commands specific to this engine */
+#define AF_ALG_CMD_CIPHERS ENGINE_CMD_BASE
+#define AF_ALG_CMD_DIGESTS (ENGINE_CMD_BASE + 1)
+#define AF_ALG_CMD_RANDS (ENGINE_CMD_BASE + 2)
+#define AF_ALG_CMD_RSA (ENGINE_CMD_BASE + 3)
+#define AF_ALG_CMD_DH (ENGINE_CMD_BASE + 4)
+#define AF_ALG_CMD_ECDH (ENGINE_CMD_BASE + 5)
+
+static const ENGINE_CMD_DEFN af_alg_cmd_defns[] = {
+ {AF_ALG_CMD_CIPHERS,"CIPHERS","which ciphers to run",ENGINE_CMD_FLAG_STRING},
+ {AF_ALG_CMD_DIGESTS,"DIGESTS","which digests to run",ENGINE_CMD_FLAG_STRING},
+ {AF_ALG_CMD_RANDS,"RAND","which rand to run",ENGINE_CMD_FLAG_STRING},
+ {AF_ALG_CMD_RSA,"RSA","RSA of af_alg engine",ENGINE_CMD_FLAG_STRING},
+ {AF_ALG_CMD_DH,"DH","DH of af_alg engine",ENGINE_CMD_FLAG_STRING},
+ {AF_ALG_CMD_ECDH,"ECDH","ECDH of af_alg engine",ENGINE_CMD_FLAG_STRING},
+ {0, NULL, NULL, 0}
+};
+static int cipher_nid(const EVP_CIPHER *c)
+{
+ return EVP_CIPHER_nid(c);
+}
+static int digest_nid(const EVP_MD *d)
+{
+ return EVP_MD_type(d);
+}
+static bool names_to_nids(const char *names, const void*(*by_name)(const char *), int (*to_nid)(const void *), int **rnids, int *rnum, int *nids, int num)
+{
+ char *str, *r;
+ char *c = NULL;
+ r = str = strdup(names);
+ while( (c = strtok_r(r, " ", &r)) != NULL )
+ {
+ const void *ec = by_name(c);
+ if (strncmp(c, "hmac-sha1", 9) == 0)
+ ec = &af_alg_md_hmac_sha1;
+ if (strncmp(c, "hmac-sha256", 11) == 0)
+ ec = &af_alg_md_hmac_sha256;
+ if (ec == NULL)
+ /* the cipher/digest is unknown */
+ return false;
+
+ if( nid_in_nids(to_nid(ec), nids, num) == false )
+ /* we do not support the cipher */
+ return false;
+
+ if((*rnids = realloc(*rnids, (*rnum+1)*sizeof(int))) == NULL)
+ return false;
+ (*rnids)[*rnum]=to_nid(ec);
+ *rnum = *rnum+1;
+ }
+ return true;
+}
+
+static int af_alg_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+{
+ OpenSSL_add_all_algorithms();
+ switch( cmd )
+ {
+ case AF_ALG_CMD_CIPHERS:
+ if( p == NULL )
+ return 1;
+ if( names_to_nids(p, (void *)EVP_get_cipherbyname, (void *)cipher_nid, &af_alg_cipher_nids, &af_alg_cipher_nids_num, af_alg_cipher_all_nids, af_alg_cipher_all_nids_num) == false )
+ return 0;
+ ENGINE_unregister_ciphers(e);
+ ENGINE_register_ciphers(e);
+ return 1;
+ case AF_ALG_CMD_DIGESTS:
+ if( p == NULL )
+ return 1;
+ if( names_to_nids(p, (void *)EVP_get_digestbyname, (void *)digest_nid, &af_alg_digest_nids, &af_alg_digest_nids_num, af_alg_digest_all_nids, af_alg_digest_all_nids_num) == false )
+ return 0;
+ ENGINE_unregister_digests(e);
+ ENGINE_register_digests(e);
+ return 1;
+ case AF_ALG_CMD_RANDS:
+ ENGINE_unregister_digests(e);
+ ENGINE_register_digests(e);
+ return 1;
+ case AF_ALG_CMD_RSA:
+ case AF_ALG_CMD_DH:
+ case AF_ALG_CMD_ECDH:
+ ENGINE_unregister_digests(e);
+ ENGINE_register_digests(e);
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int af_alg_bind_helper(ENGINE * e)
+{
+ if( !ENGINE_set_id(e, AF_ALG_ENGINE_ID) ||
+ !ENGINE_set_init_function(e, af_alg_init) ||
+ !ENGINE_set_finish_function(e, af_alg_finish) ||
+ !ENGINE_set_name(e, AF_ALG_ENGINE_NAME) ||
+ !ENGINE_set_ciphers (e, af_alg_ciphers) ||
+ !ENGINE_set_digests (e, af_alg_digests) ||
+ !ENGINE_set_RAND(e, &af_alg_random) ||
+#ifdef SS_RSA_ENABLE
+ !ENGINE_set_RSA(e, &af_alg_rsa) ||
+#endif
+#ifdef SS_DH_ENABLE
+ !ENGINE_set_DH(e, &af_alg_dh) ||
+#endif
+#ifdef SS_ECC_ENABLE
+ !ENGINE_set_ECDH(e, &af_alg_ecdh) ||
+ !ENGINE_set_ECDSA(e, &af_alg_ecdsa) ||
+#endif
+ !ENGINE_set_ctrl_function(e, af_alg_ctrl) ||
+ !ENGINE_set_cmd_defns(e, af_alg_cmd_defns))
+ return 0;
+ else
+ return 1;
+}
+
+ENGINE *ENGINE_af_alg(void)
+{
+ ENGINE *eng = ENGINE_new();
+ if( !eng )
+ return NULL;
+
+ if( !af_alg_bind_helper(eng) )
+ {
+ ENGINE_free(eng);
+ return NULL;
+ }
+ return eng;
+}
+
+void ENGINE_load_af_alg(void)
+{
+ ENGINE *toadd = ENGINE_af_alg();
+ E_DBG("toadd = %p\n", toadd);
+
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ ENGINE_free(toadd);
+ ERR_clear_error();
+}
+
+static int af_alg_bind_fn(ENGINE *e, const char *id)
+{
+ E_DBG("\n");
+ if( id && (strcmp(id, AF_ALG_ENGINE_ID) != 0) )
+ return 0;
+
+ if( !af_alg_bind_helper(e) )
+ return 0;
+
+ return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN();
+IMPLEMENT_DYNAMIC_BIND_FN(af_alg_bind_fn);
+
+static int af_alg_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key, struct sockaddr_alg *sa)
+{
+ int keylen = EVP_CIPHER_CTX_key_length(ctx);
+ struct af_alg_cipher_data *acd = (struct af_alg_cipher_data *)ctx->cipher_data;
+
+ E_DBG("keylen = %d\n", keylen);
+ acd->op = -1;
+
+ if( ctx->encrypt )
+ acd->type = ALG_OP_ENCRYPT;
+ else
+ acd->type = ALG_OP_DECRYPT;
+
+ acd->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (acd->tfmfd == -1) {
+ E_ERR("socket() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ if (bind(acd->tfmfd, (struct sockaddr*)sa, sizeof(*sa)) == -1) {
+ E_ERR("bind() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ if (setsockopt(acd->tfmfd, SOL_ALG, ALG_SET_KEY, key, keylen) == -1) {
+ E_ERR("setsockopt() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+static int af_alg_aes_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cbc(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+static int af_alg_aes_ecb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "ecb(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+#ifdef SS_CTR_MODE_ENABLE
+static int af_alg_aes_ctr_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "ctr(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+#endif
+
+#ifdef SS_CTS_MODE_ENABLE
+static int af_alg_aes_cts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cts(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+#endif
+
+#ifdef SS_XTS_MODE_ENABLE
+static int af_alg_aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "xts(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+#endif
+
+#ifdef SS_OFB_MODE_ENABLE
+static int af_alg_aes_ofb128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "ofb(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+#endif
+
+#ifdef SS_CFB_MODE_ENABLE
+static int af_alg_aes_cfb1_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cfb1(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+static int af_alg_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cfb8(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+static int af_alg_aes_cfb128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cfb128(aes)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+#endif
+
+int af_alg_aes_cleanup_key(EVP_CIPHER_CTX *ctx)
+{
+ struct af_alg_cipher_data *acd = (struct af_alg_cipher_data *)ctx->cipher_data;
+ E_DBG("\n");
+ if (acd->tfmfd > 0)
+ close(acd->tfmfd);
+ if (acd->op > 0)
+ close(acd->op);
+ return 1;
+}
+
+static int af_alg_aes_cbc_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ struct af_alg_cipher_data *acd = (struct af_alg_cipher_data *)ctx->cipher_data;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct af_alg_iv *ivm;
+ struct iovec iov;
+ int iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+ char buf[CMSG_SPACE(sizeof(acd->type)) + CMSG_SPACE(offsetof(struct af_alg_iv, iv) + iv_len)];
+ ssize_t len;
+ unsigned char save_iv[iv_len];
+
+ memset(buf, 0, sizeof(buf));
+ E_DBG("nbytes = %zd\n", nbytes);
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ if( acd->op == -1 )
+ {
+ if((acd->op = accept(acd->tfmfd, NULL, 0)) == -1)
+ return 0;
+ }
+ /* set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg),&acd->type, 4);
+
+ /* set IV - or update if it was set before */
+ if(!ctx->encrypt)
+ memcpy(save_iv, in_arg + nbytes - iv_len, iv_len);
+
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_IV;
+ cmsg->cmsg_len = CMSG_LEN(offsetof(struct af_alg_iv, iv) + iv_len);
+ ivm = (void*)CMSG_DATA(cmsg);
+ ivm->ivlen = iv_len;
+ memcpy(ivm->iv, ctx->iv, iv_len);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ unsigned int todo = nbytes;
+ unsigned int done = 0;
+ while( todo-done > 0 )
+ {
+ iov.iov_base = (void *)(in_arg + done);
+ iov.iov_len = todo-done;
+
+ if((len = sendmsg(acd->op, &msg, 0)) == -1)
+ return 0;
+
+ if (read(acd->op, out_arg+done, len) != len)
+ return 0;
+
+ /* do not update IV for following chunks */
+ msg.msg_controllen = 0;
+ done += len;
+ }
+
+ /* copy IV for next iteration */
+ if(ctx->encrypt)
+ memcpy(ctx->iv, out_arg + done - iv_len, iv_len);
+ else
+ memcpy(ctx->iv, save_iv, iv_len);
+ return 1;
+}
+
+static int af_alg_aes_ecb_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ struct af_alg_cipher_data *acd = (struct af_alg_cipher_data *)ctx->cipher_data;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char buf[CMSG_SPACE(sizeof(acd->type))];
+ ssize_t len;
+
+ memset(buf, 0, sizeof(buf));
+ E_DBG("nbytes = %zd\n", nbytes);
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+ if( acd->op == -1 )
+ {
+ if((acd->op = accept(acd->tfmfd, NULL, 0)) == -1)
+ return 0;
+ }
+ /* set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg),&acd->type, 4);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ unsigned int todo = nbytes;
+ unsigned int done = 0;
+ while( todo-done > 0 )
+ {
+ iov.iov_base = (void *)(in_arg + done);
+ iov.iov_len = todo-done;
+
+ if((len = sendmsg(acd->op, &msg, 0)) == -1)
+ return 0;
+ E_DBG("sendmsg() return %zd \n", len);
+
+ if (read(acd->op, out_arg+done, len) != len)
+ return 0;
+
+ /* do not update IV for following chunks */
+ msg.msg_controllen = 0;
+ done += len;
+ }
+
+ return 1;
+}
+
+#ifdef SS_CTR_MODE_ENABLE
+static int af_alg_aes_ctr_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+#endif
+
+#ifdef SS_CTS_MODE_ENABLE
+static int af_alg_aes_cts_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+#endif
+
+#ifdef SS_XTS_MODE_ENABLE
+static int af_alg_aes_xts_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+#endif
+
+#ifdef SS_OFB_MODE_ENABLE
+static int af_alg_aes_ofb128_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+#endif
+
+#ifdef SS_CFB_MODE_ENABLE
+static int af_alg_aes_cfb1_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+
+static int af_alg_aes_cfb8_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+
+static int af_alg_aes_cfb128_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+#endif
+
+#define EVP_CIPHER_block_size_AES_ECB AES_BLOCK_SIZE
+#define EVP_CIPHER_block_size_AES_CBC AES_BLOCK_SIZE
+#define EVP_CIPHER_block_size_AES_OFB 1
+#define EVP_CIPHER_block_size_AES_CFB 1
+#define EVP_CIPHER_block_size_AES_CTR 1
+#define EVP_CIPHER_block_size_AES_CTS 1
+#define EVP_CIPHER_block_size_AES_XTS 1
+#define EVP_CIPHER_block_size_AES_CBC_HMAC_SHA1 AES_BLOCK_SIZE
+
+#define EVP_CIPH_CBC_HMAC_SHA1_MODE EVP_CIPH_CBC_MODE
+
+#define DECLARE_AES_EVP(ksize,lmode,umode) \
+static const EVP_CIPHER af_alg_aes_##ksize##_##lmode = { \
+ .nid = NID_aes_##ksize##_##lmode, \
+ .block_size = EVP_CIPHER_block_size_AES_##umode, \
+ .key_len = AES_KEY_SIZE_##ksize, \
+ .iv_len = AES_BLOCK_SIZE, \
+ .flags = 0 | EVP_CIPH_##umode##_MODE, \
+ .init = af_alg_aes_##lmode##_init_key, \
+ .do_cipher = af_alg_aes_##lmode##_ciphers, \
+ .cleanup = af_alg_aes_cleanup_key, \
+ .ctx_size = sizeof(struct af_alg_cipher_data), \
+ .set_asn1_parameters = EVP_CIPHER_set_asn1_iv, \
+ .get_asn1_parameters = EVP_CIPHER_get_asn1_iv, \
+ .ctrl = NULL, \
+ .app_data = NULL \
+}
+#define DECLARE_AES_XTS_EVP(ksize,lmode,umode) \
+static const EVP_CIPHER af_alg_aes_##ksize##_##lmode = { \
+ .nid = NID_aes_##ksize##_##lmode, \
+ .block_size = EVP_CIPHER_block_size_AES_##umode, \
+ .key_len = AES_KEY_SIZE_##ksize * 2, \
+ .iv_len = AES_BLOCK_SIZE, \
+ .flags = 0 | EVP_CIPH_##umode##_MODE, \
+ .init = af_alg_aes_##lmode##_init_key, \
+ .do_cipher = af_alg_aes_##lmode##_ciphers, \
+ .cleanup = af_alg_aes_cleanup_key, \
+ .ctx_size = sizeof(struct af_alg_cipher_data), \
+ .set_asn1_parameters = EVP_CIPHER_set_asn1_iv, \
+ .get_asn1_parameters = EVP_CIPHER_get_asn1_iv, \
+ .ctrl = NULL, \
+ .app_data = NULL \
+}
+
+DECLARE_AES_EVP(128,ecb,ECB);
+DECLARE_AES_EVP(192,ecb,ECB);
+DECLARE_AES_EVP(256,ecb,ECB);
+DECLARE_AES_EVP(128,cbc,CBC);
+DECLARE_AES_EVP(192,cbc,CBC);
+DECLARE_AES_EVP(256,cbc,CBC);
+#ifdef SS_CTR_MODE_ENABLE
+DECLARE_AES_EVP(128,ctr,CTR);
+DECLARE_AES_EVP(192,ctr,CTR);
+DECLARE_AES_EVP(256,ctr,CTR);
+#endif
+#ifdef SS_CTS_MODE_ENABLE
+DECLARE_AES_EVP(128,cts,CTS);
+DECLARE_AES_EVP(192,cts,CTS);
+DECLARE_AES_EVP(256,cts,CTS);
+#endif
+#ifdef SS_XTS_MODE_ENABLE
+DECLARE_AES_XTS_EVP(128, xts, XTS);
+DECLARE_AES_XTS_EVP(256, xts, XTS);
+#endif
+#ifdef SS_OFB_MODE_ENABLE
+DECLARE_AES_EVP(128, ofb128, OFB);
+DECLARE_AES_EVP(192, ofb128, OFB);
+DECLARE_AES_EVP(256, ofb128, OFB);
+#endif
+#ifdef SS_OFB_MODE_ENABLE
+DECLARE_AES_EVP(128, cfb1, CFB);
+DECLARE_AES_EVP(128, cfb8, CFB);
+DECLARE_AES_EVP(128, cfb128, CFB);
+DECLARE_AES_EVP(192, cfb1, CFB);
+DECLARE_AES_EVP(192, cfb8, CFB);
+DECLARE_AES_EVP(192, cfb128, CFB);
+DECLARE_AES_EVP(256, cfb1, CFB);
+DECLARE_AES_EVP(256, cfb8, CFB);
+DECLARE_AES_EVP(256, cfb128, CFB);
+#endif
+
+static int af_alg_des_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cbc(des)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+static int af_alg_des_ecb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "ecb(des)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+static int af_alg_des_cbc_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+
+static int af_alg_des_ecb_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_ecb_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+
+static int af_alg_des_ede3_cbc_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_cbc_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+
+static int af_alg_des_ede3_ecb_ciphers(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, const unsigned char *in_arg, size_t nbytes)
+{
+ return af_alg_aes_ecb_ciphers(ctx, out_arg, in_arg, nbytes);
+}
+
+static int af_alg_des_ede3_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "cbc(des3)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+static int af_alg_des_ede3_ecb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "ecb(des3)",
+ };
+
+ E_DBG("\n");
+ return af_alg_aes_init_key(ctx, key, &sa);
+}
+
+#define DECLARE_DES_EVP(lmode,umode,keylen) \
+static const EVP_CIPHER af_alg_des_##lmode = { \
+ .nid = NID_des_##lmode, \
+ .block_size = DES_KEY_SZ, \
+ .key_len = keylen, \
+ .iv_len = DES_KEY_SZ, \
+ .flags = 0 | EVP_CIPH_##umode##_MODE, \
+ .init = af_alg_des_##lmode##_init_key, \
+ .do_cipher = af_alg_des_##lmode##_ciphers, \
+ .cleanup = af_alg_aes_cleanup_key, \
+ .ctx_size = sizeof(struct af_alg_cipher_data), \
+ .set_asn1_parameters = EVP_CIPHER_set_asn1_iv, \
+ .get_asn1_parameters = EVP_CIPHER_get_asn1_iv, \
+ .ctrl = NULL, \
+ .app_data = NULL \
+}
+DECLARE_DES_EVP(ecb,ECB,DES_KEY_SZ);
+DECLARE_DES_EVP(cbc,CBC,DES_KEY_SZ);
+DECLARE_DES_EVP(ede3_ecb,ECB,DES_KEY_SZ*3);
+DECLARE_DES_EVP(ede3_cbc,CBC,DES_KEY_SZ*3);
+
+typedef struct {
+ int nid;
+ const EVP_CIPHER *evp;
+} nid2cipher_t;
+static nid2cipher_t gs_nid2cipher[] = {
+ {NID_aes_128_ecb, &af_alg_aes_128_ecb},
+ {NID_aes_192_ecb, &af_alg_aes_192_ecb},
+ {NID_aes_256_ecb, &af_alg_aes_256_ecb},
+ {NID_aes_128_cbc, &af_alg_aes_128_cbc},
+ {NID_aes_192_cbc, &af_alg_aes_192_cbc},
+ {NID_aes_256_cbc, &af_alg_aes_256_cbc},
+#ifdef SS_CTR_MODE_ENABLE
+ {NID_aes_128_ctr, &af_alg_aes_128_ctr},
+ {NID_aes_192_ctr, &af_alg_aes_192_ctr},
+ {NID_aes_256_ctr, &af_alg_aes_256_ctr},
+#endif
+#ifdef SS_CTS_MODE_ENABLE
+ {NID_aes_128_cts, &af_alg_aes_128_cts},
+ {NID_aes_192_cts, &af_alg_aes_192_cts},
+ {NID_aes_256_cts, &af_alg_aes_256_cts},
+#endif
+#ifdef SS_XTS_MODE_ENABLE
+ {NID_aes_128_xts, &af_alg_aes_128_xts},
+ {NID_aes_256_xts, &af_alg_aes_256_xts},
+#endif
+#ifdef SS_OFB_MODE_ENABLE
+ {NID_aes_128_ofb128, &af_alg_aes_128_ofb128},
+ {NID_aes_192_ofb128, &af_alg_aes_192_ofb128},
+ {NID_aes_256_ofb128, &af_alg_aes_256_ofb128},
+#endif
+#ifdef SS_CFB_MODE_ENABLE
+ {NID_aes_128_cfb1, &af_alg_aes_128_cfb1},
+ {NID_aes_128_cfb8, &af_alg_aes_128_cfb8},
+ {NID_aes_128_cfb128, &af_alg_aes_128_cfb128},
+ {NID_aes_192_cfb1, &af_alg_aes_192_cfb1},
+ {NID_aes_192_cfb8, &af_alg_aes_192_cfb8},
+ {NID_aes_192_cfb128, &af_alg_aes_192_cfb128},
+ {NID_aes_256_cfb1, &af_alg_aes_256_cfb1},
+ {NID_aes_256_cfb8, &af_alg_aes_256_cfb8},
+ {NID_aes_256_cfb128, &af_alg_aes_256_cfb128},
+#endif
+ {NID_des_ecb, &af_alg_des_ecb},
+ {NID_des_cbc, &af_alg_des_cbc},
+ {NID_des_ede3_ecb, &af_alg_des_ede3_ecb},
+ {NID_des_ede3_cbc, &af_alg_des_ede3_cbc},
+ {0xFFFF, NULL}
+};
+static int gs_nid2cipher_cnt = sizeof(gs_nid2cipher)/sizeof(nid2cipher_t);
+
+static int af_alg_match(int nid, void *array, int cnt)
+{
+ int i;
+ nid2cipher_t *cur = (nid2cipher_t *)array;
+
+ for (i=0; i<cnt; i++, cur++) {
+ if (nid == cur->nid)
+ return i;
+ }
+ return cnt - 1;
+}
+
+static int af_alg_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
+{
+ E_DBG("cipher = %p, nid = %d\n", cipher, nid);
+ if( !cipher )
+ {
+ *nids = af_alg_cipher_nids;
+ return af_alg_cipher_nids_num;
+ }
+
+ if( ! nid_in_nids(nid, af_alg_cipher_nids, af_alg_cipher_nids_num) )
+ return 0;
+
+ *cipher = gs_nid2cipher[af_alg_match(nid, gs_nid2cipher, gs_nid2cipher_cnt)].evp;
+ return(*cipher != 0);
+}
+
+#define DIGEST_DATA(ctx) ((struct af_alg_digest_data*)(ctx->md_data))
+
+static int af_alg_hash_init(EVP_MD_CTX *ctx, struct sockaddr_alg *sa)
+{
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+
+ E_DBG("%s.%s init ... \n", sa->salg_type, sa->salg_name);
+ if( (ddata->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0)) == -1 ) {
+ E_ERR("socket() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ if( bind(ddata->tfmfd, (struct sockaddr *)sa, sizeof(*sa)) != 0 ) {
+ E_ERR("bind() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ if( (ddata->opfd = accept(ddata->tfmfd,NULL,0)) == -1 ) {
+ E_ERR("accept() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+static int af_alg_sha1_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "sha1"
+ };
+
+ return af_alg_hash_init(ctx, &sa);
+}
+
+#ifdef SS_SHA224_ENABLE
+static int af_alg_sha224_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "sha224"
+ };
+
+ return af_alg_hash_init(ctx, &sa);
+}
+#endif
+
+#ifdef SS_SHA256_ENABLE
+static int af_alg_sha256_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "sha256"
+ };
+
+ return af_alg_hash_init(ctx, &sa);
+}
+#endif
+
+#ifdef SS_SHA384_ENABLE
+static int af_alg_sha384_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "sha384"
+ };
+
+ return af_alg_hash_init(ctx, &sa);
+}
+#endif
+
+#ifdef SS_SHA512_ENABLE
+static int af_alg_sha512_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "sha512"
+ };
+
+ return af_alg_hash_init(ctx, &sa);
+}
+#endif
+
+#if defined(SS_HMAC_SHA1_ENABLE) || defined(SS_HMAC_SHA256_ENABLE)
+#define SWAB32(x) ((((x)&0x000000ffUL) << 24) | (((x)&0x0000ff00UL) << 8) \
+ | (((x)&0x00ff0000UL) >> 8) | (((x)&0xff000000UL) >> 24))
+
+int af_alg_hmac_sha_padding(char *dst, const char *src, int len, char *key, int keylen)
+{
+ int i;
+ int n = len % SHA_CBLOCK;
+ int total = len + SHA_CBLOCK;
+ char *p = dst;
+
+ /* Generate dst based on HMAC-SHA1 standard. */
+ for (i=0; i<keylen; ++i)
+ dst[i] = key[i] ^ 0x36;
+ memset(&dst[keylen], 0x36, SHA_CBLOCK-keylen);
+ memcpy(&dst[SHA_CBLOCK], src, len);
+#ifdef SUPPORT_CE_V3_2
+ return total;
+#endif
+ memset(&dst[SHA_CBLOCK+len], 0, SHA_CBLOCK*2);
+
+ /* Padding the tail based on SHA1 standard. */
+ p += total - n; /* point to the last block */
+ p[n] = 0x80;
+ n++;
+
+ if (n > (SHA_CBLOCK-8))
+ p += SHA_CBLOCK*2 - 8;
+ else
+ p += SHA_CBLOCK - 8;
+
+ *(int *)p = SWAB32(total >> 29);
+ *(int *)(p+4) = SWAB32(total << 3);
+
+ E_DBG("After padding %ld: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p + 8 - dst,
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+
+ return p + 8 - dst;
+}
+
+static int af_alg_hmac_sha_update(EVP_MD_CTX *ctx, const void *data, size_t length)
+{
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ int encrypt = ALG_OP_ENCRYPT;
+ char buf[CMSG_SPACE(sizeof(encrypt))];
+ char *padded = NULL;
+ ssize_t ret;
+
+ if (setsockopt(ddata->tfmfd, SOL_ALG, ALG_SET_KEY, ddata->key, SHA_CBLOCK) == -1) {
+ E_ERR("setsockopt() failed! [%d]: %s\n", errno, strerror(errno));
+ return 0;
+ }
+
+ padded = OPENSSL_malloc(length + SHA_CBLOCK*3);
+ if (padded == NULL) {
+ E_ERR("Failed to malloc()!\n");
+ return 0;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ E_DBG("length = %zu\n", length);
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+
+ /* set operation type encrypt|decrypt */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_ALG;
+ cmsg->cmsg_type = ALG_SET_OP;
+ cmsg->cmsg_len = CMSG_LEN(4);
+ memcpy(CMSG_DATA(cmsg), &encrypt, 4);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ ret = af_alg_hmac_sha_padding(padded, data, length, ddata->key, ddata->keylen);
+
+ iov.iov_base = (void *)padded;
+ iov.iov_len = ret;
+
+ if ((ret = sendmsg(ddata->opfd, &msg, 0)) == -1)
+ return 0;
+ E_DBG("sendmsg() return %zd \n", ret);
+
+ OPENSSL_free(padded);
+ return 1;
+}
+#endif
+
+#ifdef SS_HMAC_SHA1_ENABLE
+static int af_alg_hmac_sha1_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "hmac-sha1"
+ };
+ return af_alg_hash_init(ctx, &sa);
+}
+
+static int af_alg_hmac_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ int ret = 0;
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+
+ ret = read(ddata->opfd, md, SHA_DIGEST_LENGTH);
+ if (ret != SHA_DIGEST_LENGTH) {
+ E_ERR("read(%d) return %d! \n", ddata->opfd, ret);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifdef SS_HMAC_SHA256_ENABLE
+static int af_alg_hmac_sha256_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ .salg_name = "hmac-sha256"
+ };
+ return af_alg_hash_init(ctx, &sa);
+}
+
+static int af_alg_hmac_sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ int ret = 0;
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+
+ ret = read(ddata->opfd, md, SHA256_DIGEST_LENGTH);
+ if (ret != SHA256_DIGEST_LENGTH) {
+ E_ERR("read(%d) return %d! \n", ddata->opfd, ret);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+static int af_alg_sha_update(EVP_MD_CTX *ctx, const void *data, size_t length)
+{
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+ ssize_t r;
+
+ r = send(ddata->opfd, data, length, MSG_MORE);
+ E_DBG("send(%zu) return %zd\n", length, r);
+ if( r < 0 || (size_t)r < length )
+ return 0;
+ return 1;
+}
+
+static int af_alg_sha_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+ ssize_t r = 0;
+ int md_size = ctx->digest->md_size;
+
+ r = read(ddata->opfd, md, md_size);
+ E_DBG("read(%d) return %zd \n", md_size, r);
+ if (r != md_size) {
+ E_ERR("read() return %d. [%d]: %s\n", (int)r, errno, strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+static int af_alg_sha_copy(EVP_MD_CTX *_to,const EVP_MD_CTX *_from)
+{
+ struct af_alg_digest_data *from = DIGEST_DATA(_from);
+ struct af_alg_digest_data *to = DIGEST_DATA(_to);
+
+ E_DBG("\n");
+ if( (to->opfd = accept(from->opfd, NULL, 0)) == -1 )
+ return 0;
+ if( (to->tfmfd = accept(from->tfmfd, NULL, 0)) == -1 )
+ return 0;
+ return 1;
+}
+
+static int af_alg_sha_cleanup(EVP_MD_CTX *ctx)
+{
+ struct af_alg_digest_data *ddata = DIGEST_DATA(ctx);
+ if( ddata->opfd != -1 )
+ close(ddata->opfd);
+ if( ddata->tfmfd != -1 )
+ close(ddata->tfmfd);
+ return 0;
+}
+
+static int af_alg_md5_init(EVP_MD_CTX *ctx)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "md5"
+ };
+
+ return af_alg_hash_init(ctx, &sa);
+}
+
+#define NID_hmac_sha1WithRSAEncryption NID_sha1WithRSAEncryption
+
+#define DECLARE_MD_SHA(digest, udigest) \
+static const EVP_MD af_alg_md_##digest = { \
+ NID_##digest, \
+ NID_##digest##WithRSAEncryption, \
+ udigest##_DIGEST_LENGTH, \
+ 0, \
+ af_alg_##digest##_init, \
+ af_alg_sha_update, \
+ af_alg_sha_final, \
+ af_alg_sha_copy, \
+ af_alg_sha_cleanup, \
+ EVP_PKEY_RSA_method, \
+ SHA_CBLOCK, \
+ sizeof(struct af_alg_digest_data), \
+ NULL, \
+}
+
+DECLARE_MD_SHA(sha1, SHA);
+#ifdef SS_SHA224_ENABLE
+DECLARE_MD_SHA(sha224, SHA224);
+#endif
+#ifdef SS_SHA256_ENABLE
+DECLARE_MD_SHA(sha256, SHA256);
+#endif
+#ifdef SS_SHA384_ENABLE
+DECLARE_MD_SHA(sha384, SHA384);
+#endif
+#ifdef SS_SHA512_ENABLE
+DECLARE_MD_SHA(sha512, SHA512);
+#endif
+#ifdef SS_HMAC_SHA1_ENABLE
+static const EVP_MD af_alg_md_hmac_sha1 = {
+ NID_hmac_sha1,
+ NID_hmac_sha1WithRSAEncryption,
+ SHA_DIGEST_LENGTH,
+ 0,
+ af_alg_hmac_sha1_init,
+ af_alg_hmac_sha_update,
+ af_alg_hmac_sha1_final,
+ af_alg_sha_copy,
+ af_alg_sha_cleanup,
+ EVP_PKEY_RSA_method,
+ SHA_CBLOCK,
+ sizeof(struct af_alg_digest_data),
+ NULL
+};
+#endif
+#ifdef SS_HMAC_SHA256_ENABLE
+static const EVP_MD af_alg_md_hmac_sha256 = {
+ NID_hmacWithSHA256,
+ NID_hmac_sha1WithRSAEncryption,
+ SHA256_DIGEST_LENGTH,
+ 0,
+ af_alg_hmac_sha256_init,
+ af_alg_hmac_sha_update,
+ af_alg_hmac_sha256_final,
+ af_alg_sha_copy,
+ af_alg_sha_cleanup,
+ EVP_PKEY_RSA_method,
+ SHA_CBLOCK,
+ sizeof(struct af_alg_digest_data),
+ NULL
+};
+#endif
+DECLARE_MD_SHA(md5, MD5);
+
+typedef struct {
+ int nid;
+ const EVP_MD *evp;
+} nid2md_t;
+static nid2md_t gs_nid2md[] = {
+ {NID_sha1, &af_alg_md_sha1},
+#ifdef SS_SHA224_ENABLE
+ {NID_sha224, &af_alg_md_sha224},
+#endif
+#ifdef SS_SHA256_ENABLE
+ {NID_sha256, &af_alg_md_sha256},
+#endif
+#ifdef SS_SHA384_ENABLE
+ {NID_sha384, &af_alg_md_sha384},
+#endif
+#ifdef SS_SHA512_ENABLE
+ {NID_sha512, &af_alg_md_sha512},
+#endif
+ {NID_md5, &af_alg_md_md5},
+#ifdef SS_HMAC_SHA1_ENABLE
+ {NID_hmac_sha1, &af_alg_md_hmac_sha1},
+#endif
+#ifdef SS_HMAC_SHA256_ENABLE
+ {NID_hmacWithSHA256, &af_alg_md_hmac_sha256},
+#endif
+ {0xFFFF, NULL}
+};
+static int gs_nid2md_cnt = sizeof(gs_nid2md)/sizeof(nid2md_t);
+
+static int af_alg_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid)
+{
+ E_DBG("digest = %p \n", digest);
+ if( !digest )
+ {
+ *nids = af_alg_digest_nids;
+ return af_alg_digest_nids_num;
+ }
+
+ if( nid_in_nids(nid, af_alg_digest_nids, af_alg_digest_nids_num) == false )
+ return 0;
+
+ E_DBG("nid = %d \n", nid);
+ *digest = gs_nid2md[af_alg_match(nid, gs_nid2md, gs_nid2md_cnt)].evp;
+ return (*digest != NULL);
+}
+
diff -Naur openssl-1.0.2h/engines/Makefile openssl-1.0.2h-new/engines/Makefile
--- openssl-1.0.2h/engines/Makefile 2016-05-03 21:46:39.000000000 +0800
+++ openssl-1.0.2h-new/engines/Makefile 2018-01-08 13:29:07.000000000 +0800
@@ -26,7 +26,7 @@
APPS=
LIB=$(TOP)/libcrypto.a
-LIBNAMES= 4758cca aep atalla cswift gmp chil nuron sureware ubsec padlock capi
+LIBNAMES= 4758cca aep atalla cswift gmp chil nuron sureware ubsec padlock capi af_alg
LIBSRC= e_4758cca.c \
e_aep.c \
@@ -38,7 +38,8 @@
e_sureware.c \
e_ubsec.c \
e_padlock.c \
- e_capi.c
+ e_capi.c \
+ e_af_alg.c
LIBOBJ= e_4758cca.o \
e_aep.o \
e_atalla.o \
@@ -49,7 +50,8 @@
e_sureware.o \
e_ubsec.o \
e_padlock.o \
- e_capi.o
+ e_capi.o \
+ e_af_alg.o
SRC= $(LIBSRC)
@@ -199,6 +201,23 @@
e_aep.o: ../include/openssl/symhacks.h ../include/openssl/x509.h
e_aep.o: ../include/openssl/x509_vfy.h e_aep.c e_aep_err.c e_aep_err.h
e_aep.o: vendor_defns/aep.h
+e_af_alg.o: ../crypto/ec/ec_lcl.h ../crypto/ecdh/ech_locl.h
+e_af_alg.o: ../crypto/ecdsa/ecs_locl.h ../include/openssl/aes.h
+e_af_alg.o: ../include/openssl/asn1.h ../include/openssl/bio.h
+e_af_alg.o: ../include/openssl/bn.h ../include/openssl/buffer.h
+e_af_alg.o: ../include/openssl/crypto.h ../include/openssl/des.h
+e_af_alg.o: ../include/openssl/des_old.h ../include/openssl/e_os2.h
+e_af_alg.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
+e_af_alg.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h
+e_af_alg.o: ../include/openssl/evp.h ../include/openssl/lhash.h
+e_af_alg.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h
+e_af_alg.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+e_af_alg.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+e_af_alg.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h
+e_af_alg.o: ../include/openssl/sha.h ../include/openssl/stack.h
+e_af_alg.o: ../include/openssl/symhacks.h ../include/openssl/ui.h
+e_af_alg.o: ../include/openssl/ui_compat.h ../include/openssl/x509.h
+e_af_alg.o: ../include/openssl/x509_vfy.h e_af_alg.c
e_atalla.o: ../include/openssl/asn1.h ../include/openssl/bio.h
e_atalla.o: ../include/openssl/bn.h ../include/openssl/buffer.h
e_atalla.o: ../include/openssl/crypto.h ../include/openssl/dh.h