Implement OpenSSL crypto provider (WITH_CRYPTO=openssl)
Set the WITH_CRYPTO build option to 'openssl' to use the OpenSSL libcrypto
library for cryptographic services. When WITH_CRYPTO is not set, or set to
'tomcrypt', LibTomCrypt is used.
Usage example:
$ make CROSS_COMPILE=arm-linux-gnueabihf- \
PLATFORM=vexpress PLATFORM_FLAVOR=fvp \
WITH_CRYPTO=openssl
Tested with xtest (e7cda93) on Foundation_v8 (PLATFORM_FLAVOR=fvp) and QEMU
(PLATFORM_FLAVOR=qemu_virt).
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
diff --git a/core/core.mk b/core/core.mk
index 6a6ba5d..485894f 100644
--- a/core/core.mk
+++ b/core/core.mk
@@ -13,6 +13,9 @@
platform_flavor_$(PLATFORM_FLAVOR) := y
cppflags$(sm) += -DPLATFORM_FLAVOR=PLATFORM_FLAVOR_ID_$(PLATFORM_FLAVOR)
+# Possible values: tomcrypt, openssl
+WITH_CRYPTO ?= tomcrypt
+
cppflags$(sm) += -Icore/include $(platform-cppflags) $(core-platform-cppflags)
cflags$(sm) += $(platform-cflags) $(core-platform-cflags)
aflags$(sm) += $(platform-aflags) $(core-platform-aflags)
@@ -41,9 +44,17 @@
include mk/lib.mk
base-prefix :=
+ifeq ($(WITH_CRYPTO), tomcrypt)
libname = tomcrypt
libdir = core/lib/libtomcrypt
include mk/lib.mk
+endif
+
+ifeq ($(WITH_CRYPTO), openssl)
+libname = opensslcrypto
+libdir = core/lib/openssl
+include mk/lib.mk
+endif
#
# Do main source
diff --git a/core/lib/openssl/crypto/aes/sub.mk b/core/lib/openssl/crypto/aes/sub.mk
new file mode 100644
index 0000000..a2fdbcc
--- /dev/null
+++ b/core/lib/openssl/crypto/aes/sub.mk
@@ -0,0 +1,7 @@
+incdirs-y := .. ../.. ../../include
+
+srcs-y += aes_cbc.c
+srcs-y += aes_core.c
+srcs-y += aes_ctr.c
+srcs-y += aes_ecb.c
+srcs-y += aes_misc.c
diff --git a/core/lib/openssl/crypto/asn1/sub.mk b/core/lib/openssl/crypto/asn1/sub.mk
new file mode 100644
index 0000000..68186ce
--- /dev/null
+++ b/core/lib/openssl/crypto/asn1/sub.mk
@@ -0,0 +1,20 @@
+incdirs-y := .. ../.. ../../include
+
+cflags-remove-y := -Wcast-align -Wswitch-default
+
+srcs-y += a_bitstr.c
+srcs-y += a_int.c
+srcs-y += a_object.c
+srcs-y += a_type.c
+srcs-y += ameth_lib.c
+srcs-y += asn1_lib.c
+srcs-y += evp_asn1.c
+srcs-y += tasn_dec.c
+srcs-y += tasn_enc.c
+srcs-y += tasn_fre.c
+srcs-y += tasn_new.c
+srcs-y += tasn_typ.c
+srcs-y += tasn_utl.c
+srcs-y += x_algor.c
+srcs-y += x_attrib.c
+srcs-y += x_sig.c
diff --git a/core/lib/openssl/crypto/bio/bio.h b/core/lib/openssl/crypto/bio/bio.h
index 05699ab..d90facc 100644
--- a/core/lib/openssl/crypto/bio/bio.h
+++ b/core/lib/openssl/crypto/bio/bio.h
@@ -326,7 +326,9 @@
unsigned long num_read;
unsigned long num_write;
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_EX_DATA ex_data;
+#endif
};
DECLARE_STACK_OF(BIO)
@@ -611,10 +613,12 @@
/* These two aren't currently implemented */
/* int BIO_get_ex_num(BIO *bio); */
/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int BIO_set_ex_data(BIO *bio,int idx,void *data);
void *BIO_get_ex_data(BIO *bio,int idx);
int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+#endif
unsigned long BIO_number_read(BIO *bio);
unsigned long BIO_number_written(BIO *bio);
diff --git a/core/lib/openssl/crypto/bn/bn.h b/core/lib/openssl/crypto/bn/bn.h
index 21a1a3f..0e6043c 100644
--- a/core/lib/openssl/crypto/bn/bn.h
+++ b/core/lib/openssl/crypto/bn/bn.h
@@ -600,7 +600,9 @@
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
#endif
+#ifndef OPTEE
CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
+#endif
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
diff --git a/core/lib/openssl/crypto/bn/bn_blind.c b/core/lib/openssl/crypto/bn/bn_blind.c
index 9ed8bc2..4c771bd 100644
--- a/core/lib/openssl/crypto/bn/bn_blind.c
+++ b/core/lib/openssl/crypto/bn/bn_blind.c
@@ -125,7 +125,9 @@
unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b;
* used only by crypto/rsa/rsa_eay.c, rsa_lib.c */
#endif
+#ifndef OPTEE
CRYPTO_THREADID tid;
+#endif
int counter;
unsigned long flags;
BN_MONT_CTX *m_ctx;
@@ -164,7 +166,9 @@
* to indicate that this is never-used fresh blinding
* that does not need updating before first use. */
ret->counter = -1;
+#ifndef OPTEE
CRYPTO_THREADID_current(&ret->tid);
+#endif
return(ret);
err:
if (ret != NULL) BN_BLINDING_free(ret);
@@ -288,10 +292,12 @@
}
#endif
+#ifndef OPTEE
CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *b)
{
return &b->tid;
}
+#endif
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
{
@@ -343,20 +349,24 @@
if (!BN_rand_range(ret->A, ret->mod)) goto err;
if (BN_mod_inverse(ret->Ai, ret->A, ret->mod, ctx) == NULL)
{
+#ifndef OPTEE
/* this should almost never happen for good RSA keys */
unsigned long error = ERR_peek_last_error();
if (ERR_GET_REASON(error) == BN_R_NO_INVERSE)
{
+#endif
if (retry_counter-- == 0)
{
BNerr(BN_F_BN_BLINDING_CREATE_PARAM,
BN_R_TOO_MANY_ITERATIONS);
goto err;
}
+#ifndef OPTEE
ERR_clear_error();
}
else
goto err;
+#endif
}
else
break;
diff --git a/core/lib/openssl/crypto/bn/sub.mk b/core/lib/openssl/crypto/bn/sub.mk
new file mode 100644
index 0000000..76375c1
--- /dev/null
+++ b/core/lib/openssl/crypto/bn/sub.mk
@@ -0,0 +1,23 @@
+incdirs-y := .. ../.. ../../include
+
+cflags-remove-y := -Wcast-align -Wswitch-default
+cflags-y := -Wno-unused-parameter
+
+srcs-y += bn_add.c
+srcs-y += bn_asm.c
+srcs-y += bn_blind.c
+srcs-y += bn_ctx.c
+srcs-y += bn_div.c
+srcs-y += bn_exp.c
+srcs-y += bn_exp2.c
+srcs-y += bn_gcd.c
+srcs-y += bn_lib.c
+srcs-y += bn_mod.c
+srcs-y += bn_mont.c
+srcs-y += bn_mul.c
+srcs-y += bn_prime.c
+srcs-y += bn_rand.c
+srcs-y += bn_recp.c
+srcs-y += bn_shift.c
+srcs-y += bn_sqr.c
+srcs-y += bn_word.c
diff --git a/core/lib/openssl/crypto/buffer/sub.mk b/core/lib/openssl/crypto/buffer/sub.mk
new file mode 100644
index 0000000..15a86cc
--- /dev/null
+++ b/core/lib/openssl/crypto/buffer/sub.mk
@@ -0,0 +1,4 @@
+incdirs-y := .. ../.. ../../include
+
+srcs-y += buf_str.c
+srcs-y += buffer.c
diff --git a/core/lib/openssl/crypto/conf/conf.h b/core/lib/openssl/crypto/conf/conf.h
index c219997..4936345 100644
--- a/core/lib/openssl/crypto/conf/conf.h
+++ b/core/lib/openssl/crypto/conf/conf.h
@@ -134,7 +134,9 @@
long CONF_get_number(LHASH_OF(CONF_VALUE) *conf,const char *group,
const char *name);
void CONF_free(LHASH_OF(CONF_VALUE) *conf);
+#ifndef OPENSSL_NO_FP_API
int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
+#endif
int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
void OPENSSL_config(const char *config_name);
@@ -168,7 +170,9 @@
char *NCONF_get_string(const CONF *conf,const char *group,const char *name);
int NCONF_get_number_e(const CONF *conf,const char *group,const char *name,
long *result);
+#ifndef OPENSSL_NO_FP_API
int NCONF_dump_fp(const CONF *conf, FILE *out);
+#endif
int NCONF_dump_bio(const CONF *conf, BIO *out);
#if 0 /* The following function has no error checking,
diff --git a/core/lib/openssl/crypto/conf/conf_api.c b/core/lib/openssl/crypto/conf/conf_api.c
index f5fcbb9..b06c74f 100644
--- a/core/lib/openssl/crypto/conf/conf_api.c
+++ b/core/lib/openssl/crypto/conf/conf_api.c
@@ -129,7 +129,9 @@
char *_CONF_get_string(const CONF *conf, const char *section, const char *name)
{
CONF_VALUE *v,vv;
+#ifndef OPTEE
char *p;
+#endif
if (name == NULL) return(NULL);
if (conf != NULL)
@@ -140,13 +142,15 @@
vv.section=(char *)section;
v=lh_CONF_VALUE_retrieve(conf->data,&vv);
if (v != NULL) return(v->value);
+#ifndef OPTEE
if (strcmp(section,"ENV") == 0)
{
p=getenv(name);
if (p != NULL) return(p);
}
+#endif
}
- vv.section="default";
+ vv.section=(char *)"default";
vv.name=(char *)name;
v=lh_CONF_VALUE_retrieve(conf->data,&vv);
if (v != NULL)
@@ -155,7 +159,11 @@
return(NULL);
}
else
+#ifdef OPTEE
+ return NULL;
+#else
return(getenv(name));
+#endif
}
#if 0 /* There's no way to provide error checking with this function, so
diff --git a/core/lib/openssl/crypto/conf/conf_def.c b/core/lib/openssl/crypto/conf/conf_def.c
index f0b2768..9a06182 100644
--- a/core/lib/openssl/crypto/conf/conf_def.c
+++ b/core/lib/openssl/crypto/conf/conf_def.c
@@ -183,6 +183,9 @@
static int def_load(CONF *conf, const char *name, long *line)
{
+#ifdef OPTEE
+ return 0;
+#else
int ret;
BIO *in=NULL;
@@ -204,6 +207,7 @@
BIO_free(in);
return ret;
+#endif
}
static int def_load_bio(CONF *conf, BIO *in, long *line)
diff --git a/core/lib/openssl/crypto/conf/conf_lib.c b/core/lib/openssl/crypto/conf/conf_lib.c
index 54046de..bd1bee1 100644
--- a/core/lib/openssl/crypto/conf/conf_lib.c
+++ b/core/lib/openssl/crypto/conf/conf_lib.c
@@ -90,6 +90,9 @@
LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
long *eline)
{
+#ifdef OPTEE
+ return NULL;
+#else
LHASH_OF(CONF_VALUE) *ltmp;
BIO *in=NULL;
@@ -108,6 +111,7 @@
BIO_free(in);
return ltmp;
+#endif
}
#ifndef OPENSSL_NO_FP_API
diff --git a/core/lib/openssl/crypto/conf/conf_mod.c b/core/lib/openssl/crypto/conf/conf_mod.c
index df1642a..e044ca8 100644
--- a/core/lib/openssl/crypto/conf/conf_mod.c
+++ b/core/lib/openssl/crypto/conf/conf_mod.c
@@ -64,6 +64,10 @@
#include <openssl/dso.h>
#include <openssl/x509.h>
+#ifdef OPTEE
+#include <kernel/tee_core_trace.h>
+#include <kernel/tee_common_unpg.h>
+#endif
#define DSO_mod_init_name "OPENSSL_init"
#define DSO_mod_finish_name "OPENSSL_finish"
@@ -245,6 +249,10 @@
static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
unsigned long flags)
{
+#ifdef OPTEE
+ TEE_ASSERT(!"Not implemented");
+ return NULL;
+#else
DSO *dso = NULL;
conf_init_func *ifunc;
conf_finish_func *ffunc;
@@ -285,6 +293,7 @@
CONFerr(CONF_F_MODULE_LOAD_DSO, errcode);
ERR_add_error_data(4, "module=", name, ", path=", path);
return NULL;
+#endif
}
/* add module to list */
@@ -322,6 +331,10 @@
static CONF_MODULE *module_find(char *name)
{
+#ifdef OPTEE
+ TEE_ASSERT(!"Not implemented");
+ return NULL;
+#else
CONF_MODULE *tmod;
int i, nchar;
char *p;
@@ -341,6 +354,7 @@
return NULL;
+#endif
}
/* initialize a module */
@@ -445,8 +459,10 @@
/* unload a single module */
static void module_free(CONF_MODULE *md)
{
+#ifndef OPTEE
if (md->dso)
DSO_free(md->dso);
+#endif
OPENSSL_free(md->name);
OPENSSL_free(md);
}
@@ -545,6 +561,10 @@
char *CONF_get1_default_config_file(void)
{
+#ifdef OPTEE
+ TEE_ASSERT(!"Not implemented");
+ return NULL;
+#else
char *file;
int len;
@@ -569,6 +589,7 @@
BUF_strlcat(file,OPENSSL_CONF,len + 1);
return file;
+#endif
}
/* This function takes a list separated by 'sep' and calls the
diff --git a/core/lib/openssl/crypto/conf/sub.mk b/core/lib/openssl/crypto/conf/sub.mk
new file mode 100644
index 0000000..3b269fa
--- /dev/null
+++ b/core/lib/openssl/crypto/conf/sub.mk
@@ -0,0 +1,10 @@
+incdirs-y := .. ../.. ../../include
+
+cflags-remove-y := -pedantic -Wcast-align
+cflags-y += -Wno-unused-parameter -Wno-suggest-attribute=noreturn
+cflags-y += -Wno-old-style-definition
+
+srcs-y += conf_api.c
+srcs-y += conf_def.c
+srcs-y += conf_mod.c
+srcs-y += conf_lib.c
diff --git a/core/lib/openssl/crypto/cryptlib.c b/core/lib/openssl/crypto/cryptlib.c
index 0b77d8b..91cdd29 100644
--- a/core/lib/openssl/crypto/cryptlib.c
+++ b/core/lib/openssl/crypto/cryptlib.c
@@ -116,6 +116,10 @@
#include "cryptlib.h"
#include <openssl/safestack.h>
+#ifdef OPTEE
+#include <kernel/thread.h>
+#endif
+
#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */
@@ -502,6 +506,8 @@
CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
#elif defined(OPENSSL_SYS_BEOS)
CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL));
+#elif defined(OPTEE)
+ CRYPTO_THREADID_set_numeric(id, (unsigned long)thread_get_id());
#else
/* For everything else, default to using the address of 'errno' */
CRYPTO_THREADID_set_pointer(id, (void*)&errno);
@@ -899,9 +905,12 @@
#endif
MessageBox (NULL,buf,_T("OpenSSL: FATAL"),MB_OK|MB_ICONSTOP);
}
+#elif defined(OPTEE)
+/* Nothing, OPENSSL_showfatal is a macro */
#else
void OPENSSL_showfatal (const char *fmta,...)
-{ va_list ap;
+{
+ va_list ap;
va_start (ap,fmta);
vfprintf (stderr,fmta,ap);
@@ -923,7 +932,9 @@
_exit(3);
#endif
}
-
+#ifdef OPTEE
+#define stderr NULL
+#endif
void *OPENSSL_stderr(void) { return stderr; }
int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
diff --git a/core/lib/openssl/crypto/cryptlib.h b/core/lib/openssl/crypto/cryptlib.h
index d26f963..d45e261 100644
--- a/core/lib/openssl/crypto/cryptlib.h
+++ b/core/lib/openssl/crypto/cryptlib.h
@@ -75,6 +75,10 @@
#include <openssl/err.h>
#include <openssl/opensslconf.h>
+#ifdef OPTEE
+#include <kernel/tee_core_trace.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -100,7 +104,11 @@
void OPENSSL_cpuid_setup(void);
extern unsigned int OPENSSL_ia32cap_P[];
+#ifdef OPTEE
+#define OPENSSL_showfatal(...) EMSG_RAW(__VA_ARGS__)
+#else
void OPENSSL_showfatal(const char *fmta,...);
+#endif
void *OPENSSL_stderr(void);
extern int OPENSSL_NONPIC_relocated;
diff --git a/core/lib/openssl/crypto/crypto.h b/core/lib/openssl/crypto/crypto.h
index f92fc51..7c38b9b 100644
--- a/core/lib/openssl/crypto/crypto.h
+++ b/core/lib/openssl/crypto/crypto.h
@@ -342,6 +342,14 @@
# endif
#endif
+#ifdef OPTEE_OPENSSL_NO_MEM_DBG
+#define CRYPTO_malloc_debug_init()
+#define MemCheck_start()
+#define MemCheck_stop()
+#define MemCheck_on()
+#define MemCheck_off()
+#define is_MemCheck_on() 0
+#else
/* Set standard debugging functions (not done by default
* unless CRYPTO_MDEBUG is defined) */
#define CRYPTO_malloc_debug_init() do {\
@@ -364,6 +372,7 @@
#define MemCheck_on() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)
#define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
#define is_MemCheck_on() CRYPTO_is_mem_check_on()
+#endif
#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__)
#define OPENSSL_strdup(str) CRYPTO_strdup((str),__FILE__,__LINE__)
@@ -499,6 +508,10 @@
void OPENSSL_cleanse(void *ptr, size_t len);
+#ifdef OPTEE_OPENSSL_NO_MEM_DBG
+#define CRYPTO_push_info(info)
+#define CRYPTO_pop_info(info)
+#else
void CRYPTO_set_mem_debug_options(long bits);
long CRYPTO_get_mem_debug_options(void);
@@ -538,6 +551,7 @@
/* unsigned long order, char *file, int line, int num_bytes, char *addr */
typedef void *CRYPTO_MEM_LEAK_CB(unsigned long, const char *, int, int, void *);
void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
+#endif /* !OPTEE_OPENSSL_NO_MEM_DBG */
/* die if we have to */
void OpenSSLDie(const char *file,int line,const char *assertion);
diff --git a/core/lib/openssl/crypto/des/des.h b/core/lib/openssl/crypto/des/des.h
index 1eaedcb..243769d 100644
--- a/core/lib/openssl/crypto/des/des.h
+++ b/core/lib/openssl/crypto/des/des.h
@@ -127,7 +127,9 @@
OPENSSL_DECLARE_GLOBAL(int,DES_rw_mode); /* defaults to DES_PCBC_MODE */
#define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode)
+#ifndef OPTEE
const char *DES_options(void);
+#endif
void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks1,DES_key_schedule *ks2,
DES_key_schedule *ks3, int enc);
diff --git a/core/lib/openssl/crypto/des/des_locl.h b/core/lib/openssl/crypto/des/des_locl.h
index a3b512e..39a65d5 100644
--- a/core/lib/openssl/crypto/des/des_locl.h
+++ b/core/lib/openssl/crypto/des/des_locl.h
@@ -77,9 +77,11 @@
#else
# include <unistd.h>
#endif
+#ifndef OPTEE
#include <math.h>
#endif
#endif
+#endif
#include <openssl/des.h>
#ifdef OPENSSL_SYS_MSDOS /* Visual C++ 2.1 (Windows NT/95) */
diff --git a/core/lib/openssl/crypto/des/ecb_enc.c b/core/lib/openssl/crypto/des/ecb_enc.c
index 0684e76..e9c4c7c 100644
--- a/core/lib/openssl/crypto/des/ecb_enc.c
+++ b/core/lib/openssl/crypto/des/ecb_enc.c
@@ -64,6 +64,7 @@
OPENSSL_GLOBAL const char libdes_version[]="libdes" OPENSSL_VERSION_PTEXT;
OPENSSL_GLOBAL const char DES_version[]="DES" OPENSSL_VERSION_PTEXT;
+#ifndef OPTEE
const char *DES_options(void)
{
static int init=1;
@@ -103,6 +104,7 @@
}
return(buf);
}
+#endif
void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
diff --git a/core/lib/openssl/crypto/des/sub.mk b/core/lib/openssl/crypto/des/sub.mk
new file mode 100644
index 0000000..078cbda
--- /dev/null
+++ b/core/lib/openssl/crypto/des/sub.mk
@@ -0,0 +1,11 @@
+incdirs-y := .. ../.. ../../include
+cflags-remove-y += -Wswitch-default -Wmissing-prototypes
+cflags-remove-y += -Wmissing-declarations
+cflags-y += -Wno-sign-compare
+
+srcs-y += cbc_enc.c
+srcs-y += cbc3_enc.c
+srcs-y += des_enc.c
+srcs-y += ecb3_enc.c
+srcs-y += ecb_enc.c
+srcs-y += set_key.c
diff --git a/core/lib/openssl/crypto/dh/dh.h b/core/lib/openssl/crypto/dh/dh.h
index ea59e61..3ee5790 100644
--- a/core/lib/openssl/crypto/dh/dh.h
+++ b/core/lib/openssl/crypto/dh/dh.h
@@ -192,10 +192,12 @@
void DH_free(DH *dh);
int DH_up_ref(DH *dh);
int DH_size(const DH *dh);
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int DH_set_ex_data(DH *d, int idx, void *arg);
void *DH_get_ex_data(DH *d, int idx);
+#endif
/* Deprecated version */
#ifndef OPENSSL_NO_DEPRECATED
diff --git a/core/lib/openssl/crypto/dh/dh_lib.c b/core/lib/openssl/crypto/dh/dh_lib.c
index 00218f2..8c73ba1 100644
--- a/core/lib/openssl/crypto/dh/dh_lib.c
+++ b/core/lib/openssl/crypto/dh/dh_lib.c
@@ -170,14 +170,18 @@
ret->method_mont_p=NULL;
ret->references = 1;
ret->flags=ret->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
+#endif
if ((ret->meth->init != NULL) && !ret->meth->init(ret))
{
#ifndef OPENSSL_NO_ENGINE
if (ret->engine)
ENGINE_finish(ret->engine);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
+#endif
OPENSSL_free(ret);
ret=NULL;
}
@@ -208,7 +212,9 @@
ENGINE_finish(r->engine);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
+#endif
if (r->p != NULL) BN_clear_free(r->p);
if (r->g != NULL) BN_clear_free(r->g);
@@ -237,6 +243,7 @@
return ((i > 1) ? 1 : 0);
}
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
{
@@ -253,6 +260,7 @@
{
return(CRYPTO_get_ex_data(&d->ex_data,idx));
}
+#endif
int DH_size(const DH *dh)
{
diff --git a/core/lib/openssl/crypto/dh/sub.mk b/core/lib/openssl/crypto/dh/sub.mk
new file mode 100644
index 0000000..f82528c
--- /dev/null
+++ b/core/lib/openssl/crypto/dh/sub.mk
@@ -0,0 +1,7 @@
+incdirs-y := .. ../.. ../../include ../asn1 ../evp
+
+cflags-y := -Wno-unused-parameter
+
+srcs-y += dh_check.c
+srcs-y += dh_key.c
+srcs-y += dh_lib.c
diff --git a/core/lib/openssl/crypto/dsa/dsa.h b/core/lib/openssl/crypto/dsa/dsa.h
index a6f6d0b..a36e131 100644
--- a/core/lib/openssl/crypto/dsa/dsa.h
+++ b/core/lib/openssl/crypto/dsa/dsa.h
@@ -216,10 +216,12 @@
unsigned char *sig, unsigned int *siglen, DSA *dsa);
int DSA_verify(int type,const unsigned char *dgst,int dgst_len,
const unsigned char *sigbuf, int siglen, DSA *dsa);
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int DSA_set_ex_data(DSA *d, int idx, void *arg);
void *DSA_get_ex_data(DSA *d, int idx);
+#endif
DSA * d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length);
DSA * d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length);
diff --git a/core/lib/openssl/crypto/dsa/dsa_lib.c b/core/lib/openssl/crypto/dsa/dsa_lib.c
index 96d8d0c..6ab7658 100644
--- a/core/lib/openssl/crypto/dsa/dsa_lib.c
+++ b/core/lib/openssl/crypto/dsa/dsa_lib.c
@@ -177,14 +177,18 @@
ret->references=1;
ret->flags=ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
+#endif
if ((ret->meth->init != NULL) && !ret->meth->init(ret))
{
#ifndef OPENSSL_NO_ENGINE
if (ret->engine)
ENGINE_finish(ret->engine);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
+#endif
OPENSSL_free(ret);
ret=NULL;
}
@@ -218,7 +222,9 @@
ENGINE_finish(r->engine);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
+#endif
if (r->p != NULL) BN_clear_free(r->p);
if (r->q != NULL) BN_clear_free(r->q);
@@ -268,6 +274,7 @@
return(ret);
}
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
{
@@ -284,6 +291,7 @@
{
return(CRYPTO_get_ex_data(&d->ex_data,idx));
}
+#endif
#ifndef OPENSSL_NO_DH
DH *DSA_dup_DH(const DSA *r)
diff --git a/core/lib/openssl/crypto/dsa/sub.mk b/core/lib/openssl/crypto/dsa/sub.mk
new file mode 100644
index 0000000..de4343c
--- /dev/null
+++ b/core/lib/openssl/crypto/dsa/sub.mk
@@ -0,0 +1,10 @@
+incdirs-y := .. ../.. ../../include ../asn1 ../evp
+
+cflags-y := -Wno-unused-parameter
+
+srcs-y += dsa_gen.c
+srcs-y += dsa_key.c
+srcs-y += dsa_lib.c
+srcs-y += dsa_ossl.c
+srcs-y += dsa_sign.c
+srcs-y += dsa_vrf.c
diff --git a/core/lib/openssl/crypto/err/err.c b/core/lib/openssl/crypto/err/err.c
index fcdb244..bfaf80a 100644
--- a/core/lib/openssl/crypto/err/err.c
+++ b/core/lib/openssl/crypto/err/err.c
@@ -118,6 +118,10 @@
#include <openssl/buffer.h>
#include <openssl/bio.h>
#include <openssl/err.h>
+#ifdef OPTEE
+#include <kernel/tee_core_trace.h>
+#include <kernel/tee_common_unpg.h>
+#endif
DECLARE_LHASH_OF(ERR_STRING_DATA);
DECLARE_LHASH_OF(ERR_STATE);
@@ -572,8 +576,10 @@
static void build_SYS_str_reasons(void)
{
+#ifndef OPTEE
/* OPENSSL_malloc cannot be used here, use static storage instead */
static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
+#endif
int i;
static int init = 1;
@@ -597,6 +603,7 @@
ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
str->error = (unsigned long)i;
+#ifndef OPTEE
if (str->string == NULL)
{
char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
@@ -608,6 +615,7 @@
str->string = *dest;
}
}
+#endif
if (str->string == NULL)
str->string = "unknown";
}
@@ -708,6 +716,10 @@
{
ERR_STATE *es;
+#ifdef OPTEE
+ EMSG("OpenSSL error: lib %d func %d reason %d file %s line %d", lib,
+ func, reason, file, line);
+#endif
#ifdef _OSD_POSIX
/* In the BS2000-OSD POSIX subsystem, the compiler generates
* path names in the form "*POSIX(/etc/passwd)".
diff --git a/core/lib/openssl/crypto/err/err.h b/core/lib/openssl/crypto/err/err.h
index 974cc9c..3c099cc 100644
--- a/core/lib/openssl/crypto/err/err.h
+++ b/core/lib/openssl/crypto/err/err.h
@@ -137,7 +137,9 @@
#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0)
#endif
+#ifndef OPTEE
#include <errno.h>
+#endif
#define ERR_TXT_MALLOCED 0x01
#define ERR_TXT_STRING 0x02
diff --git a/core/lib/openssl/crypto/err/sub.mk b/core/lib/openssl/crypto/err/sub.mk
new file mode 100644
index 0000000..5618760
--- /dev/null
+++ b/core/lib/openssl/crypto/err/sub.mk
@@ -0,0 +1,3 @@
+incdirs-y := .. ../.. ../../include
+
+srcs-y += err.c
diff --git a/core/lib/openssl/crypto/evp/sub.mk b/core/lib/openssl/crypto/evp/sub.mk
new file mode 100644
index 0000000..27930e3
--- /dev/null
+++ b/core/lib/openssl/crypto/evp/sub.mk
@@ -0,0 +1,19 @@
+incdirs-y := .. ../.. ../../include ../asn1 ../modes
+
+cflags-remove-y := -Wcast-align
+cflags-y := -Wno-unused-parameter
+
+srcs-y += digest.c
+srcs-y += e_aes.c
+srcs-y += e_des3.c
+srcs-y += e_des.c
+srcs-y += e_rc5.c
+srcs-y += evp_enc.c
+srcs-y += evp_lib.c
+srcs-y += m_md5.c
+srcs-y += m_sha1.c
+srcs-y += m_sha.c
+srcs-y += names.c
+srcs-y += p_lib.c
+srcs-y += pmeth_lib.c
+
diff --git a/core/lib/openssl/crypto/lhash/sub.mk b/core/lib/openssl/crypto/lhash/sub.mk
new file mode 100644
index 0000000..c63a754
--- /dev/null
+++ b/core/lib/openssl/crypto/lhash/sub.mk
@@ -0,0 +1,3 @@
+incdirs-y := ../../include
+
+srcs-y += lhash.c
diff --git a/core/lib/openssl/crypto/md32_common.h b/core/lib/openssl/crypto/md32_common.h
index bb73819..4b064eb 100644
--- a/core/lib/openssl/crypto/md32_common.h
+++ b/core/lib/openssl/crypto/md32_common.h
@@ -222,11 +222,11 @@
#endif
#ifndef HOST_c2l
-#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
- l|=(((unsigned long)(*((c)++)))<<16), \
- l|=(((unsigned long)(*((c)++)))<< 8), \
- l|=(((unsigned long)(*((c)++))) ), \
- l)
+#define HOST_c2l(c,l) ((void)(l =(((unsigned long)(*((c)++)))<<24), \
+ l|=(((unsigned long)(*((c)++)))<<16), \
+ l|=(((unsigned long)(*((c)++)))<< 8), \
+ l|=(((unsigned long)(*((c)++))) ), \
+ l))
#endif
#ifndef HOST_l2c
#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
@@ -259,11 +259,11 @@
#endif
#ifndef HOST_c2l
-#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
- l|=(((unsigned long)(*((c)++)))<< 8), \
- l|=(((unsigned long)(*((c)++)))<<16), \
- l|=(((unsigned long)(*((c)++)))<<24), \
- l)
+#define HOST_c2l(c,l) ((void)(l =(((unsigned long)(*((c)++))) ), \
+ l|=(((unsigned long)(*((c)++)))<< 8), \
+ l|=(((unsigned long)(*((c)++)))<<16), \
+ l|=(((unsigned long)(*((c)++)))<<24), \
+ l))
#endif
#ifndef HOST_l2c
#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
diff --git a/core/lib/openssl/crypto/md5/sub.mk b/core/lib/openssl/crypto/md5/sub.mk
new file mode 100644
index 0000000..559674b
--- /dev/null
+++ b/core/lib/openssl/crypto/md5/sub.mk
@@ -0,0 +1,3 @@
+incdirs-y := .. ../.. ../../include
+
+srcs-y += md5_dgst.c
diff --git a/core/lib/openssl/crypto/mem.c b/core/lib/openssl/crypto/mem.c
index 1cc62ea..9c56f4f 100644
--- a/core/lib/openssl/crypto/mem.c
+++ b/core/lib/openssl/crypto/mem.c
@@ -406,6 +406,7 @@
return(a);
}
+#ifndef OPTEE_OPENSSL_NO_MEM_DBG
void CRYPTO_set_mem_debug_options(long bits)
{
if (set_debug_options_func != NULL)
@@ -418,3 +419,4 @@
return get_debug_options_func();
return 0;
}
+#endif
diff --git a/core/lib/openssl/crypto/modes/sub.mk b/core/lib/openssl/crypto/modes/sub.mk
new file mode 100644
index 0000000..494e9f0
--- /dev/null
+++ b/core/lib/openssl/crypto/modes/sub.mk
@@ -0,0 +1,9 @@
+incdirs-y := .. ../.. ../../include
+
+cflags-remove-y := -Wcast-align
+
+srcs-y += cbc128.c
+srcs-y += ccm128.c
+srcs-y += ctr128.c
+srcs-y += gcm128.c
+srcs-y += xts128.c
diff --git a/core/lib/openssl/crypto/objects/sub.mk b/core/lib/openssl/crypto/objects/sub.mk
new file mode 100644
index 0000000..87c5e72
--- /dev/null
+++ b/core/lib/openssl/crypto/objects/sub.mk
@@ -0,0 +1,7 @@
+incdirs-y := .. ../../ ../../include
+
+cflags-remove-y := -Wredundant-decls
+
+srcs-y += o_names.c
+srcs-y += obj_dat.c
+srcs-y += obj_lib.c
diff --git a/core/lib/openssl/crypto/pem/pem.h b/core/lib/openssl/crypto/pem/pem.h
index 8a6abab..953e93b 100644
--- a/core/lib/openssl/crypto/pem/pem.h
+++ b/core/lib/openssl/crypto/pem/pem.h
@@ -325,6 +325,7 @@
#define DECLARE_PEM_read_fp(name, type) /**/
#define DECLARE_PEM_write_fp(name, type) /**/
+#define DECLARE_PEM_write_fp_const(name, type) /**/
#define DECLARE_PEM_write_cb_fp(name, type) /**/
#else
@@ -425,6 +426,7 @@
unsigned char *kstr, int klen, pem_password_cb *cd, void *u);
#endif
+#ifndef OPTEE
int PEM_read(FILE *fp, char **name, char **header,
unsigned char **data,long *len);
int PEM_write(FILE *fp,char *name,char *hdr,unsigned char *data,long len);
@@ -435,6 +437,7 @@
int klen,pem_password_cb *callback, void *u);
STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
pem_password_cb *cb, void *u);
+#endif
int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type,
EVP_MD *md_type, unsigned char **ek, int *ekl,
@@ -523,6 +526,7 @@
pem_password_cb *cb, void *u);
EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
+#ifndef OPTEE
int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
@@ -537,6 +541,7 @@
int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
char *kstr,int klen, pem_password_cb *cd, void *u);
+#endif
EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x);
diff --git a/core/lib/openssl/crypto/rand/rand_optee.c b/core/lib/openssl/crypto/rand/rand_optee.c
new file mode 100644
index 0000000..24aa825
--- /dev/null
+++ b/core/lib/openssl/crypto/rand/rand_optee.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 COPYRIGHT HOLDER OR 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 "rand.h"
+#include <rng_support.h>
+
+void RAND_add(const void *buf, int num, double entropy)
+{
+ (void)buf;
+ (void)num;
+ (void)entropy;
+}
+
+int RAND_bytes(unsigned char *buf, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ buf[i] = hw_get_random_byte();
+ return 1;
+}
+
+int RAND_pseudo_bytes(unsigned char *buf, int num)
+{
+ return RAND_bytes(buf, num);
+}
+
+int RAND_status(void)
+{
+ return 1;
+}
+
+void RAND_seed(const void *buf, int num)
+{
+ RAND_add(buf, num, (double)num);
+}
diff --git a/core/lib/openssl/crypto/rand/sub.mk b/core/lib/openssl/crypto/rand/sub.mk
new file mode 100644
index 0000000..d6b4119
--- /dev/null
+++ b/core/lib/openssl/crypto/rand/sub.mk
@@ -0,0 +1,3 @@
+incdirs-y := .. ../.. ../../include
+
+srcs-y += rand_optee.c
diff --git a/core/lib/openssl/crypto/rsa/rsa.h b/core/lib/openssl/crypto/rsa/rsa.h
index 5f269e5..e95ec6b 100644
--- a/core/lib/openssl/crypto/rsa/rsa.h
+++ b/core/lib/openssl/crypto/rsa/rsa.h
@@ -143,8 +143,10 @@
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
/* be careful using this if the RSA structure is shared */
CRYPTO_EX_DATA ex_data;
+#endif
int references;
int flags;
@@ -421,10 +423,12 @@
const unsigned char *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash, int sLen);
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int RSA_set_ex_data(RSA *r,int idx,void *arg);
void *RSA_get_ex_data(const RSA *r, int idx);
+#endif
RSA *RSAPublicKey_dup(RSA *rsa);
RSA *RSAPrivateKey_dup(RSA *rsa);
diff --git a/core/lib/openssl/crypto/rsa/rsa_crpt.c b/core/lib/openssl/crypto/rsa/rsa_crpt.c
index d3e4478..d7af414 100644
--- a/core/lib/openssl/crypto/rsa/rsa_crpt.c
+++ b/core/lib/openssl/crypto/rsa/rsa_crpt.c
@@ -245,7 +245,9 @@
RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
goto err;
}
+#ifndef OPTEE
CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
+#endif
err:
BN_CTX_end(ctx);
if (in_ctx == NULL)
diff --git a/core/lib/openssl/crypto/rsa/rsa_eay.c b/core/lib/openssl/crypto/rsa/rsa_eay.c
index aa81045..3f05c4b 100644
--- a/core/lib/openssl/crypto/rsa/rsa_eay.c
+++ b/core/lib/openssl/crypto/rsa/rsa_eay.c
@@ -197,14 +197,16 @@
case RSA_PKCS1_PADDING:
i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen);
break;
-#ifndef OPENSSL_NO_SHA
+#if !defined(OPENSSL_NO_SHA)
case RSA_PKCS1_OAEP_PADDING:
i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0);
break;
#endif
+#ifndef OPTEE_OPENSSL_NO_SSLV23_PADDING
case RSA_SSLV23_PADDING:
i=RSA_padding_add_SSLv23(buf,num,from,flen);
break;
+#endif
case RSA_NO_PADDING:
i=RSA_padding_add_none(buf,num,from,flen);
break;
@@ -256,7 +258,9 @@
{
BN_BLINDING *ret;
int got_write_lock = 0;
+#ifndef OPTEE
CRYPTO_THREADID cur;
+#endif
CRYPTO_r_lock(CRYPTO_LOCK_RSA);
@@ -274,6 +278,9 @@
if (ret == NULL)
goto err;
+#ifdef OPTEE
+ *local = 1;
+#else
CRYPTO_THREADID_current(&cur);
if (!CRYPTO_THREADID_cmp(&cur, BN_BLINDING_thread_id(ret)))
{
@@ -305,6 +312,7 @@
}
ret = rsa->mt_blinding;
}
+#endif
err:
if (got_write_lock)
@@ -378,9 +386,11 @@
case RSA_PKCS1_PADDING:
i=RSA_padding_add_PKCS1_type_1(buf,num,from,flen);
break;
+#ifndef OPTEE_OPENSSL_NO_RSA_X931_PADDING
case RSA_X931_PADDING:
i=RSA_padding_add_X931(buf,num,from,flen);
break;
+#endif
case RSA_NO_PADDING:
i=RSA_padding_add_none(buf,num,from,flen);
break;
@@ -456,6 +466,7 @@
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
+#ifndef OPTEE_OPENSSL_NO_RSA_X931_PADDING
if (padding == RSA_X931_PADDING)
{
BN_sub(f, rsa->n, ret);
@@ -465,6 +476,7 @@
res = ret;
}
else
+#endif
res = ret;
/* put in leading 0 bytes if the number is less than the
@@ -553,7 +565,6 @@
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
goto err;
}
-
/* do the decrypt */
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
((rsa->p != NULL) &&
@@ -597,14 +608,16 @@
case RSA_PKCS1_PADDING:
r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num);
break;
-#ifndef OPENSSL_NO_SHA
+#if !defined(OPENSSL_NO_SHA)
case RSA_PKCS1_OAEP_PADDING:
r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0);
break;
#endif
+#ifndef OPTEE_OPENSSL_NO_SSLV23_PADDING
case RSA_SSLV23_PADDING:
r=RSA_padding_check_SSLv23(to,num,buf,j,num);
break;
+#endif
case RSA_NO_PADDING:
r=RSA_padding_check_none(to,num,buf,j,num);
break;
@@ -696,8 +709,10 @@
if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
rsa->_method_mod_n)) goto err;
+#ifndef OPTEE_OPENSSL_NO_RSA_X931_PADDING
if ((padding == RSA_X931_PADDING) && ((ret->d[0] & 0xf) != 12))
if (!BN_sub(ret, rsa->n, ret)) goto err;
+#endif
p=buf;
i=BN_bn2bin(ret,p);
@@ -707,9 +722,11 @@
case RSA_PKCS1_PADDING:
r=RSA_padding_check_PKCS1_type_1(to,num,buf,i,num);
break;
+#ifndef OPTEE_OPENSSL_NO_RSA_X931_PADDING
case RSA_X931_PADDING:
r=RSA_padding_check_X931(to,num,buf,i,num);
break;
+#endif
case RSA_NO_PADDING:
r=RSA_padding_check_none(to,num,buf,i,num);
break;
diff --git a/core/lib/openssl/crypto/rsa/rsa_lib.c b/core/lib/openssl/crypto/rsa/rsa_lib.c
index c95ceaf..861769e 100644
--- a/core/lib/openssl/crypto/rsa/rsa_lib.c
+++ b/core/lib/openssl/crypto/rsa/rsa_lib.c
@@ -189,6 +189,7 @@
ret->mt_blinding=NULL;
ret->bignum_data=NULL;
ret->flags=ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
{
#ifndef OPENSSL_NO_ENGINE
@@ -198,6 +199,7 @@
OPENSSL_free(ret);
return(NULL);
}
+#endif
if ((ret->meth->init != NULL) && !ret->meth->init(ret))
{
@@ -205,7 +207,9 @@
if (ret->engine)
ENGINE_finish(ret->engine);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
+#endif
OPENSSL_free(ret);
ret=NULL;
}
@@ -238,7 +242,9 @@
ENGINE_finish(r->engine);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
+#endif
if (r->n != NULL) BN_clear_free(r->n);
if (r->e != NULL) BN_clear_free(r->e);
@@ -270,6 +276,7 @@
return ((i > 1) ? 1 : 0);
}
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
{
@@ -286,6 +293,7 @@
{
return(CRYPTO_get_ex_data(&r->ex_data,idx));
}
+#endif
int RSA_memory_lock(RSA *r)
{
diff --git a/core/lib/openssl/crypto/rsa/sub.mk b/core/lib/openssl/crypto/rsa/sub.mk
new file mode 100644
index 0000000..bba30b1
--- /dev/null
+++ b/core/lib/openssl/crypto/rsa/sub.mk
@@ -0,0 +1,15 @@
+incdirs-y := .. ../.. ../../include ../asn1 ../evp
+
+cflags-remove-y := -Wcast-align
+cflags-y := -Wno-empty-body -Wno-unused-parameter
+
+srcs-y += rsa_crpt.c
+srcs-y += rsa_eay.c
+srcs-y += rsa_gen.c
+srcs-y += rsa_lib.c
+srcs-y += rsa_none.c
+srcs-y += rsa_oaep.c
+srcs-y += rsa_pk1.c
+srcs-y += rsa_pmeth.c
+srcs-y += rsa_pss.c
+srcs-y += rsa_sign.c
diff --git a/core/lib/openssl/crypto/sha/sub.mk b/core/lib/openssl/crypto/sha/sub.mk
new file mode 100644
index 0000000..3c07b22
--- /dev/null
+++ b/core/lib/openssl/crypto/sha/sub.mk
@@ -0,0 +1,8 @@
+incdirs-y := .. ../.. ../../include
+
+cflags-remove-y := -Wcast-align
+
+srcs-y += sha1_one.c
+srcs-y += sha1dgst.c
+srcs-y += sha256.c
+srcs-y += sha512.c
diff --git a/core/lib/openssl/crypto/stack/stack.c b/core/lib/openssl/crypto/stack/stack.c
index 76cf1a1..96faa98 100644
--- a/core/lib/openssl/crypto/stack/stack.c
+++ b/core/lib/openssl/crypto/stack/stack.c
@@ -75,7 +75,9 @@
const char STACK_version[]="Stack" OPENSSL_VERSION_PTEXT;
+#ifndef OPTEE
#include <errno.h>
+#endif
int (*sk_set_cmp_func(_STACK *sk, int (*c)(const void *, const void *)))
(const void *, const void *)
diff --git a/core/lib/openssl/crypto/stack/sub.mk b/core/lib/openssl/crypto/stack/sub.mk
new file mode 100644
index 0000000..4b72d6c
--- /dev/null
+++ b/core/lib/openssl/crypto/stack/sub.mk
@@ -0,0 +1,3 @@
+incdirs-y := .. ../.. ../../include
+
+srcs-y += stack.c
diff --git a/core/lib/openssl/crypto/sub.mk b/core/lib/openssl/crypto/sub.mk
new file mode 100644
index 0000000..77c4239
--- /dev/null
+++ b/core/lib/openssl/crypto/sub.mk
@@ -0,0 +1,27 @@
+incdirs-y := . .. ../include
+
+cflags-remove-y := -Wredundant-decls
+cflags-y := -Wno-unused-parameter -Wno-nested-externs -Wno-suggest-attribute=noreturn
+
+srcs-y += cryptlib.c
+srcs-y += mem.c
+srcs-y += mem_clr.c
+srcs-y += o_init.c
+
+subdirs-y += asn1
+subdirs-y += aes
+subdirs-y += bn
+subdirs-y += buffer
+subdirs-y += des
+subdirs-y += dh
+subdirs-y += dsa
+subdirs-y += err
+subdirs-y += evp
+subdirs-y += lhash
+subdirs-y += md5
+subdirs-y += modes
+subdirs-y += objects
+subdirs-y += rand
+subdirs-y += rsa
+subdirs-y += sha
+subdirs-y += stack
diff --git a/core/lib/openssl/crypto/x509/x509.h b/core/lib/openssl/crypto/x509/x509.h
index 092dd74..1da9a55 100644
--- a/core/lib/openssl/crypto/x509/x509.h
+++ b/core/lib/openssl/crypto/x509/x509.h
@@ -841,10 +841,13 @@
DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int X509_set_ex_data(X509 *r, int idx, void *arg);
void *X509_get_ex_data(X509 *r, int idx);
+#endif
+
int i2d_X509_AUX(X509 *a,unsigned char **pp);
X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
diff --git a/core/lib/openssl/crypto/x509/x509_vfy.h b/core/lib/openssl/crypto/x509/x509_vfy.h
index fe09b30..0cb12e3 100644
--- a/core/lib/openssl/crypto/x509/x509_vfy.h
+++ b/core/lib/openssl/crypto/x509/x509_vfy.h
@@ -472,10 +472,12 @@
int X509_STORE_set_default_paths(X509_STORE *ctx);
#endif
+#ifndef OPTEE_OPENSSL_NO_EX_DATA
int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data);
void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx);
+#endif
int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s);
int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
diff --git a/core/lib/openssl/crypto/x509v3/x509v3.h b/core/lib/openssl/crypto/x509v3/x509v3.h
index b308abe..d9ae928 100644
--- a/core/lib/openssl/crypto/x509v3/x509v3.h
+++ b/core/lib/openssl/crypto/x509v3/x509v3.h
@@ -670,7 +670,9 @@
void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
int ml);
int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent);
+#ifndef OPENSSL_NO_FP_API
int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
+#endif
int X509V3_extensions_print(BIO *out, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent);
diff --git a/core/lib/openssl/e_os.h b/core/lib/openssl/e_os.h
index 6a0aad1..8fc2faa 100644
--- a/core/lib/openssl/e_os.h
+++ b/core/lib/openssl/e_os.h
@@ -675,7 +675,7 @@
#if defined(OPENSSL_SYS_WINDOWS)
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
-#elif defined(OPENSSL_SYS_VMS)
+#elif defined(OPENSSL_SYS_VMS) || defined(OPTEE)
/* VMS below version 7.0 doesn't have strcasecmp() */
# include "o_str.h"
# define strcasecmp OPENSSL_strcasecmp
diff --git a/core/lib/openssl/sub.mk b/core/lib/openssl/sub.mk
new file mode 100644
index 0000000..3934a92
--- /dev/null
+++ b/core/lib/openssl/sub.mk
@@ -0,0 +1,34 @@
+cppflags-lib-y += -DGETPID_IS_MEANINGLESS
+cppflags-lib-y += -DOPENSSL_NO_DEPRECATED
+cppflags-lib-y += -DOPENSSL_NO_ENGINE
+cppflags-lib-y += -DOPENSSL_NO_ERR
+cppflags-lib-y += -DOPENSSL_NO_FP_API
+cppflags-lib-y += -DOPENSSL_NO_LOCKING
+cppflags-lib-y += -DOPENSSL_NO_STDIO
+
+# OP-TEE-specific defines to remove some unused features
+cppflags-lib-y += -DOPTEE
+cppflags-lib-y += -DOPTEE_OPENSSL_NO_EX_DATA
+cppflags-lib-y += -DOPTEE_OPENSSL_NO_MEM_DBG
+cppflags-lib-y += -DOPTEE_OPENSSL_NO_PKCS12
+cppflags-lib-y += -DOPTEE_OPENSSL_NO_RSA_X931_PADDING
+cppflags-lib-y += -DOPTEE_OPENSSL_NO_SSLV23_PADDING
+
+# Enable custom modification in AES-XTS
+cppflags-lib-y += -DOPTEE_OPENSSL_AES_XTS_MULTIPLE_UPDATES
+
+# Eliminate unused symbols:
+# 1. Tell compiler to place each data/function item in its own section
+cflags-lib-y += -fdata-sections -ffunction-sections
+# 2. Tell lib.mk to use $(LD) rather than $(AR)
+lib-use-ld := y
+# 3. Tell $(LD) to perform incremental link, keeping symbol 'crypto_ops' and
+# its dependencies, then discarding unreferenced symbols
+lib-ldflags := -i --gc-sections -u crypto_ops
+
+incdirs-lib-y := ../../include
+incdirs-y := include
+
+srcs-y += tee_ossl_provider.c
+
+subdirs-y += crypto
diff --git a/core/lib/openssl/tee_ossl_provider.c b/core/lib/openssl/tee_ossl_provider.c
new file mode 100644
index 0000000..f760217
--- /dev/null
+++ b/core/lib/openssl/tee_ossl_provider.c
@@ -0,0 +1,2574 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 COPYRIGHT HOLDER OR 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.
+ *
+ *
+ * The HMAC and AES-CMAC code below is adapted from OpenSSL. The following
+ * notice applies.
+ *
+ *
+ * ====================================================================
+ * Copyright (c) 2010 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 <tee/tee_cryp_provider.h>
+#include <tee/tee_cryp_utl.h>
+#include <kernel/tee_ta_manager_unpg.h>
+#include <kernel/tee_core_trace.h>
+#include <kernel/util.h>
+#include <compiler.h>
+#include <utee_defines.h>
+#include <openssl/bn.h>
+#include <openssl/aes.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+
+static TEE_Result tee_ossl_init(void)
+{
+ EVP_add_digest(EVP_md5());
+ EVP_add_digest(EVP_sha1());
+ EVP_add_digest(EVP_sha224());
+ EVP_add_digest(EVP_sha256());
+ EVP_add_digest(EVP_sha384());
+ EVP_add_digest(EVP_sha512());
+
+ EVP_add_cipher(EVP_aes_128_cbc());
+ EVP_add_cipher(EVP_aes_128_ccm());
+ EVP_add_cipher(EVP_aes_128_ctr());
+ EVP_add_cipher(EVP_aes_128_ecb());
+ EVP_add_cipher(EVP_aes_128_gcm());
+ EVP_add_cipher(EVP_aes_128_xts());
+ EVP_add_cipher(EVP_aes_192_cbc());
+ EVP_add_cipher(EVP_aes_192_ccm());
+ EVP_add_cipher(EVP_aes_192_ctr());
+ EVP_add_cipher(EVP_aes_192_ecb());
+ EVP_add_cipher(EVP_aes_192_gcm());
+ EVP_add_cipher(EVP_aes_256_cbc());
+ EVP_add_cipher(EVP_aes_256_ccm());
+ EVP_add_cipher(EVP_aes_256_ctr());
+ EVP_add_cipher(EVP_aes_256_ecb());
+ EVP_add_cipher(EVP_aes_256_gcm());
+ EVP_add_cipher(EVP_aes_256_xts());
+ EVP_add_cipher(EVP_des_cbc());
+ EVP_add_cipher(EVP_des_ecb());
+ EVP_add_cipher(EVP_des_ede3_cbc());
+ EVP_add_cipher(EVP_des_ede3_ecb());
+ EVP_add_cipher(EVP_des_ede_cbc());
+ EVP_add_cipher(EVP_des_ede_ecb());
+
+ return TEE_SUCCESS;
+}
+
+
+/******************************************************************************
+ * Message digest functions
+ ******************************************************************************/
+
+static int hash_supported(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_MD5:
+ case TEE_ALG_SHA1:
+ case TEE_ALG_SHA224:
+ case TEE_ALG_SHA256:
+ case TEE_ALG_SHA384:
+ case TEE_ALG_SHA512:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static size_t hash_get_blocksize(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_MD5:
+ case TEE_ALG_SHA1:
+ case TEE_ALG_SHA224:
+ case TEE_ALG_SHA256:
+ return 64;
+ case TEE_ALG_SHA384:
+ case TEE_ALG_SHA512:
+ return 128;
+ default:
+ return 0;
+ }
+}
+
+static TEE_Result hash_get_ctx_size(uint32_t algo, size_t *size)
+{
+ if (!hash_supported(algo))
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ *size = sizeof(EVP_MD_CTX);
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result hash_init(void *ctx, uint32_t algo)
+{
+ int st;
+ const struct env_md_st *md;
+
+ switch (algo) {
+ case TEE_ALG_MD5:
+ md = EVP_md5();
+ break;
+ case TEE_ALG_SHA1:
+ md = EVP_sha1();
+ break;
+ case TEE_ALG_SHA224:
+ md = EVP_sha224();
+ break;
+ case TEE_ALG_SHA256:
+ md = EVP_sha256();
+ break;
+ case TEE_ALG_SHA384:
+ md = EVP_sha384();
+ break;
+ case TEE_ALG_SHA512:
+ md = EVP_sha512();
+ break;
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ st = EVP_DigestInit(ctx, md);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result hash_update(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t len)
+{
+ int st;
+
+ if (!hash_supported(algo))
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ st = EVP_DigestUpdate(ctx, data, len);
+
+ return (st == 1) ? TEE_SUCCESS : TEE_ERROR_BAD_STATE;
+}
+
+static TEE_Result hash_final(void *ctx, uint32_t algo, uint8_t *digest,
+ size_t len)
+{
+ int st;
+ size_t hash_size;
+ uint8_t buf[64], *out;
+
+ if (!hash_supported(algo))
+ return TEE_ERROR_NOT_SUPPORTED;
+ if (tee_hash_get_digest_size(algo, &hash_size) != TEE_SUCCESS)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ if ((len == 0) || (hash_size < len) || (hash_size > sizeof(buf)))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ out = (hash_size > len) ? buf : digest;
+
+ st = EVP_DigestFinal(ctx, out, NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+
+ if (hash_size > len)
+ memcpy(digest, out, len);
+
+ return TEE_SUCCESS;
+}
+
+
+/******************************************************************************
+ * Symmetric ciphers
+ ******************************************************************************/
+
+struct aes_cts_ctx {
+ EVP_CIPHER_CTX ecb;
+ EVP_CIPHER_CTX cbc;
+};
+
+static int cipher_supported(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_AES_ECB_NOPAD:
+ case TEE_ALG_AES_CBC_NOPAD:
+ case TEE_ALG_AES_CTR:
+ case TEE_ALG_AES_CTS:
+ case TEE_ALG_DES_ECB_NOPAD:
+ case TEE_ALG_DES_CBC_NOPAD:
+ case TEE_ALG_DES3_ECB_NOPAD:
+ case TEE_ALG_DES3_CBC_NOPAD:
+ case TEE_ALG_AES_XTS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static TEE_Result cipher_get_ctx_size(uint32_t algo, size_t *size)
+{
+ switch (algo) {
+ case TEE_ALG_AES_ECB_NOPAD:
+ case TEE_ALG_AES_CBC_NOPAD:
+ case TEE_ALG_AES_CTR:
+ case TEE_ALG_DES_ECB_NOPAD:
+ case TEE_ALG_DES_CBC_NOPAD:
+ case TEE_ALG_DES3_ECB_NOPAD:
+ case TEE_ALG_DES3_CBC_NOPAD:
+ case TEE_ALG_AES_XTS:
+ *size = sizeof(EVP_CIPHER_CTX);
+ break;
+ case TEE_ALG_AES_CTS:
+ *size = sizeof(struct aes_cts_ctx);
+ break;
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result cipher_init(void *ctx, uint32_t algo, TEE_OperationMode mode,
+ const uint8_t *key1, size_t key1_len,
+ const uint8_t *key2, size_t key2_len,
+ const uint8_t *iv, size_t iv_len)
+{
+ int st;
+ TEE_Result tres;
+ struct aes_cts_ctx *acts;
+ const struct evp_cipher_st *cipher;
+ uint8_t *key = (uint8_t *)key1;
+
+ switch (algo) {
+ case TEE_ALG_AES_ECB_NOPAD:
+ if (key1_len == 16)
+ cipher = EVP_aes_128_ecb();
+ else if (key1_len == 24)
+ cipher = EVP_aes_192_ecb();
+ else if (key1_len == 32)
+ cipher = EVP_aes_256_ecb();
+ else
+ return TEE_ERROR_NOT_SUPPORTED;
+ break;
+ case TEE_ALG_AES_CBC_NOPAD:
+ if (key1_len == 16)
+ cipher = EVP_aes_128_cbc();
+ else if (key1_len == 24)
+ cipher = EVP_aes_192_cbc();
+ else if (key1_len == 32)
+ cipher = EVP_aes_256_cbc();
+ else
+ return TEE_ERROR_NOT_SUPPORTED;
+ break;
+ case TEE_ALG_AES_CTR:
+ if (key1_len == 16)
+ cipher = EVP_aes_128_ctr();
+ else if (key1_len == 24)
+ cipher = EVP_aes_192_ctr();
+ else if (key1_len == 32)
+ cipher = EVP_aes_256_ctr();
+ else
+ return TEE_ERROR_NOT_SUPPORTED;
+ break;
+ case TEE_ALG_AES_CTS:
+ acts = ctx;
+ tres = cipher_init(&acts->ecb, TEE_ALG_AES_ECB_NOPAD, mode,
+ key1, key1_len, key2, key2_len, iv, iv_len);
+ if (tres != TEE_SUCCESS)
+ return tres;
+ tres = cipher_init(&acts->cbc, TEE_ALG_AES_CBC_NOPAD, mode,
+ key1, key1_len, key2, key2_len, iv, iv_len);
+ if (tres != TEE_SUCCESS)
+ return tres;
+ return TEE_SUCCESS;
+ case TEE_ALG_DES_ECB_NOPAD:
+ cipher = EVP_des_ecb();
+ break;
+ case TEE_ALG_DES_CBC_NOPAD:
+ cipher = EVP_des_cbc();
+ break;
+ case TEE_ALG_DES3_ECB_NOPAD:
+ if (key1_len == 16) {
+ /* 2-DES */
+ cipher = EVP_des_ede_ecb();
+ } else if (key1_len == 24) {
+ /* 3-DES */
+ cipher = EVP_des_ede3_ecb();
+ } else {
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+ break;
+ case TEE_ALG_DES3_CBC_NOPAD:
+ if (key1_len == 16) {
+ /* 2-DES */
+ cipher = EVP_des_ede_cbc();
+ } else if (key1_len == 24) {
+ /* 3-DES */
+ cipher = EVP_des_ede3_cbc();
+ } else {
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+ break;
+ case TEE_ALG_AES_XTS:
+ if (key1_len == 16)
+ cipher = EVP_aes_128_xts();
+ else if (key1_len == 32)
+ cipher = EVP_aes_256_xts();
+ else
+ return TEE_ERROR_NOT_SUPPORTED;
+ break;
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ if (algo == TEE_ALG_AES_XTS) {
+ key = malloc(key1_len + key2_len);
+ if (!key)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ memcpy(key, key1, key1_len);
+ memcpy(key + key1_len, key2, key2_len);
+ }
+
+ if (mode == TEE_MODE_ENCRYPT)
+ st = EVP_EncryptInit(ctx, cipher, key, iv);
+ else
+ st = EVP_DecryptInit(ctx, cipher, key, iv);
+
+ if (algo == TEE_ALG_AES_XTS)
+ free(key);
+
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+
+ st = EVP_CIPHER_CTX_set_padding(ctx, 0);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result cipher_update(void *ctx, uint32_t algo,
+ TEE_OperationMode mode,
+ bool last_block, const uint8_t *data,
+ size_t len, uint8_t *dst)
+{
+ struct aes_cts_ctx *acts;
+ int st;
+ int outl = 0;
+
+ if (!cipher_supported(algo))
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ if (algo == TEE_ALG_AES_CTS) {
+ acts = ctx;
+ return tee_aes_cbc_cts_update(&acts->cbc, &acts->ecb, mode,
+ last_block, data, len, dst);
+ }
+
+ if (mode == TEE_MODE_ENCRYPT) {
+ st = EVP_EncryptUpdate(ctx, dst, &outl, data, len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ if (last_block) {
+ st = EVP_EncryptFinal(ctx, dst + outl, &outl);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ }
+ } else {
+ st = EVP_DecryptUpdate(ctx, dst, &outl, data, len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ if (last_block) {
+ st = EVP_DecryptFinal(ctx, dst + outl, &outl);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ }
+ }
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static void cipher_final(void *ctx, uint32_t algo __unused)
+{
+ (void)EVP_CIPHER_CTX_cleanup(ctx);
+}
+
+/*****************************************************************************
+ * Message Authentication Code functions
+ *****************************************************************************/
+
+/*
+ * The hmac_* functions below are heavily inspired from OpenSSL's HMAC_*
+ * functions. We don't use the OpenSSL ones because they bring in too many
+ * dependencies due to the EVP* stuff.
+ */
+#define HMAC_MAX_BLOCKSIZE 128 /* Largest block size is SHA512 */
+
+#define HASH_CTX_MAX_SIZE sizeof(EVP_MD_CTX)
+
+struct hmac_ctx {
+ uint8_t key[HMAC_MAX_BLOCKSIZE];
+ size_t keylen;
+ uint8_t ctx[HASH_CTX_MAX_SIZE];
+ uint8_t i_ctx[HASH_CTX_MAX_SIZE];
+ uint8_t o_ctx[HASH_CTX_MAX_SIZE];
+};
+
+static int32_t hmac_get_base_algo(int32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_HMAC_MD5:
+ return TEE_ALG_MD5;
+ case TEE_ALG_HMAC_SHA1:
+ return TEE_ALG_SHA1;
+ case TEE_ALG_HMAC_SHA224:
+ return TEE_ALG_SHA224;
+ case TEE_ALG_HMAC_SHA256:
+ return TEE_ALG_SHA256;
+ case TEE_ALG_HMAC_SHA384:
+ return TEE_ALG_SHA384;
+ case TEE_ALG_HMAC_SHA512:
+ return TEE_ALG_SHA512;
+ default:
+ return 0;
+ }
+}
+
+static TEE_Result hmac_init(void *ctx, int32_t algo, const uint8_t *key,
+ size_t keylen)
+{
+ TEE_Result res;
+ struct hmac_ctx *h_ctx;
+ uint32_t h_alg;
+ size_t blocksize, i;
+ uint8_t pad[HMAC_MAX_BLOCKSIZE];
+
+ h_ctx = ctx;
+ memset(h_ctx, 0, sizeof(*h_ctx));
+
+ h_alg = hmac_get_base_algo(algo);
+ blocksize = hash_get_blocksize(h_alg);
+ if (blocksize == 0) {
+ res = TEE_ERROR_BAD_STATE;
+ goto err;
+ }
+
+ if (keylen > blocksize) {
+ /* Key shall be shortened by hashing */
+ res = hash_init(h_ctx->ctx, h_alg);
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = hash_update(h_ctx->ctx, h_alg, key, keylen);
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = hash_final(h_ctx->ctx, h_alg, h_ctx->key,
+ sizeof(h_ctx->key));
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = tee_hash_get_digest_size(algo, &h_ctx->keylen);
+ if (res != TEE_SUCCESS)
+ goto err;
+ }
+ if (keylen < blocksize) {
+ /* Key shall be zero-padded (already done by above memset) */
+ memcpy(h_ctx->key, key, keylen);
+ h_ctx->keylen = keylen;
+ }
+
+ for (i = 0; i < HMAC_MAX_BLOCKSIZE; i++)
+ pad[i] = 0x36 ^ h_ctx->key[i];
+ res = hash_init(h_ctx->i_ctx, h_alg);
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = hash_update(h_ctx->i_ctx, h_alg, pad, blocksize);
+ if (res != TEE_SUCCESS)
+ goto err;
+
+ for (i = 0; i < HMAC_MAX_BLOCKSIZE; i++)
+ pad[i] = 0x5c ^ h_ctx->key[i];
+ res = hash_init(h_ctx->o_ctx, h_alg);
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = hash_update(h_ctx->o_ctx, h_alg, pad, blocksize);
+ if (res != TEE_SUCCESS)
+ goto err;
+
+ /*
+ * This assumes that hash contexts are self-contained
+ * (which is the case for OpenSSL's MD5_CTX/SHA_CTX etc.)
+ */
+ memcpy(h_ctx->ctx, h_ctx->i_ctx, sizeof(h_ctx->ctx));
+ res = TEE_SUCCESS;
+
+err:
+ return res;
+}
+
+static TEE_Result hmac_update(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t len)
+{
+ struct hmac_ctx *hctx = ctx;
+
+ return hash_update(hctx->ctx, hmac_get_base_algo(algo), data, len);
+}
+
+static TEE_Result hmac_final(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t data_len, uint8_t *digest,
+ size_t digest_len)
+{
+ TEE_Result res;
+ uint32_t h_alg;
+ struct hmac_ctx *h_ctx;
+ size_t h_size;
+ uint8_t buf[HMAC_MAX_BLOCKSIZE];
+
+ if (data && data_len) {
+ res = hmac_update(ctx, algo, data, data_len);
+ if (res != TEE_SUCCESS)
+ goto err;
+ }
+ h_ctx = ctx;
+ h_alg = hmac_get_base_algo(algo);
+ res = tee_hash_get_digest_size(algo, &h_size);
+ if (res != TEE_SUCCESS)
+ goto err;
+ if (h_size > sizeof(buf)) {
+ res = TEE_ERROR_BAD_STATE;
+ goto err;
+ }
+ res = hash_final(h_ctx->ctx, h_alg, buf, h_size);
+ if (res != TEE_SUCCESS)
+ goto err;
+ memcpy(h_ctx->ctx, h_ctx->o_ctx, sizeof(h_ctx->ctx));
+ res = hash_update(h_ctx->ctx, h_alg, buf, h_size);
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = hash_final(h_ctx->ctx, h_alg, digest, digest_len);
+err:
+ return res;
+}
+
+/*
+ * AES/DES/DES3 CBC-MAC code is based on the tee_ltc_provider.c implementation.
+ * This code could be slightly refactored and moved to tee_svc_cryp.c. The only
+ * difficulty is to deal with the size of the CBC contexts which are not
+ * statically known at compile time in tee_svc_cryp.c.
+ */
+
+#define CBCMAC_MAX_BLOCK_LEN 16
+struct cbc_mac_ctx {
+ EVP_CIPHER_CTX cipher_ctx;
+ uint8_t block[CBCMAC_MAX_BLOCK_LEN];
+ uint8_t digest[CBCMAC_MAX_BLOCK_LEN];
+ size_t current_block_len, block_len;
+ int is_computed;
+};
+
+static uint32_t cbc_mac_get_base_algo(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_AES_CBC_MAC_NOPAD:
+ case TEE_ALG_AES_CBC_MAC_PKCS5:
+ return TEE_ALG_AES_CBC_NOPAD;
+ case TEE_ALG_DES_CBC_MAC_NOPAD:
+ case TEE_ALG_DES_CBC_MAC_PKCS5:
+ return TEE_ALG_DES_CBC_NOPAD;
+ case TEE_ALG_DES3_CBC_MAC_NOPAD:
+ case TEE_ALG_DES3_CBC_MAC_PKCS5:
+ return TEE_ALG_DES3_CBC_NOPAD;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static TEE_Result cbc_mac_init(void *ctx, uint32_t algo, const uint8_t *key,
+ size_t len)
+{
+ TEE_Result res;
+ uint32_t c_alg;
+ struct cbc_mac_ctx *cbc_mac;
+ uint8_t iv[CBCMAC_MAX_BLOCK_LEN];
+
+ cbc_mac = ctx;
+ memset(cbc_mac, 0, sizeof(*cbc_mac));
+ c_alg = cbc_mac_get_base_algo(algo);
+ res = tee_cipher_get_block_size(c_alg, &cbc_mac->block_len);
+ if (res != TEE_SUCCESS)
+ goto err;
+ if (cbc_mac->block_len > CBCMAC_MAX_BLOCK_LEN) {
+ res = TEE_ERROR_BAD_STATE;
+ goto err;
+ }
+ memset(iv, 0, cbc_mac->block_len);
+ res = cipher_init(&cbc_mac->cipher_ctx, c_alg, TEE_MODE_ENCRYPT, key,
+ len, NULL, 0, iv, cbc_mac->block_len);
+err:
+ return res;
+}
+
+static TEE_Result cbc_mac_update(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t len)
+{
+ TEE_Result res;
+ uint32_t c_alg;
+ struct cbc_mac_ctx *cbc;
+ size_t pad_len;
+
+ cbc = ctx;
+ c_alg = cbc_mac_get_base_algo(algo);
+
+ if ((cbc->current_block_len > 0) &&
+ (len + cbc->current_block_len >= cbc->block_len)) {
+ pad_len = cbc->block_len - cbc->current_block_len;
+ memcpy(cbc->block + cbc->current_block_len,
+ data, pad_len);
+ data += pad_len;
+ len -= pad_len;
+ res = cipher_update(&cbc->cipher_ctx, c_alg, TEE_MODE_ENCRYPT,
+ 0, cbc->block, cbc->block_len,
+ cbc->digest);
+ if (res != TEE_SUCCESS)
+ return TEE_ERROR_BAD_STATE;
+ cbc->is_computed = 1;
+ }
+
+ while (len >= cbc->block_len) {
+ res = cipher_update(&cbc->cipher_ctx, c_alg, TEE_MODE_ENCRYPT,
+ 0, data, cbc->block_len, cbc->digest);
+ if (res != TEE_SUCCESS)
+ return TEE_ERROR_BAD_STATE;
+ cbc->is_computed = 1;
+ data += cbc->block_len;
+ len -= cbc->block_len;
+ }
+
+ if (len > 0)
+ memcpy(cbc->block, data, len);
+
+ cbc->current_block_len = len;
+
+ res = TEE_SUCCESS;
+ return res;
+}
+
+static TEE_Result cbc_mac_final(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t data_len, uint8_t *digest,
+ size_t digest_len)
+{
+ struct cbc_mac_ctx *cbc;
+ size_t pad_len;
+
+ cbc = ctx;
+ if (cbc_mac_update(ctx, algo, data, data_len) != TEE_SUCCESS)
+ return TEE_ERROR_BAD_STATE;
+
+ switch (algo) {
+ case TEE_ALG_AES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES3_CBC_MAC_PKCS5:
+ /*
+ * Add PKCS5 padding. The value of each added byte is the
+ * number of bytes that are added, i.e., append '0x01' when 1
+ * byte is needed, '0x02 0x02' when two bytes are needed, etc.
+ */
+ pad_len = cbc->block_len - cbc->current_block_len;
+ memset(cbc->block+cbc->current_block_len, pad_len, pad_len);
+ cbc->current_block_len = 0;
+ if (cbc_mac_update(ctx, algo, cbc->block, cbc->block_len)
+ != TEE_SUCCESS)
+ return TEE_ERROR_BAD_STATE;
+ break;
+ default:
+ /* No padding is required */
+ break;
+ }
+
+ if ((!cbc->is_computed) || (cbc->current_block_len != 0))
+ return TEE_ERROR_BAD_STATE;
+
+ memcpy(digest, cbc->digest, MIN(digest_len, cbc->block_len));
+ cipher_final(&cbc->cipher_ctx, algo);
+
+ return TEE_SUCCESS;
+}
+
+/*
+ * cmac_*: AES-CMAC, adapted from OpenSSL's CMAC_* implementation
+ */
+struct cmac_aes_cbc_ctx {
+ EVP_CIPHER_CTX cipher_ctx;
+ uint8_t k1[AES_BLOCK_SIZE], k2[AES_BLOCK_SIZE];
+ uint8_t tbl[AES_BLOCK_SIZE];
+ uint8_t last_block[AES_BLOCK_SIZE];
+ ssize_t nlast_block;
+};
+
+/* Make temporary keys k1 and k2 */
+static void cmac_make_kn(uint8_t *k1, uint8_t *l, size_t bl)
+{
+ size_t i;
+ /* Shift block to left, including carry */
+ for (i = 0; i < bl; i++) {
+ k1[i] = l[i] << 1;
+ if (i < bl - 1 && l[i + 1] & 0x80)
+ k1[i] |= 1;
+ }
+ /* If MSB set fixup with R */
+ if (l[0] & 0x80)
+ k1[bl - 1] ^= bl == 16 ? 0x87 : 0x1b;
+}
+
+static TEE_Result cmac_aes_cbc_init(void *ctx, const uint8_t *key,
+ size_t keylen)
+{
+ TEE_Result res;
+ struct cmac_aes_cbc_ctx *c_ctx;
+ static uint8_t zero_iv[AES_BLOCK_SIZE];
+ const size_t bl = AES_BLOCK_SIZE;
+
+
+ c_ctx = ctx;
+ memset(c_ctx, 0, sizeof(*c_ctx));
+ res = cipher_init(&c_ctx->cipher_ctx, TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, key, keylen, NULL, 0, zero_iv,
+ sizeof(zero_iv));
+ if (res != TEE_SUCCESS)
+ goto err;
+ res = cipher_update(&c_ctx->cipher_ctx, TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, false, zero_iv, sizeof(zero_iv),
+ c_ctx->tbl);
+ if (res != TEE_SUCCESS)
+ goto err;
+ cmac_make_kn(c_ctx->k1, c_ctx->tbl, bl);
+ cmac_make_kn(c_ctx->k2, c_ctx->k1, bl);
+ memset(c_ctx->tbl, 0, bl);
+ /* Reset context again, ready for first data block */
+ res = cipher_init(&c_ctx->cipher_ctx, TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, key, keylen, NULL, 0, zero_iv,
+ sizeof(zero_iv));
+ if (res != TEE_SUCCESS)
+ goto err;
+ c_ctx->nlast_block = 0;
+err:
+ return res;
+}
+
+static TEE_Result cmac_aes_cbc_update(void *ctx, const uint8_t *in,
+ size_t dlen)
+{
+ TEE_Result res;
+ struct cmac_aes_cbc_ctx *c_ctx = ctx;
+ const size_t bl = AES_BLOCK_SIZE;
+ const uint8_t *data = in;
+
+ if (c_ctx->nlast_block == -1)
+ return TEE_ERROR_BAD_STATE;
+ if (dlen == 0)
+ return TEE_SUCCESS;
+ /* Copy into partial block if we need to */
+ if (c_ctx->nlast_block > 0) {
+ size_t nleft;
+
+ nleft = bl - c_ctx->nlast_block;
+ if (dlen < nleft)
+ nleft = dlen;
+ memcpy(c_ctx->last_block + c_ctx->nlast_block, data, nleft);
+ dlen -= nleft;
+ c_ctx->nlast_block += nleft;
+ /* If no more to process return */
+ if (dlen == 0)
+ return TEE_SUCCESS;
+ data += nleft;
+ /* Else not final block so encrypt it */
+ res = cipher_update(&c_ctx->cipher_ctx, TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, false, c_ctx->last_block,
+ bl, c_ctx->tbl);
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+ /* Encrypt all but one of the complete blocks left */
+ while (dlen > bl) {
+ res = cipher_update(&c_ctx->cipher_ctx, TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, false, data,
+ bl, c_ctx->tbl);
+ if (res != TEE_SUCCESS)
+ return res;
+ dlen -= bl;
+ data += bl;
+ }
+ /* Copy any data left to last block buffer */
+ memcpy(c_ctx->last_block, data, dlen);
+ c_ctx->nlast_block = dlen;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result cmac_aes_cbc_final(void *ctx, const uint8_t *data,
+ size_t data_len, uint8_t *digest,
+ size_t digest_len __unused)
+{
+ TEE_Result res;
+ struct cmac_aes_cbc_ctx *c_ctx = ctx;
+ const size_t bl = AES_BLOCK_SIZE;
+ size_t i, lb;
+
+ if (data && data_len) {
+ res = cmac_aes_cbc_update(ctx, data, data_len);
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+ if (c_ctx->nlast_block == -1)
+ return TEE_ERROR_BAD_STATE;
+ lb = c_ctx->nlast_block;
+ /* Is last block complete? */
+ if (lb == bl) {
+ for (i = 0; i < bl; i++)
+ digest[i] = c_ctx->last_block[i] ^ c_ctx->k1[i];
+ } else {
+ c_ctx->last_block[lb] = 0x80;
+ if (bl - lb > 1)
+ memset(c_ctx->last_block + lb + 1, 0, bl - lb - 1);
+ for (i = 0; i < bl; i++)
+ digest[i] = c_ctx->last_block[i] ^ c_ctx->k2[i];
+ }
+ res = cipher_update(&c_ctx->cipher_ctx, TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, false, digest, bl, digest);
+ if (res != TEE_SUCCESS) {
+ memset(digest, 0, bl);
+ return res;
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result mac_get_ctx_size(uint32_t algo, size_t *size)
+{
+ switch (algo) {
+ case TEE_ALG_HMAC_MD5:
+ case TEE_ALG_HMAC_SHA224:
+ case TEE_ALG_HMAC_SHA1:
+ case TEE_ALG_HMAC_SHA256:
+ case TEE_ALG_HMAC_SHA384:
+ case TEE_ALG_HMAC_SHA512:
+ *size = sizeof(struct hmac_ctx);
+ break;
+ case TEE_ALG_AES_CBC_MAC_NOPAD:
+ case TEE_ALG_AES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES_CBC_MAC_NOPAD:
+ case TEE_ALG_DES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES3_CBC_MAC_NOPAD:
+ case TEE_ALG_DES3_CBC_MAC_PKCS5:
+ *size = sizeof(struct cbc_mac_ctx);
+ break;
+ case TEE_ALG_AES_CMAC:
+ *size = sizeof(struct cmac_aes_cbc_ctx);
+ break;
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result mac_init(void *ctx, uint32_t algo, const uint8_t *key,
+ size_t len)
+{
+ switch (algo) {
+ case TEE_ALG_HMAC_MD5:
+ case TEE_ALG_HMAC_SHA224:
+ case TEE_ALG_HMAC_SHA1:
+ case TEE_ALG_HMAC_SHA256:
+ case TEE_ALG_HMAC_SHA384:
+ case TEE_ALG_HMAC_SHA512:
+ return hmac_init(ctx, algo, key, len);
+ case TEE_ALG_AES_CBC_MAC_NOPAD:
+ case TEE_ALG_AES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES_CBC_MAC_NOPAD:
+ case TEE_ALG_DES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES3_CBC_MAC_NOPAD:
+ case TEE_ALG_DES3_CBC_MAC_PKCS5:
+ return cbc_mac_init(ctx, algo, key, len);
+ case TEE_ALG_AES_CMAC:
+ return cmac_aes_cbc_init(ctx, key, len);
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+}
+
+static TEE_Result mac_update(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t len)
+{
+ switch (algo) {
+ case TEE_ALG_HMAC_MD5:
+ case TEE_ALG_HMAC_SHA224:
+ case TEE_ALG_HMAC_SHA1:
+ case TEE_ALG_HMAC_SHA256:
+ case TEE_ALG_HMAC_SHA384:
+ case TEE_ALG_HMAC_SHA512:
+ return hmac_update(ctx, algo, data, len);
+ case TEE_ALG_AES_CBC_MAC_NOPAD:
+ case TEE_ALG_AES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES_CBC_MAC_NOPAD:
+ case TEE_ALG_DES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES3_CBC_MAC_NOPAD:
+ case TEE_ALG_DES3_CBC_MAC_PKCS5:
+ return cbc_mac_update(ctx, algo, data, len);
+ case TEE_ALG_AES_CMAC:
+ return cmac_aes_cbc_update(ctx, data, len);
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+}
+
+static TEE_Result mac_final(void *ctx, uint32_t algo, const uint8_t *data,
+ size_t data_len, uint8_t *digest,
+ size_t digest_len)
+{
+ switch (algo) {
+ case TEE_ALG_HMAC_MD5:
+ case TEE_ALG_HMAC_SHA224:
+ case TEE_ALG_HMAC_SHA1:
+ case TEE_ALG_HMAC_SHA256:
+ case TEE_ALG_HMAC_SHA384:
+ case TEE_ALG_HMAC_SHA512:
+ return hmac_final(ctx, algo, data, data_len, digest,
+ digest_len);
+ case TEE_ALG_AES_CBC_MAC_NOPAD:
+ case TEE_ALG_AES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES_CBC_MAC_NOPAD:
+ case TEE_ALG_DES_CBC_MAC_PKCS5:
+ case TEE_ALG_DES3_CBC_MAC_NOPAD:
+ case TEE_ALG_DES3_CBC_MAC_PKCS5:
+ return cbc_mac_final(ctx, algo, data, data_len, digest,
+ digest_len);
+ case TEE_ALG_AES_CMAC:
+ return cmac_aes_cbc_final(ctx, data, data_len, digest,
+ digest_len);
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+}
+
+/******************************************************************************
+ * Big numbers
+ ******************************************************************************/
+
+static size_t num_bytes(struct bignum *a)
+{
+ return BN_num_bytes((const struct bignum_st *)a);
+}
+
+static void bn2bin(const struct bignum *from, uint8_t *to)
+{
+ BN_bn2bin((const struct bignum_st *)from, to);
+}
+
+static TEE_Result bin2bn(const uint8_t *from, size_t fromsize,
+ struct bignum *to)
+{
+ if (BN_bin2bn(from, fromsize, (struct bignum_st *)to))
+ return TEE_SUCCESS;
+ /*
+ * The only error situation is when struct bignum_st storage cannot be
+ * expanded.
+ */
+ return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static void bn_copy(struct bignum *to, const struct bignum *from)
+{
+ BN_copy((struct bignum_st *)to, (const struct bignum_st *)from);
+}
+
+static struct bignum *bn_allocate(size_t size_bits __unused)
+{
+ return (struct bignum *)BN_new();
+}
+
+static void bn_free(struct bignum *s)
+{
+ BN_free((struct bignum_st *)s);
+}
+
+
+static TEE_Result alloc_rsa_keypair(struct rsa_keypair *s,
+ size_t key_size_bits __unused)
+{
+ memset(s, 0, sizeof(*s));
+ s->e = (struct bignum *)BN_new();
+ if (!s->e)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ s->d = (struct bignum *)BN_new();
+ if (!s->d)
+ goto err;
+ s->n = (struct bignum *)BN_new();
+ if (!s->n)
+ goto err;
+ s->p = (struct bignum *)BN_new();
+ if (!s->p)
+ goto err;
+ BN_set_word((struct bignum_st *)s->p, 0);
+ s->q = (struct bignum *)BN_new();
+ if (!s->q)
+ goto err;
+ s->qp = (struct bignum *)BN_new();
+ if (!s->qp)
+ goto err;
+ s->dp = (struct bignum *)BN_new();
+ if (!s->dp)
+ goto err;
+ s->dq = (struct bignum *)BN_new();
+ if (!s->dq)
+ goto err;
+ return TEE_SUCCESS;
+err:
+ free(s->e);
+ free(s->d);
+ free(s->n);
+ free(s->p);
+ free(s->q);
+ free(s->qp);
+ free(s->dp);
+ return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result alloc_rsa_public_key(struct rsa_public_key *s,
+ size_t key_size_bits __unused)
+{
+ memset(s, 0, sizeof(*s));
+ s->e = (struct bignum *)BN_new();
+ if (!s->e)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ s->n = (struct bignum *)BN_new();
+ if (!s->n)
+ goto err;
+ return TEE_SUCCESS;
+err:
+ free(s->e);
+ return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result alloc_dsa_keypair(struct dsa_keypair *s,
+ size_t key_size_bits __unused)
+{
+ memset(s, 0, sizeof(*s));
+ s->g = (struct bignum *)BN_new();
+ if (!s->g)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ s->p = (struct bignum *)BN_new();
+ if (!s->p)
+ goto err;
+ s->q = (struct bignum *)BN_new();
+ if (!s->q)
+ goto err;
+ s->y = (struct bignum *)BN_new();
+ if (!s->y)
+ goto err;
+ s->x = (struct bignum *)BN_new();
+ if (!s->x)
+ goto err;
+ return TEE_SUCCESS;
+err:
+ free(s->g);
+ free(s->p);
+ free(s->q);
+ free(s->y);
+ return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result alloc_dsa_public_key(struct dsa_public_key *s,
+ size_t key_size_bits __unused)
+{
+ memset(s, 0, sizeof(*s));
+ s->g = (struct bignum *)BN_new();
+ if (!s->g)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ s->p = (struct bignum *)BN_new();
+ if (!s->p)
+ goto err;
+ s->q = (struct bignum *)BN_new();
+ if (!s->q)
+ goto err;
+ s->y = (struct bignum *)BN_new();
+ if (!s->y)
+ goto err;
+ return TEE_SUCCESS;
+err:
+ free(s->g);
+ free(s->p);
+ free(s->q);
+ return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result alloc_dh_keypair(struct dh_keypair *s,
+ size_t key_size_bits __unused)
+{
+ memset(s, 0, sizeof(*s));
+ s->g = (struct bignum *)BN_new();
+ if (!s->g)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ s->p = (struct bignum *)BN_new();
+ if (!s->p)
+ goto err;
+ s->x = (struct bignum *)BN_new();
+ if (!s->x)
+ goto err;
+ s->y = (struct bignum *)BN_new();
+ if (!s->y)
+ goto err;
+ s->q = (struct bignum *)BN_new();
+ if (!s->q)
+ goto err;
+ return TEE_SUCCESS;
+err:
+ free(s->g);
+ free(s->p);
+ free(s->x);
+ free(s->y);
+ return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result gen_rsa_key(struct rsa_keypair *key, size_t key_size)
+{
+ TEE_Result res = TEE_ERROR_OUT_OF_MEMORY;
+ RSA *tmp_key;
+ struct bignum_st *e, *c;
+ int st;
+
+ tmp_key = RSA_new();
+ if (!tmp_key)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ e = BN_new();
+ if (!e)
+ goto err;
+ st = BN_set_word(e, 65537);
+ if (st != 1)
+ goto err;
+ st = RSA_generate_key_ex(tmp_key, key_size, e, NULL);
+ if (st != 1) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto err;
+ }
+ if ((size_t)BN_num_bits(tmp_key->n) != key_size) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto err;
+ }
+ c = BN_copy((struct bignum_st *)key->e, tmp_key->e);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->d, tmp_key->d);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->n, tmp_key->n);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->p, tmp_key->p);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->q, tmp_key->q);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->qp, tmp_key->iqmp);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->dp, tmp_key->dmp1);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->dq, tmp_key->dmq1);
+ if (!c)
+ goto err;
+ RSA_free(tmp_key);
+
+ return TEE_SUCCESS;
+err:
+ RSA_free(tmp_key);
+ BN_free(e);
+ return res;
+}
+
+static TEE_Result gen_dsa_key(struct dsa_keypair *key,
+ size_t key_size)
+{
+ TEE_Result res = TEE_ERROR_OUT_OF_MEMORY;
+ DSA *tmp_key;
+ struct bignum_st *c;
+ int st;
+
+ tmp_key = DSA_new();
+ if (!tmp_key)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ st = DSA_generate_parameters_ex(tmp_key, key_size, NULL, 0, NULL,
+ NULL, NULL);
+ if (st != 1) {
+ res = TEE_ERROR_BAD_STATE;
+ goto err;
+ }
+ st = DSA_generate_key(tmp_key);
+ if (st != 1) {
+ res = TEE_ERROR_BAD_STATE;
+ goto err;
+ }
+ c = BN_copy((struct bignum_st *)key->g, tmp_key->g);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->p, tmp_key->p);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->q, tmp_key->q);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->y, tmp_key->pub_key);
+ if (!c)
+ goto err;
+ c = BN_copy((struct bignum_st *)key->x, tmp_key->priv_key);
+ if (!c)
+ goto err;
+ DSA_free(tmp_key);
+
+ return TEE_SUCCESS;
+err:
+ DSA_free(tmp_key);
+ return res;
+}
+
+static DH *make_dh_keypair(struct dh_keypair *key, int copy_priv)
+{
+ DH *dh = NULL;
+ struct bignum_st *n;
+
+ dh = DH_new();
+ if (!dh)
+ return NULL;
+ dh->p = BN_new();
+ dh->g = BN_new();
+ if (!dh->p || !dh->g)
+ goto err;
+ n = BN_copy(dh->p, (struct bignum_st *)key->p);
+ if (!n)
+ goto err;
+ n = BN_copy(dh->g, (struct bignum_st *)key->g);
+ if (!n)
+ goto err;
+ if (copy_priv && key->x) {
+ dh->priv_key = BN_new();
+ if (!dh->priv_key)
+ goto err;
+ n = BN_copy(dh->priv_key, (struct bignum_st *)key->x);
+ }
+ return dh;
+err:
+ DH_free(dh);
+ return NULL;
+}
+
+static TEE_Result gen_dh_key(struct dh_keypair *key, struct bignum *q,
+ size_t xbits)
+{
+ TEE_Result res = TEE_ERROR_OUT_OF_MEMORY;
+ DH *dh;
+ struct bignum_st *n;
+ int st;
+
+ dh = make_dh_keypair(key, 0);
+ if (!dh)
+ goto out;
+ if (q) {
+ dh->q = BN_new();
+ if (!dh->q)
+ goto out;
+ n = BN_copy(dh->q, (struct bignum_st *)q);
+ if (!n)
+ goto out;
+ }
+ if (xbits)
+ dh->length = xbits;
+ st = DH_generate_key(dh);
+ if (st != 1) {
+ res = TEE_ERROR_BAD_STATE;
+ goto out;
+ }
+ n = BN_copy((struct bignum_st *)key->y, dh->pub_key);
+ if (!n)
+ goto out;
+ n = BN_copy((struct bignum_st *)key->x, dh->priv_key);
+ if (!n)
+ goto out;
+ res = TEE_SUCCESS;
+out:
+ DH_free(dh);
+ return res;
+}
+
+static TEE_Result do_dh_shared_secret(struct dh_keypair *private_key,
+ struct bignum *public_key,
+ struct bignum *secret)
+{
+ TEE_Result res = TEE_ERROR_OUT_OF_MEMORY;
+ DH *dh;
+ struct bignum_st *n;
+ int sz;
+ unsigned char *buf = NULL;
+
+ dh = make_dh_keypair(private_key, 1);
+ if (!dh)
+ goto out;
+ sz = DH_size(dh);
+ buf = malloc(sz);
+ if (!buf)
+ goto out;
+ sz = DH_compute_key(buf, (struct bignum_st *)public_key, dh);
+ if (sz < 0) {
+ res = TEE_ERROR_BAD_STATE;
+ goto out;
+ }
+ n = BN_bin2bn(buf, sz, (struct bignum_st *)secret);
+ if (!n)
+ goto out;
+ res = TEE_SUCCESS;
+out:
+ DH_free(dh);
+ free(buf);
+ return res;
+}
+
+static RSA *make_rsa_keypair(struct rsa_keypair *key)
+{
+ RSA *rsa;
+
+ rsa = RSA_new();
+ if (!rsa)
+ return NULL;
+ RSA_blinding_off(rsa); /* FIXME */
+ rsa->e = BN_new();
+ rsa->d = BN_new();
+ rsa->n = BN_new();
+ if (!rsa->e || !rsa->d || !rsa->n)
+ goto err;
+ if (!BN_copy(rsa->e, (struct bignum_st *)key->e))
+ goto err;
+ if (!BN_copy(rsa->d, (struct bignum_st *)key->d))
+ goto err;
+ if (!BN_copy(rsa->n, (struct bignum_st *)key->n))
+ goto err;
+ if (key->p && num_bytes(key->p)) {
+ rsa->p = BN_new();
+ rsa->q = BN_new();
+ rsa->iqmp = BN_new();
+ rsa->dmp1 = BN_new();
+ rsa->dmq1 = BN_new();
+ if (!rsa->p || !rsa->q || !rsa->iqmp || !rsa->dmp1 ||
+ !rsa->dmq1)
+ goto err;
+ if (!BN_copy(rsa->p, (struct bignum_st *)key->p))
+ goto err;
+ if (!BN_copy(rsa->q, (struct bignum_st *)key->q))
+ goto err;
+ if (!BN_copy(rsa->iqmp, (struct bignum_st *)key->qp))
+ goto err;
+ if (!BN_copy(rsa->dmp1, (struct bignum_st *)key->dp))
+ goto err;
+ if (!BN_copy(rsa->dmq1, (struct bignum_st *)key->dq))
+ goto err;
+ }
+ return rsa;
+err:
+ RSA_free(rsa);
+ return NULL;
+
+}
+
+static RSA *make_rsa_public_key(struct rsa_public_key *key)
+{
+ RSA *rsa;
+
+ rsa = RSA_new();
+ if (!rsa)
+ return NULL;
+ RSA_blinding_off(rsa); /* FIXME */
+ rsa->e = BN_new();
+ rsa->n = BN_new();
+ if (!rsa->e || !rsa->n)
+ goto err;
+ if (!BN_copy(rsa->e, (struct bignum_st *)key->e))
+ goto err;
+ if (!BN_copy(rsa->n, (struct bignum_st *)key->n))
+ goto err;
+ return rsa;
+err:
+ RSA_free(rsa);
+ return NULL;
+
+}
+
+static TEE_Result rsa_public_encrypt(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding,
+ int *tolen)
+{
+ /*
+ * Wrapper around RSA_public_encrypt, which requires that
+ * flen == RSA_size(rsa). Here we just require flen <= RSA_size(rsa).
+ * Input buffer is padded with zeros if needed.
+ */
+ TEE_Result ret;
+ const unsigned char *in = from;
+ unsigned char *out = to;
+ unsigned char *inbuf = NULL, *outbuf = NULL;
+ int outsz, insz = flen, reqsz = RSA_size(rsa);
+ bool alloced = 0;
+
+ if (insz < reqsz) {
+ inbuf = calloc(1, reqsz);
+ outbuf = calloc(1, reqsz);
+ alloced = 1;
+ if (!inbuf || !outbuf) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ memcpy(inbuf + reqsz - flen, from, flen);
+ in = inbuf;
+ insz = reqsz;
+ out = outbuf;
+ }
+ outsz = RSA_public_encrypt(insz, in, out, rsa, padding);
+ if (outsz < 0) {
+ ret = TEE_ERROR_BAD_STATE;
+ goto out;
+ }
+ if (*tolen < outsz) {
+ *tolen = outsz;
+ ret = TEE_ERROR_SHORT_BUFFER;
+ goto out;
+ }
+ *tolen = outsz;
+ if (alloced)
+ memcpy(to, out, outsz);
+ ret = TEE_SUCCESS;
+out:
+ if (alloced) {
+ free(inbuf);
+ free(outbuf);
+ }
+ return ret;
+}
+static TEE_Result rsanopad_encrypt(struct rsa_public_key *key,
+ const uint8_t *src, size_t src_len,
+ uint8_t *dst, size_t *dst_len)
+{
+ RSA *rsa;
+ const unsigned char *in = src;
+ unsigned char *out = dst;
+ int maxinsz, outsz = *dst_len, insz, leftinsz;
+ int leftoutsz, done = 0;
+ TEE_Result ret;
+
+ rsa = make_rsa_public_key(key);
+ if (!rsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ maxinsz = RSA_size(rsa);
+ leftinsz = src_len;
+ leftoutsz = *dst_len;
+ do {
+ insz = MIN(leftinsz, maxinsz);
+ outsz = leftoutsz;
+ ret = rsa_public_encrypt(insz, in, out, rsa, RSA_NO_PADDING,
+ &outsz);
+ if (ret != TEE_SUCCESS)
+ goto out;
+ if (outsz > leftoutsz) {
+ ret = TEE_ERROR_SHORT_BUFFER;
+ goto out;
+ }
+ in += insz;
+ out += outsz;
+ leftinsz -= insz;
+ leftoutsz -= outsz;
+ done += outsz;
+ } while (leftinsz > 0);
+ *dst_len = done;
+ ret = TEE_SUCCESS;
+out:
+ RSA_free(rsa);
+ return ret;
+}
+static TEE_Result rsanopad_decrypt(struct rsa_keypair *key,
+ const uint8_t *src, size_t src_len,
+ uint8_t *dst, size_t *dst_len)
+{
+ RSA *rsa;
+ TEE_Result ret;
+ unsigned char *buf = NULL;
+ int maxsz, outsz, offset;
+
+ rsa = make_rsa_keypair(key);
+ if (!rsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /*
+ * Decrypt to temporary buffer since output size is unknown (but less
+ * than maxsz)
+ */
+ maxsz = RSA_size(rsa);
+ buf = calloc(1, maxsz);
+ if (!buf) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ outsz = RSA_private_decrypt(src_len, src, buf, rsa, RSA_NO_PADDING);
+
+ /* Remove the zero-padding (leave one zero if buff is all zeroes) */
+ offset = 0;
+ while ((offset < outsz - 1) && (buf[offset] == 0))
+ offset++;
+
+ if (*dst_len < (size_t)(outsz - offset)) {
+ *dst_len = outsz - offset;
+ ret = TEE_ERROR_SHORT_BUFFER;
+ goto out;
+ }
+
+ *dst_len = outsz - offset;
+ memcpy(dst, (char *)buf + offset, *dst_len);
+ ret = TEE_SUCCESS;
+out:
+ RSA_free(rsa);
+ free(buf);
+ return ret;
+}
+
+static TEE_Result rsaes_encrypt(uint32_t algo, struct rsa_public_key *key,
+ const uint8_t *label, size_t label_len,
+ const uint8_t *src, size_t src_len,
+ uint8_t *dst, size_t *dst_len)
+{
+ TEE_Result ret = TEE_SUCCESS;
+ unsigned char *buf = NULL;
+ int st;
+ size_t bufsz;
+
+ bufsz = num_bytes(key->n);
+ buf = calloc(1, bufsz);
+ if (!buf) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
+ st = RSA_padding_add_PKCS1_type_2(buf, bufsz, src, src_len);
+ } else {
+ st = RSA_padding_add_PKCS1_OAEP(buf, bufsz, src, src_len,
+ label, label_len);
+ }
+ if (st < 0) {
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+ ret = rsanopad_encrypt(key, buf, bufsz, dst, dst_len);
+out:
+ free(buf);
+ return ret;
+}
+
+static TEE_Result rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
+ const uint8_t *label, size_t label_len,
+ const uint8_t *src, size_t src_len,
+ uint8_t *dst, size_t *dst_len)
+{
+ TEE_Result ret = TEE_SUCCESS;
+ unsigned char *buf = NULL;
+ int st;
+ size_t rsa_len, bufsz;
+
+ rsa_len = num_bytes(key->n);
+ bufsz = rsa_len;
+ buf = malloc(bufsz);
+ if (!buf) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ ret = rsanopad_decrypt(key, src, src_len, buf, &bufsz);
+ if (ret != TEE_SUCCESS)
+ goto out;
+ if (algo == TEE_ALG_RSAES_PKCS1_V1_5) {
+ st = RSA_padding_check_PKCS1_type_2(dst, *dst_len, buf, bufsz,
+ rsa_len);
+ } else {
+ st = RSA_padding_check_PKCS1_OAEP(dst, *dst_len, buf, bufsz,
+ rsa_len, label, label_len);
+ }
+ if (st < 0) {
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+ if (*dst_len < (size_t)st) {
+ *dst_len = st;
+ ret = TEE_ERROR_SHORT_BUFFER;
+ goto out;
+ }
+ *dst_len = st;
+out:
+ free(buf);
+ return ret;
+}
+
+static int digest_type(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
+ return NID_md5;
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
+ case TEE_ALG_DSA_SHA1:
+ return NID_sha1;
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
+ return NID_sha224;
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
+ return NID_sha256;
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
+ return NID_sha384;
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
+ return NID_sha512;
+ default:
+ return -1;
+ }
+
+}
+
+static TEE_Result rsassa_pkcs1_v1_5_sign(uint32_t algo,
+ struct rsa_keypair *key,
+ const uint8_t *msg, size_t msg_len,
+ uint8_t *sig, size_t *sig_len)
+{
+ int st, type;
+ TEE_Result ret = TEE_ERROR_BAD_STATE;
+ RSA *rsa = NULL;
+
+ type = digest_type(algo);
+ if (type < 0)
+ return TEE_ERROR_NOT_IMPLEMENTED;
+ rsa = make_rsa_keypair(key);
+ if (!rsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ st = RSA_sign(type, msg, msg_len, sig, sig_len, rsa);
+ if (st != 1)
+ goto out;
+ ret = TEE_SUCCESS;
+out:
+ RSA_free(rsa);
+ return ret;
+}
+
+static TEE_Result rsassa_pkcs1_v1_5_verify(uint32_t algo,
+ struct rsa_public_key *key,
+ const uint8_t *msg,
+ size_t msg_len, const uint8_t *sig,
+ size_t sig_len)
+{
+ int st, type;
+ TEE_Result ret = TEE_ERROR_BAD_STATE;
+ RSA *rsa = NULL;
+
+ type = digest_type(algo);
+ if (type < 0)
+ return TEE_ERROR_NOT_IMPLEMENTED;
+
+ rsa = make_rsa_public_key(key);
+ if (!rsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ st = RSA_verify(type, msg, msg_len, sig, sig_len, rsa);
+ if (st != 1) {
+ ret = TEE_ERROR_SIGNATURE_INVALID;
+ goto out;
+ }
+ ret = TEE_SUCCESS;
+out:
+ RSA_free(rsa);
+ return ret;
+}
+
+static const EVP_MD *evp_md(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
+ return EVP_sha1();
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
+ return EVP_sha224();
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
+ return EVP_sha256();
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
+ return EVP_sha384();
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
+ return EVP_sha512();
+ default:
+ return NULL;
+ }
+}
+
+static TEE_Result rsassa_pkcs1_pss_mgf1_sign(uint32_t algo, uint32_t salt_len,
+ struct rsa_keypair *key,
+ const uint8_t *msg,
+ size_t msg_len,
+ uint8_t *sig, size_t *sig_len)
+{
+ int st, padded_sz;
+ TEE_Result ret = TEE_ERROR_BAD_STATE;
+ RSA *rsa = NULL;
+ const EVP_MD *md;
+ unsigned char *padded = NULL;
+
+ md = evp_md(algo);
+ if (!md)
+ goto out;
+ if (msg_len != (size_t)EVP_MD_size(md)) {
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+ rsa = make_rsa_keypair(key);
+ if (!rsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ if (*sig_len < (size_t)RSA_size(rsa)) {
+ ret = TEE_ERROR_SHORT_BUFFER;
+ goto out;
+ }
+ padded_sz = RSA_size(rsa);
+ padded = malloc(padded_sz);
+ if (!padded)
+ goto out;
+ st = RSA_padding_add_PKCS1_PSS_mgf1(rsa, padded, msg, md, NULL,
+ salt_len);
+ if (st != 1)
+ goto out;
+ st = RSA_private_encrypt(padded_sz, padded, sig, rsa, RSA_NO_PADDING);
+ if (st < 0)
+ goto out;
+ *sig_len = st;
+ ret = TEE_SUCCESS;
+out:
+ RSA_free(rsa);
+ free(padded);
+ return ret;
+}
+
+static TEE_Result rsassa_pkcs1_pss_mgf1_verify(uint32_t algo,
+ uint32_t salt_len,
+ struct rsa_public_key *key,
+ const uint8_t *msg,
+ size_t msg_len __unused,
+ const uint8_t *sig,
+ size_t sig_len)
+{
+ int st;
+ TEE_Result ret = TEE_ERROR_BAD_STATE;
+ RSA *rsa = NULL;
+ const EVP_MD *md;
+ unsigned char *buf = NULL;
+
+ md = evp_md(algo);
+ if (!md)
+ goto out;
+ if (msg_len != (size_t)EVP_MD_size(md)) {
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+ rsa = make_rsa_public_key(key);
+ if (!rsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ if (sig_len != (size_t)RSA_size(rsa)) {
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+ buf = malloc(RSA_size(rsa));
+ if (!buf)
+ goto out;
+ st = RSA_public_decrypt(sig_len, sig, buf, rsa, RSA_NO_PADDING);
+ if (st <= 0) {
+ ret = TEE_ERROR_SIGNATURE_INVALID;
+ goto out;
+ }
+ if ((size_t)st != sig_len) {
+ ret = TEE_ERROR_SIGNATURE_INVALID;
+ goto out;
+ }
+ st = RSA_verify_PKCS1_PSS_mgf1(rsa, msg, md, NULL, buf, salt_len);
+ if (st != 1) {
+ ret = TEE_ERROR_SIGNATURE_INVALID;
+ goto out;
+ }
+ ret = TEE_SUCCESS;
+out:
+ RSA_free(rsa);
+ free(buf);
+ return ret;
+}
+
+static TEE_Result rsassa_sign(uint32_t algo, struct rsa_keypair *key,
+ int salt_len, const uint8_t *msg,
+ size_t msg_len, uint8_t *sig,
+ size_t *sig_len)
+{
+ TEE_Result res;
+ size_t hash_size, mod_size;
+
+ (void)salt_len;
+ res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
+ &hash_size);
+ if (res != TEE_SUCCESS)
+ return res;
+ if (msg_len != hash_size)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ mod_size = num_bytes(key->n);
+ if (*sig_len < mod_size) {
+ *sig_len = mod_size;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+ *sig_len = mod_size;
+
+ switch (algo) {
+ case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
+ return rsassa_pkcs1_v1_5_sign(algo, key, msg, msg_len, sig,
+ sig_len);
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
+ return rsassa_pkcs1_pss_mgf1_sign(algo, salt_len, key, msg,
+ msg_len, sig, sig_len);
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static TEE_Result rsassa_verify(uint32_t algo, struct rsa_public_key *key,
+ int salt_len, const uint8_t *msg,
+ size_t msg_len, const uint8_t *sig,
+ size_t sig_len)
+{
+ switch (algo) {
+ case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
+ return rsassa_pkcs1_v1_5_verify(algo, key, msg, msg_len, sig,
+ sig_len);
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
+ return rsassa_pkcs1_pss_mgf1_verify(algo, salt_len, key, msg,
+ msg_len, sig, sig_len);
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static DSA *make_dsa_public_key(struct dsa_public_key *key)
+{
+ DSA *dsa;
+
+ dsa = DSA_new();
+ if (!dsa)
+ return NULL;
+ dsa->g = BN_new();
+ dsa->p = BN_new();
+ dsa->q = BN_new();
+ dsa->pub_key = BN_new();
+ if (!dsa->g || !dsa->p || !dsa->q || !dsa->pub_key)
+ goto err;
+ if (!BN_copy(dsa->g, (struct bignum_st *)key->g))
+ goto err;
+ if (!BN_copy(dsa->p, (struct bignum_st *)key->p))
+ goto err;
+ if (!BN_copy(dsa->q, (struct bignum_st *)key->q))
+ goto err;
+ if (!BN_copy(dsa->pub_key, (struct bignum_st *)key->y))
+ goto err;
+ return dsa;
+err:
+ DSA_free(dsa);
+ return NULL;
+
+}
+
+static DSA *make_dsa_keypair(struct dsa_keypair *key)
+{
+ DSA *dsa;
+
+ dsa = DSA_new();
+ if (!dsa)
+ return NULL;
+ dsa->g = BN_new();
+ dsa->p = BN_new();
+ dsa->q = BN_new();
+ dsa->pub_key = BN_new();
+ dsa->priv_key = BN_new();
+ if (!dsa->g || !dsa->p || !dsa->q || !dsa->pub_key || !dsa->priv_key)
+ goto err;
+ if (!BN_copy(dsa->g, (struct bignum_st *)key->g))
+ goto err;
+ if (!BN_copy(dsa->p, (struct bignum_st *)key->p))
+ goto err;
+ if (!BN_copy(dsa->q, (struct bignum_st *)key->q))
+ goto err;
+ if (!BN_copy(dsa->pub_key, (struct bignum_st *)key->y))
+ goto err;
+ if (!BN_copy(dsa->priv_key, (struct bignum_st *)key->x))
+ goto err;
+ return dsa;
+err:
+ DSA_free(dsa);
+ return NULL;
+
+}
+
+static TEE_Result dsa_sign(uint32_t algo, struct dsa_keypair *key,
+ const uint8_t *msg, size_t msg_len, uint8_t *sig,
+ size_t *sig_len)
+{
+ TEE_Result ret;
+ DSA *dsa = NULL;
+ DSA_SIG *dsig = NULL;
+ size_t hashsz, outsz;
+
+ ret = tee_hash_get_digest_size(algo, &hashsz);
+ if (ret != TEE_SUCCESS)
+ goto out;
+ if (msg_len != hashsz) {
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+ dsa = make_dsa_keypair(key);
+ if (!dsa) {
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ outsz = 2 * BN_num_bytes(dsa->q);
+ if (*sig_len < outsz) {
+ *sig_len = outsz;
+ ret = TEE_ERROR_SHORT_BUFFER;
+ goto out;
+ }
+ *sig_len = outsz;
+ dsig = DSA_do_sign(msg, msg_len, dsa);
+ if (!dsig) {
+ ret = TEE_ERROR_BAD_STATE;
+ goto out;
+ }
+ BN_bn2bin(dsig->r, sig);
+ BN_bn2bin(dsig->s, sig + outsz/2);
+ ret = TEE_SUCCESS;
+out:
+ DSA_SIG_free(dsig);
+ DSA_free(dsa);
+ return ret;
+}
+
+static TEE_Result dsa_verify(uint32_t algo __unused,
+ struct dsa_public_key *key,
+ const uint8_t *msg, size_t msg_len,
+ const uint8_t *sig, size_t sig_len)
+{
+ int st;
+ TEE_Result ret = TEE_ERROR_OUT_OF_MEMORY;
+ DSA *dsa = NULL;
+ DSA_SIG *dsig = NULL;
+
+ dsa = make_dsa_public_key(key);
+ if (!dsa)
+ goto out;
+ dsig = DSA_SIG_new();
+ if (!dsig)
+ goto out;
+ dsig->r = BN_bin2bn(sig, sig_len/2, NULL);
+ if (!dsig->r)
+ goto out;
+ dsig->s = BN_bin2bn(sig + sig_len/2, sig_len/2, NULL);
+ if (!dsig->s)
+ goto out;
+ st = DSA_do_verify(msg, msg_len, dsig, dsa);
+ if (st != 1) {
+ ret = TEE_ERROR_SIGNATURE_INVALID;
+ goto out;
+ }
+ ret = TEE_SUCCESS;
+out:
+ DSA_SIG_free(dsig);
+ DSA_free(dsa);
+ return ret;
+}
+
+/******************************************************************************
+ * Authenticated encryption
+ ******************************************************************************/
+
+/*
+ * In CCM mode, EVP_EncryptUpdate() or EVP_DecryptUpdate() may be called only
+ * once for AAD data, and once for the payload (plain text or cipher text).
+ * Hence, we have to re-assemble data in our own buffers.
+ * GCM does not suffer from this limitation.
+ */
+struct aes_ccm_ctx {
+ EVP_CIPHER_CTX ctx;
+ unsigned char *aad;
+ size_t aad_len;
+ size_t aad_count;
+ unsigned char *dst_buf;
+ unsigned char *payload;
+ size_t payload_len;
+ size_t payload_count;
+ unsigned char *nonce;
+ unsigned char *key;
+ size_t key_len;
+};
+
+static TEE_Result authenc_get_ctx_size(uint32_t algo, size_t *size)
+{
+ switch (algo) {
+ case TEE_ALG_AES_CCM:
+ *size = sizeof(struct aes_ccm_ctx);
+ break;
+ case TEE_ALG_AES_GCM:
+ *size = sizeof(EVP_CIPHER_CTX);
+ break;
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result aes_ccm_init(void *ctx, TEE_OperationMode mode,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t tag_len, size_t aad_len,
+ size_t payload_len)
+{
+ const EVP_CIPHER *cipher;
+ struct aes_ccm_ctx *cctx = ctx;
+ int st, len;
+
+ switch (key_len) {
+ case 16:
+ cipher = EVP_aes_128_ccm();
+ break;
+ case 24:
+ cipher = EVP_aes_192_ccm();
+ break;
+ case 32:
+ cipher = EVP_aes_256_ccm();
+ break;
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ /* Allocate buffer for AAD data and payload. */
+ memset(cctx, 0, sizeof(*cctx));
+ cctx->aad = malloc(aad_len);
+ if (!cctx->aad)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ cctx->aad_len = aad_len;
+ cctx->aad_count = 0;
+
+ cctx->payload = malloc(payload_len);
+ if (!cctx->payload)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ cctx->payload_len = payload_len;
+ cctx->payload_count = 0;
+
+ if (mode == TEE_MODE_ENCRYPT) {
+ /* Set cipher */
+ st = EVP_EncryptInit(ctx, cipher, NULL, NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set IV length */
+ st = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN,
+ nonce_len, NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set tag length */
+ st = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len,
+ NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set key and nonce */
+ st = EVP_EncryptInit(ctx, NULL, key, nonce);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Provide plaintext length */
+ st = EVP_EncryptUpdate(ctx, NULL, &len, NULL, payload_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ } else {
+ /* Save key and nonce for later use */
+ cctx->nonce = malloc(nonce_len);
+ if (!cctx->nonce)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ memcpy(cctx->nonce, nonce, nonce_len);
+ cctx->key = malloc(key_len);
+ if (!cctx->key)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ memcpy(cctx->key, key, key_len);
+ /* Set cipher */
+ st = EVP_DecryptInit(ctx, cipher, NULL, NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set IV length */
+ st = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN,
+ nonce_len, NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result aes_gcm_init(void *ctx, TEE_OperationMode mode,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *nonce, size_t nonce_len)
+{
+ const EVP_CIPHER *cipher;
+ struct aes_ccm_ctx *cctx = ctx;
+ int st;
+
+ switch (key_len) {
+ case 16:
+ cipher = EVP_aes_128_gcm();
+ break;
+ case 24:
+ cipher = EVP_aes_192_gcm();
+ break;
+ case 32:
+ cipher = EVP_aes_256_gcm();
+ break;
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ /* Set cipher */
+ if (mode == TEE_MODE_ENCRYPT)
+ st = EVP_EncryptInit(&cctx->ctx, cipher, NULL, NULL);
+ else
+ st = EVP_DecryptInit(&cctx->ctx, cipher, NULL, NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set IV length */
+ st = EVP_CIPHER_CTX_ctrl(&cctx->ctx, EVP_CTRL_GCM_SET_IVLEN, nonce_len,
+ NULL);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set key and nonce */
+ if (mode == TEE_MODE_ENCRYPT)
+ st = EVP_EncryptInit(&cctx->ctx, NULL, key, nonce);
+ else
+ st = EVP_DecryptInit(&cctx->ctx, NULL, key, nonce);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result authenc_init(void *ctx, uint32_t algo,
+ TEE_OperationMode mode,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t tag_len, size_t aad_len,
+ size_t payload_len)
+{
+ switch (algo) {
+ case TEE_ALG_AES_CCM:
+ return aes_ccm_init(ctx, mode, key, key_len, nonce, nonce_len,
+ tag_len, aad_len, payload_len);
+ case TEE_ALG_AES_GCM:
+ return aes_gcm_init(ctx, mode, key, key_len, nonce, nonce_len);
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result authenc_update_aad(void *ctx, uint32_t algo,
+ TEE_OperationMode mode,
+ const uint8_t *data, size_t len)
+{
+ int st, outlen;
+ struct aes_ccm_ctx *cctx;
+
+ switch (algo) {
+ case TEE_ALG_AES_CCM:
+ cctx = ctx;
+ if (cctx->aad_count + len > cctx->aad_len)
+ return TEE_ERROR_BAD_PARAMETERS;
+ memcpy(cctx->aad + cctx->aad_count, data, len);
+ cctx->aad_count += len;
+ break;
+ case TEE_ALG_AES_GCM:
+ if (mode == TEE_MODE_ENCRYPT)
+ st = EVP_EncryptUpdate(ctx, NULL, &outlen, data, len);
+ else
+ st = EVP_DecryptUpdate(ctx, NULL, &outlen, data, len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ break;
+ default:
+ return TEE_ERROR_BAD_STATE;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result authenc_update_payload(void *ctx, uint32_t algo,
+ TEE_OperationMode mode,
+ const uint8_t *src_data,
+ size_t src_len, uint8_t *dst_data,
+ size_t *dst_len)
+{
+ int st, outlen;
+ struct aes_ccm_ctx *cctx;
+
+ switch (algo) {
+ case TEE_ALG_AES_CCM:
+ cctx = ctx;
+ if (cctx->payload_count + src_len > cctx->payload_len)
+ return TEE_ERROR_BAD_PARAMETERS;
+ memcpy(cctx->payload + cctx->payload_count, src_data, src_len);
+ cctx->payload_count += src_len;
+ /* Save start of destination buffer on first call */
+ if (!cctx->dst_buf)
+ cctx->dst_buf = dst_data;
+ *dst_len = 0;
+ break;
+ case TEE_ALG_AES_GCM:
+ outlen = *dst_len;
+ if (mode == TEE_MODE_ENCRYPT)
+ st = EVP_EncryptUpdate(ctx, dst_data, &outlen,
+ src_data, src_len);
+ else
+ st = EVP_DecryptUpdate(ctx, dst_data, &outlen,
+ src_data, src_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ *dst_len = outlen;
+ break;
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result authenc_enc_final(void *ctx, uint32_t algo,
+ const uint8_t *src_data,
+ size_t src_len, uint8_t *dst_data,
+ size_t *dst_len, uint8_t *dst_tag,
+ size_t *dst_tag_len)
+{
+ TEE_Result res;
+ int st, outlen;
+ size_t dlen;
+ struct aes_ccm_ctx *cctx;
+
+ switch (algo) {
+ case TEE_ALG_AES_CCM:
+ cctx = ctx;
+ dlen = *dst_len;
+ res = authenc_update_payload(ctx, algo, TEE_MODE_ENCRYPT,
+ src_data, src_len, dst_data,
+ &dlen);
+ if (res != TEE_SUCCESS)
+ return res;
+ /* AAD data and payload data complete? */
+ if (cctx->aad_count != cctx->aad_len)
+ return TEE_ERROR_BAD_STATE;
+ if (cctx->payload_count != cctx->payload_len)
+ return TEE_ERROR_BAD_STATE;
+ /* Provide AAD data */
+ st = EVP_EncryptUpdate(&cctx->ctx, NULL, &outlen, cctx->aad,
+ cctx->aad_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Provide plaintext data */
+ st = EVP_EncryptUpdate(&cctx->ctx, cctx->dst_buf, &outlen,
+ cctx->payload, cctx->payload_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ *dst_len = outlen;
+ /* Finalize encryption */
+ st = EVP_EncryptFinal(&cctx->ctx, cctx->dst_buf + outlen,
+ &outlen);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* EVP_EncryptFinal generates no additional data */
+ TEE_ASSERT(outlen == 0);
+ /* Get the tag */
+ st = EVP_CIPHER_CTX_ctrl(&cctx->ctx, EVP_CTRL_CCM_GET_TAG,
+ *dst_tag_len, dst_tag);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ break;
+ case TEE_ALG_AES_GCM:
+ /* Encrypt data */
+ st = EVP_EncryptUpdate(ctx, dst_data, &outlen, src_data,
+ src_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ *dst_len = outlen;
+ /* Finalize encryption */
+ st = EVP_EncryptFinal(ctx, dst_data + outlen, &outlen);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* EVP_EncryptFinal generates no additional data */
+ TEE_ASSERT(outlen == 0);
+ /* Get the tag */
+ st = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
+ *dst_tag_len, dst_tag);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ break;
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result authenc_dec_final(void *ctx, uint32_t algo,
+ const uint8_t *src_data, size_t src_len,
+ uint8_t *dst_data, size_t *dst_len,
+ const uint8_t *tag, size_t tag_len)
+{
+ TEE_Result res;
+ int st, outlen;
+ size_t dlen;
+ struct aes_ccm_ctx *cctx;
+
+ switch (algo) {
+ case TEE_ALG_AES_CCM:
+ cctx = ctx;
+ dlen = *dst_len;
+ res = authenc_update_payload(ctx, algo, TEE_MODE_DECRYPT,
+ src_data, src_len, dst_data,
+ &dlen);
+ if (res != TEE_SUCCESS)
+ return res;
+ /* AAD data and payload data complete? */
+ if (cctx->aad_count != cctx->aad_len)
+ return TEE_ERROR_BAD_STATE;
+ if (cctx->payload_count != cctx->payload_len)
+ return TEE_ERROR_BAD_STATE;
+ /* Provide expected tag */
+ st = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len,
+ (void *)tag);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Set key and IV */
+ st = EVP_DecryptInit(ctx, NULL, cctx->key, cctx->nonce);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Provide total length of encrypted data */
+ st = EVP_DecryptUpdate(&cctx->ctx, NULL, &outlen, NULL,
+ cctx->payload_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Provide AAD data */
+ st = EVP_DecryptUpdate(&cctx->ctx, NULL, &outlen, cctx->aad,
+ cctx->aad_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Process ciphertext*/
+ st = EVP_DecryptUpdate(&cctx->ctx, cctx->dst_buf, &outlen,
+ cctx->payload, cctx->payload_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ *dst_len = outlen;
+ break;
+ case TEE_ALG_AES_GCM:
+ /* Decrypt data */
+ st = EVP_DecryptUpdate(ctx, dst_data, &outlen, src_data,
+ src_len);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ *dst_len = outlen;
+ /* Provide the tag */
+ st = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len,
+ (void *)tag);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* Finalize encryption */
+ st = EVP_DecryptFinal(ctx, dst_data + *dst_len, &outlen);
+ if (st != 1)
+ return TEE_ERROR_BAD_STATE;
+ /* EVP_EncryptFinal() generates no additional data */
+ TEE_ASSERT(outlen == 0);
+ break;
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ return TEE_SUCCESS;
+}
+
+static void authenc_final(void *ctx, uint32_t algo)
+{
+ struct aes_ccm_ctx *cctx;
+
+ if (algo == TEE_ALG_AES_CCM) {
+ cctx = ctx;
+ free(cctx->aad);
+ free(cctx->payload);
+ free(cctx->nonce);
+ EVP_CIPHER_CTX_cleanup(&cctx->ctx);
+ } else {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ }
+}
+
+struct crypto_ops crypto_ops = {
+ .name = "OpenSSL provider",
+ .init = tee_ossl_init,
+ .bignum = {
+ .allocate = bn_allocate,
+ .num_bytes = num_bytes,
+ .bn2bin = bn2bin,
+ .bin2bn = bin2bn,
+ .copy = bn_copy,
+ .free = bn_free,
+ },
+ .hash = {
+ .get_ctx_size = hash_get_ctx_size,
+ .init = hash_init,
+ .update = hash_update,
+ .final = hash_final,
+ },
+ .cipher = {
+ .get_ctx_size = cipher_get_ctx_size,
+ .init = cipher_init,
+ .update = cipher_update,
+ .final = cipher_final
+ },
+ .mac = {
+ .get_ctx_size = mac_get_ctx_size,
+ .init = mac_init,
+ .update = mac_update,
+ .final = mac_final
+ },
+ .acipher = {
+ .alloc_dh_keypair = alloc_dh_keypair,
+ .alloc_dsa_keypair = alloc_dsa_keypair,
+ .alloc_dsa_public_key = alloc_dsa_public_key,
+ .alloc_rsa_keypair = alloc_rsa_keypair,
+ .alloc_rsa_public_key = alloc_rsa_public_key,
+ .dh_shared_secret = do_dh_shared_secret,
+ .dsa_sign = dsa_sign,
+ .dsa_verify = dsa_verify,
+ .gen_dh_key = gen_dh_key,
+ .gen_dsa_key = gen_dsa_key,
+ .gen_rsa_key = gen_rsa_key,
+ .rsaes_decrypt = rsaes_decrypt,
+ .rsaes_encrypt = rsaes_encrypt,
+ .rsanopad_decrypt = rsanopad_decrypt,
+ .rsanopad_encrypt = rsanopad_encrypt,
+ .rsassa_sign = rsassa_sign,
+ .rsassa_verify = rsassa_verify,
+ },
+ .authenc = {
+ .dec_final = authenc_dec_final,
+ .enc_final = authenc_enc_final,
+ .final = authenc_final,
+ .get_ctx_size = authenc_get_ctx_size,
+ .init = authenc_init,
+ .update_aad = authenc_update_aad,
+ .update_payload = authenc_update_payload,
+ },
+
+};