add support for ECDSA key generation, sign/verify 06/294806/9
authorDongsun Lee <ds73.lee@samsung.com>
Tue, 27 Jun 2023 01:47:58 +0000 (10:47 +0900)
committerDongsun Lee <ds73.lee@samsung.com>
Thu, 10 Aug 2023 07:54:24 +0000 (16:54 +0900)
Change-Id: Ib85c5d8079e6539c37d9dd92e67e57d53d6a0638

include/include/tee_internal_api.h
ssflib/inc/crypto_internal.h
ssflib/inc/ssf_crypto_openssl.h
ssflib/src/ssf_crypto.cpp
ssflib/src/ssf_crypto_openssl.cpp
ssflib/src/ssf_storage.cpp

index a82990a32dddfc6fa5fabbdd07560904ae8b071e..1bb8549a75fa8da3e403633c60f4844e084fc67d 100644 (file)
@@ -1649,9 +1649,10 @@ typedef enum {
        TEE_TYPE_DSA_KEYPAIR = 0xA1000031,
        TEE_TYPE_DH_KEYPAIR = 0xA1000032,
 #ifdef ECC_IMPLEMENTATION
-       TEE_TYPE_ECDSA_PUBLIC_KEY = 0xA0000033,
-       TEE_TYPE_ECDSA_KEYPAIR = 0xA1000033,
-       TEE_TYPE_ECDH_KEYPAIR = 0xA1000034,
+       TEE_TYPE_ECDSA_PUBLIC_KEY = 0xA0000041,
+       TEE_TYPE_ECDSA_KEYPAIR = 0xA1000041,
+       TEE_TYPE_ECDH_PUBLIC_KEY = 0xA0000042,
+       TEE_TYPE_ECDH_KEYPAIR = 0xA1000042,
 #endif // ECC_IMPLEMENTATION
        TEE_TYPE_GENERIC_SECRET = 0xA0000000,
        TEE_TYPE_CERT_ROOT_GSL = 0xA00000A0,     // GPD System Loader root Certificate
@@ -1661,6 +1662,16 @@ typedef enum {
 // more for application certificate?
 } TEE_OBJECT_TYPES;
 
+#ifdef ECC_IMPLEMENTATION
+typedef enum {
+       TEE_ECC_CURVE_NIST_P192 = 0x00000001,
+       TEE_ECC_CURVE_NIST_P224 = 0x00000002,
+       TEE_ECC_CURVE_NIST_P256 = 0x00000003,
+       TEE_ECC_CURVE_NIST_P384 = 0x00000004,
+       TEE_ECC_CURVE_NIST_P521 = 0x00000005
+} TEE_ECC_CURVE;
+#endif // ECC_IMPLEMENTATION
+
 /******************************************************************************
  *  6.11 Object or Operation Attributes
  ******************************************************************************/
@@ -1690,15 +1701,10 @@ typedef enum {
        TEE_ATTR_RSA_PSS_SALT_LENGTH = 0xF0000A30,
 
 #ifdef ECC_IMPLEMENTATION
-       TEE_ATTR_ECDSA_PRIME = 0xD0001041,
-       TEE_ATTR_ECDSA_COFF_A = 0xD0001141,
-       TEE_ATTR_ECDSA_COFF_B = 0xD0001241,
-       TEE_ATTR_ECDSA_GENERATOR_X = 0xD0001341,
-       TEE_ATTR_ECDSA_GENERATOR_Y = 0xD0001441,
-       TEE_ATTR_ECDSA_ORDER = 0xD0001541,
-       TEE_ATTR_ECDSA_PUBLIC_VALUE_X = 0xD0002141,
-       TEE_ATTR_ECDSA_PUBLIC_VALUE_Y = 0xD0003141,
-       TEE_ATTR_ECDSA_PRIVATE_VALUE = 0xC0000241,
+       TEE_ATTR_ECC_PUBLIC_VALUE_X = 0xD0000141,
+       TEE_ATTR_ECC_PUBLIC_VALUE_Y = 0xD0000241,
+       TEE_ATTR_ECC_PRIVATE_VALUE = 0xC0000341,
+       TEE_ATTR_ECC_CURVE = 0xF0000441,
 #endif // ECC_IMPLEMENTATION
 
 //Certificate attribute start
index 33395d10d79cdd0d6a44dc7b0cfc2a5e068b06fd..a8694d995ab91e41eeafa53c9e05829d04c7d04f 100644 (file)
@@ -70,12 +70,16 @@ typedef struct
        crypto_internal_keydata secret;                         /* TEE_ATTR_SECRET_VALUE */
        crypto_internal_keydata rsa_modulus;            /* TEE_ATTR_RSA_MODULUS / TEE_ATTR_DSA_BASE */
        crypto_internal_keydata rsa_public;                     /* TEE_ATTR_RSA_PUBLIC_EXPONENT / TEE_ATTR_DSA_PUBLIC_VALUE  */
-       crypto_internal_keydata rsa_private;                    /* TEE_ATTR_RSA_PRIVATE_EXPONENT / TEE_ATTR_DSA_PRIVATE_VALUE  */
-       crypto_internal_keydata rsa_prime1;             /* TEE_ATTR_RSA_PRIME1 / TEE_ATTR_DSA_PRIME  */
-       crypto_internal_keydata rsa_prime2;             /* TEE_ATTR_RSA_PRIME2 / TEE_ATTR_DSA_SUBPRIME  */
+       crypto_internal_keydata rsa_private;            /* TEE_ATTR_RSA_PRIVATE_EXPONENT / TEE_ATTR_DSA_PRIVATE_VALUE  */
+       crypto_internal_keydata rsa_prime1;                     /* TEE_ATTR_RSA_PRIME1 / TEE_ATTR_DSA_PRIME  */
+       crypto_internal_keydata rsa_prime2;                     /* TEE_ATTR_RSA_PRIME2 / TEE_ATTR_DSA_SUBPRIME  */
        crypto_internal_keydata rsa_exponent1;          /* TEE_ATTR_RSA_EXPONENT1 */
        crypto_internal_keydata rsa_exponent2;          /* TEE_ATTR_RSA_EXPONENT2 */
-       crypto_internal_keydata rsa_coefficient;                /* TEE_ATTR_RSA_COEFFICIENT */
+       crypto_internal_keydata rsa_coefficient;        /* TEE_ATTR_RSA_COEFFICIENT */
+       crypto_internal_keydata ecc_private;            /* TEE_ATTR_ECC_PRIVATE_VALUE */
+       crypto_internal_keydata ecc_public_x;           /* TEE_ATTR_ECC_PUBLIC_VALUE_X */
+       crypto_internal_keydata ecc_public_y;           /* TEE_ATTR_ECC_PUBLIC_VALUE_Y */
+       uint32_t ecc_curve;                                                     /* TEE_ATTR_ECC_CURVE */
 } crypto_internal_keystruct;
 
 void crypto_internal_set_engine(int set);
index d875e2107ac6c0bf623264a17748d76553ed599d..1b6372afe21e8da729a464433f781aef16ff0e17 100644 (file)
@@ -41,5 +41,10 @@ int ossl_crypto_ae_enc_final(crypto_internal_operation *op, void *src, size_t sr
                                                        void *dst, size_t *dst_len, void *tag, size_t *tag_len);
 int ossl_crypto_ae_dec_final(crypto_internal_operation *op, void *src, size_t src_len,
                                                        void *dst, size_t *dst_len, void *tag, size_t tag_len);
+int ossl_ecdsa_sign(crypto_internal_keydata priv_key, const void *src, size_t src_len,
+                                                       void *sig, size_t *sig_len);
+int ossl_ecdsa_verify(uint32_t curve, crypto_internal_keydata pub_x, crypto_internal_keydata pub_y,
+                                                       const void *src, size_t src_len, const void *sig, size_t sig_len);
+int curve_to_nid(int curve, int *nid);
 
 #endif // _SSF_CRYPTO_OPENSSL_H_
index bbd5233fe5d0760dce0d3221c5ad58de5c76309d..b834cc2f70b492d6ca34d1676cf02fe7322f6512 100644 (file)
@@ -925,19 +925,45 @@ private:
 
 int crypto_internal_open(crypto_internal_operation *operation)
 {
-       if (operation->info.algorithm == TEE_ALG_AES_GCM || operation->info.algorithm == TEE_ALG_AES_CTR) {
+       switch(operation->info.algorithm) {
+       case TEE_ALG_AES_GCM:
+       case TEE_ALG_AES_CTR:
+       case TEE_ALG_ECDSA_P160:
+       case TEE_ALG_ECDSA_P192:
+       case TEE_ALG_ECDSA_P224:
+       case TEE_ALG_ECDSA_P256:
+       case TEE_ALG_ECDSA_P384:
+       case TEE_ALG_ECDSA_P521:
+       case TEE_ALG_ECDH_P192:
+       case TEE_ALG_ECDH_P224:
+       case TEE_ALG_ECDH_P256:
+       case TEE_ALG_ECDH_P384:
+       case TEE_ALG_ECDH_P521:
                return ossl_crypto_open(operation);
-       } else {
+       default:
                return sw_crypto_open(operation);
        }
 }
 
 int crypto_internal_close(crypto_internal_operation *operation)
 {
-       if (operation->info.algorithm == TEE_ALG_AES_GCM || operation->info.algorithm == TEE_ALG_AES_CTR) {
+       switch(operation->info.algorithm) {
+       case TEE_ALG_AES_GCM:
+       case TEE_ALG_AES_CTR:
+       case TEE_ALG_ECDSA_P160:
+       case TEE_ALG_ECDSA_P192:
+       case TEE_ALG_ECDSA_P224:
+       case TEE_ALG_ECDSA_P256:
+       case TEE_ALG_ECDSA_P384:
+       case TEE_ALG_ECDSA_P521:
+       case TEE_ALG_ECDH_P192:
+       case TEE_ALG_ECDH_P224:
+       case TEE_ALG_ECDH_P256:
+       case TEE_ALG_ECDH_P384:
+       case TEE_ALG_ECDH_P521:
                ossl_crypto_close(operation);
                return 0;
-       } else {
+       default:
                return sw_crypto_close(operation);
        }
 }
@@ -2604,6 +2630,7 @@ TEE_Result TEE_AsymmetricSignDigest( TEE_OperationHandle operation, const TEE_At
        crypto_internal_operation *op = (crypto_internal_operation*) operation;
        crypto_internal_keystruct key;
        TEE_ObjectInfo info;
+       int ret = 0;
 
        if (op->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) {
                CRYPTO_PANIC;
@@ -2688,17 +2715,36 @@ TEE_Result TEE_AsymmetricSignDigest( TEE_OperationHandle operation, const TEE_At
                                (void*) key.rsa_private.buffer, (size_t*) &key.rsa_private.size) != TEE_SUCCESS) {
                        CRYPTO_PANIC;
                }
-
+               break;
+       }
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_KEYPAIR:
+       {
+               bp.PrepareBuffer(maxAttrSize, key.ecc_private);
+               if (TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_ECC_PRIVATE_VALUE,
+                               (void*) key.ecc_private.buffer, (size_t*) &key.ecc_private.size) != TEE_SUCCESS) {
+                       CRYPTO_PANIC;
+               }
+               uint32_t a, b;
+               if (TEE_GetObjectValueAttribute(op->key1, TEE_ATTR_ECC_CURVE, &a, &b) != TEE_SUCCESS) {
+                       CRYPTO_PANIC;
+               }
+               key.ecc_curve = b;
                break;
        }
        default:
                CRYPTO_PANIC;
        }
 
-       if (crypto_internal_init(op, &key, NULL, 0)) {
-               CRYPTO_PANIC;
+       if (info.objectType == TEE_TYPE_ECDSA_KEYPAIR || info.objectType == TEE_TYPE_ECDH_KEYPAIR) {
+               ret = ossl_ecdsa_sign(key.ecc_private, digest, digestLen, signature, signatureLen);
+       } else {
+               if (crypto_internal_init(op, &key, NULL, 0)) {
+                       CRYPTO_PANIC;
+               }
+               ret = crypto_internal_final(op, (unsigned char*)digest, digestLen, (unsigned char*)signature, signatureLen);
        }
-       int ret = crypto_internal_final(op, (unsigned char*)digest, digestLen, (unsigned char*)signature, signatureLen);
+
        switch (ret) {
        case 0:
                return TEE_SUCCESS;
@@ -2719,6 +2765,7 @@ TEE_Result TEE_AsymmetricVerifyDigest( TEE_OperationHandle operation, const TEE_
        crypto_internal_keystruct key;
        size_t sign_len=signatureLen;
        TEE_ObjectInfo info;
+       int ret = 0;
 
        if (op->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) {
                CRYPTO_PANIC;
@@ -2784,14 +2831,43 @@ TEE_Result TEE_AsymmetricVerifyDigest( TEE_OperationHandle operation, const TEE_
                }
                break;
        }
+       case TEE_TYPE_ECDSA_PUBLIC_KEY:
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_PUBLIC_KEY:
+       case TEE_TYPE_ECDH_KEYPAIR:
+       {
+               bp.PrepareBuffer(maxAttrSize, key.ecc_public_x);
+               bp.PrepareBuffer(maxAttrSize, key.ecc_public_y);
+               if (TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_ECC_PUBLIC_VALUE_X,
+                               (void*) key.ecc_public_x.buffer, (size_t*) &key.ecc_public_x.size) != TEE_SUCCESS) {
+                       CRYPTO_PANIC;
+               }
+               if (TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+                               (void*) key.ecc_public_y.buffer, (size_t*) &key.ecc_public_y.size) != TEE_SUCCESS) {
+                       CRYPTO_PANIC;
+               }
+               uint32_t a, b;
+               if (TEE_GetObjectValueAttribute(op->key1, TEE_ATTR_ECC_CURVE, &a, &b) != TEE_SUCCESS) {
+                       CRYPTO_PANIC;
+               }
+               key.ecc_curve = b;
+               break;
+       }
        default:
                CRYPTO_PANIC;
        }
 
-       if (crypto_internal_init(op, &key, NULL, 0)) {
-               CRYPTO_PANIC;
+       if (info.objectType == TEE_TYPE_ECDSA_PUBLIC_KEY || info.objectType == TEE_TYPE_ECDSA_KEYPAIR ||
+           info.objectType == TEE_TYPE_ECDH_PUBLIC_KEY || info.objectType == TEE_TYPE_ECDH_KEYPAIR) {
+               ret = ossl_ecdsa_verify(key.ecc_curve, key.ecc_public_x, key.ecc_public_y,
+                                                               digest, digestLen, signature, signatureLen);
+       } else {
+               if (crypto_internal_init(op, &key, NULL, 0)) {
+                       CRYPTO_PANIC;
+               }
+               ret = crypto_internal_final(op, (unsigned char*)digest, digestLen, (unsigned char*)signature, &sign_len);
        }
-       int ret = crypto_internal_final(op, (unsigned char*)digest, digestLen, (unsigned char*)signature, &sign_len);
+
        switch (ret) {
        case 0:
                return TEE_SUCCESS;
index a96535051561cad991706373913656f0e88fc5fa..578ac9c81e9c863a174ed6fc36ac97af8075e21f 100644 (file)
 #include "ssf_crypto_openssl.h"
 #include <tee_internal_api.h>
 #include <openssl/evp.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ecdh.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
 #include <log.h>
 
 // DO NOT MODIFY BELOW VALUES
@@ -293,3 +297,69 @@ int ossl_crypto_ae_dec_final(crypto_internal_operation *op, void *src, size_t sr
        return 0;
 }
 
+int ossl_ecdsa_sign(crypto_internal_keydata priv_key,
+                                       const void *src, size_t src_len,
+                                       void *sig, size_t *sig_len)
+{
+       EC_KEY* eckey;
+
+    BIO* bio = BIO_new_mem_buf(priv_key.buffer, priv_key.size);
+
+       if ((eckey = d2i_ECPrivateKey_bio(bio, NULL)) == NULL) {
+               LOGE(MODULE_SSF_LIB, "ossl_ecdsa_sign: PEM_read_bio_ECPrivateKey() failed");
+               return -1;
+    }
+
+       if (ECDSA_sign(0, (unsigned char *)src, (int) src_len,
+                                       (unsigned char *) sig, (unsigned int *)sig_len, eckey) == 0) {
+               LOGE(MODULE_SSF_LIB, "ossl_ecdsa_sign: ECDSA_sign() failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+int ossl_ecdsa_verify(uint32_t curve,
+                                       crypto_internal_keydata pub_x,
+                                       crypto_internal_keydata pub_y,
+                                       const void *src, size_t src_len,
+                                       const void *sig, size_t sig_len)
+{
+       int nid;
+       EC_KEY* eckey;
+       BIGNUM *x, *y;
+       int ret;
+
+       if (curve_to_nid(curve, &nid) != 0) {
+               LOGE(MODULE_SSF_LIB, "ossl_ecdsa_sign: to_nid() failed");
+               return -2;
+       }
+       eckey = EC_KEY_new_by_curve_name(nid);
+
+       x = BN_bin2bn(pub_x.buffer, pub_x.size, NULL);
+       y = BN_bin2bn(pub_y.buffer, pub_y.size, NULL);
+
+    EC_KEY_set_public_key_affine_coordinates(eckey, x, y);
+    EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
+
+       ret = ECDSA_verify(0, (unsigned char *)src, (int) src_len,
+                                       (unsigned char *) sig, (unsigned int)sig_len, eckey);
+       if (ret == 0) { // Invalid Signature
+               LOGE(MODULE_SSF_LIB, "ossl_ecdsa_verify: ECDSA_verify() failed");
+               return -1;
+       } else if (ret < 0) { // Error
+               LOGE(MODULE_SSF_LIB, "ossl_ecdsa_verify: Error happened in ECDSA_verify()");
+               return -1;
+       }
+
+       return 0;
+}
+
+int curve_to_nid(int curve, int *nid) {
+       switch ((TEE_ECC_CURVE) curve) {
+               case TEE_ECC_CURVE_NIST_P192: {*nid = NID_X9_62_prime192v1; return 0;}
+               case TEE_ECC_CURVE_NIST_P256: {*nid = NID_X9_62_prime256v1; return 0;}
+               case TEE_ECC_CURVE_NIST_P384: {*nid = NID_secp384r1; return 0;}
+               default: return -1;
+       }
+}
\ No newline at end of file
index c9ce5f73062738cfac2efb3a3cf76d4036feca58..0323781b88de4b16008965206470129a6bb6e1e2 100644 (file)
  *  Include files
  *-----------------------------------------------------------------------------*/
 #include "ssf_storage.h"
+#include "ssf_crypto_openssl.h"
 #include <sys/mman.h>
 #include <string.h>
 #include <permission.h>
 #include <log.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ecdh.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
 
 /*-----------------------------------------------------------------------------
  *  MACROS
@@ -95,6 +101,12 @@ void printhex(unsigned char* buf, unsigned int size) {
        MSG("\n---------------------------------------------------");
 }
 
+static inline bool isValueAttr(uint32_t attrId)
+{
+       // bit[29] == 1 -> value type attribute, not a buffer attribute.
+       return attrId & TEE_ATTR_FLAG_VALUE;
+}
+
 /*-----------------------------------------------------------------------------
  *  TEE API implementation
  *-----------------------------------------------------------------------------*/
@@ -134,6 +146,27 @@ void free_attribute(TEE_Attribute* attr) {
        }
 }
 
+int to_buffer(BIO *bio, uint8_t **buffer, size_t *size) {
+       uint8_t tmp[1024*4];
+       uint8_t* tmp_buffer;
+       size_t read = 0;
+
+       BIO_seek(bio, 0);
+       read = BIO_read(bio, tmp, sizeof(tmp));
+       if (read >= sizeof(tmp)) { // Too Big Data
+               return -1;
+       }
+       tmp_buffer = (uint8_t*) malloc(read);
+       if(tmp_buffer == NULL) {
+               return -1;
+       }
+       memcpy(tmp_buffer, tmp, read);
+
+       *buffer = tmp_buffer;
+       *size = read;
+       return 0;
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////////
 // Internal transient Object Operations
 /////////////////////////////////////////////////////////////////////////////////////////////
@@ -194,6 +227,15 @@ TEE_Result allocate_transient_object(TransientObject* tr, uint32_t objectType,
                        if (maxObjectSize < 256 || maxObjectSize > 2048)
                          return TEE_ERROR_NOT_SUPPORTED;
                        break;
+#ifdef ECC_IMPLEMENTATION
+               case TEE_TYPE_ECDSA_PUBLIC_KEY:
+               case TEE_TYPE_ECDSA_KEYPAIR:
+               case TEE_TYPE_ECDH_PUBLIC_KEY:
+               case TEE_TYPE_ECDH_KEYPAIR:
+                       // This types of keys will have internal format.
+                       // So no size check is required.
+                       break;
+#endif // ECC_IMPLEMENTATION
                case TEE_TYPE_GENERIC_SECRET:
                        if (maxObjectSize > 4096 || maxObjectSize % 8)
                          return TEE_ERROR_NOT_SUPPORTED;
@@ -1473,7 +1515,8 @@ TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object,
 
        TEE_Attribute* curr_attr = &tr->attr.attr_array[tr->attr.attr_number];
        for (i = 0; i < attrCount; i++) {
-               if (attrs[i].content.ref.length * 8 > tr->info.maxObjectSize) {
+               if ((!isValueAttr(attrs[i].attributeID))
+                               && (attrs[i].content.ref.length * 8 > tr->info.maxObjectSize)) {
                        TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__);
                        TEE_Panic(0);
                }
@@ -1536,6 +1579,22 @@ TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object,
                        }
                }
                        break;
+               case TEE_TYPE_ECDSA_PUBLIC_KEY:
+               case TEE_TYPE_ECDH_PUBLIC_KEY: {
+                       if (tr->attr.attr_number != 3) {
+                               TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+                       break;
+               }
+               case TEE_TYPE_ECDSA_KEYPAIR:
+               case TEE_TYPE_ECDH_KEYPAIR: {
+                       if (tr->attr.attr_number != 4) {
+                               TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+                       break;
+               }
                default:
                        return TEE_ERROR_BAD_PARAMETERS;
        }
@@ -1582,12 +1641,18 @@ void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject,
            || ((dest->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY)
                && (src->info.objectType == TEE_TYPE_RSA_KEYPAIR))
            || ((dest->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY)
-               && (src->info.objectType == TEE_TYPE_DSA_KEYPAIR)))) {
+               && (src->info.objectType == TEE_TYPE_DSA_KEYPAIR))
+           || ((dest->info.objectType == TEE_TYPE_ECDSA_PUBLIC_KEY)
+               && (src->info.objectType == TEE_TYPE_ECDSA_KEYPAIR))
+           || ((dest->info.objectType == TEE_TYPE_ECDH_PUBLIC_KEY)
+               && (src->info.objectType == TEE_TYPE_ECDH_KEYPAIR)))) {
                TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__);
+               TZ_ERROR("dest obj type = %x, src obj type = %x\n", dest->info.objectType , src->info.objectType);
                TEE_Panic(0);
        }
+
        if (src->info.objectSize > dest->info.maxObjectSize) {
-               TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__);
+               TZ_ERROR("operation error line = %d,%s, src_obj_size=%d, dest_max_obj_size=%d\n", __LINE__, __func__, src->info.objectSize, dest->info.maxObjectSize);
                TEE_Panic(0);
        }
        dest->info.objectSize = src->info.objectSize;
@@ -1779,8 +1844,87 @@ TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize,
                        OsaFree(pubKey);
                }
                        break;
+#ifdef ECC_IMPLEMENTATION
+               case TEE_TYPE_ECDSA_KEYPAIR:
+               case TEE_TYPE_ECDH_KEYPAIR: {
+                       size_t key_size = (keySize + 7) / 8;
+                       int nid = 0;
+                       uint8_t *privKey = NULL, *pubX = NULL, *pubY = NULL;
+                       size_t privSize = 0, pubXSize = 0, pubYSize = 0;
+
+                       for (i = 0; i < paramCount; i++) {
+                               if (params[i].attributeID == TEE_ATTR_ECC_CURVE) {
+                                       if (curve_to_nid(params[i].content.value.b, &nid) != 0)
+                                               return TEE_ERROR_BAD_PARAMETERS;
+                                       check |= 0x01;
+                               }
+                       }
+                       if (check != 0x01) {
+                               TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+
+                       /* Create an Elliptic Curve Key object */
+                       EC_KEY *ec_key = EC_KEY_new();
+                       EC_GROUP *ec_group = EC_GROUP_new_by_curve_name(nid);
+                       EC_KEY_set_group(ec_key, ec_group);
+                       if(NULL == ec_group) {
+                               TZ_ERROR("EC_GROUP_new_by_curve_name() operation error line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+
+                       /* Generate the private and public key */
+                       if(1 != EC_KEY_generate_key(ec_key))  {
+                               TZ_ERROR("EC_KEY_generate_key() operation error line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+
+                       BIO *bio_pri = BIO_new(BIO_s_mem());
+                       i2d_ECPrivateKey_bio(bio_pri, ec_key);
+
+                       if(to_buffer(bio_pri, &privKey, &privSize) != 0) {
+                               TZ_ERROR("failed to convert private key to binary. line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+
+                       const EC_POINT *pubkey_pnt = EC_KEY_get0_public_key(ec_key);
+                       BIGNUM *x = BN_new();
+                       BIGNUM *y = BN_new();
+                       if (EC_POINT_get_affine_coordinates_GFp(ec_group, pubkey_pnt, x, y, NULL) != 1) {
+                               TZ_ERROR("failed in EC_POINT_get_affine_coordinates_GFp(). line = %d,%s\n", __LINE__, __func__);
+                               TEE_Panic(0);
+                       }
+                       pubX = (uint8_t *) malloc(key_size);
+                       pubY = (uint8_t *) malloc(key_size);
+                       pubXSize = BN_bn2bin(x, pubX);
+                       pubYSize = BN_bn2bin(y, pubY);
+                       if (key_size < pubXSize || key_size < pubYSize) {
+                               TZ_ERROR("Too small key size. line = %d,%s. key_size=%d, pubXSize=%d, pubYSize=%d\n",
+                                               __LINE__, __func__, key_size, pubXSize, pubYSize);
+                               TEE_Panic(0);
+                       }
+
+                       TEE_InitValueAttribute(&attrs[0], params[0].attributeID, params[0].content.value.a, params[0].content.value.b);
+                       TEE_InitRefAttribute(&attrs[1], TEE_ATTR_ECC_PRIVATE_VALUE, privKey, privSize);
+                       TEE_InitRefAttribute(&attrs[2], TEE_ATTR_ECC_PUBLIC_VALUE_X, pubX, pubXSize);
+                       TEE_InitRefAttribute(&attrs[3], TEE_ATTR_ECC_PUBLIC_VALUE_Y, pubY, pubYSize);
+                       TEE_PopulateTransientObject(object, attrs, 4);
+
+                       EC_GROUP_free(ec_group);
+                       EC_KEY_free(ec_key);
+                       BIO_free(bio_pri);
+                       BN_free(x);
+                       BN_free(y);
+                       free(privKey);
+                       free(pubX);
+                       free(pubY);
+               }
+                       break;
+#endif // ECC_IMPLEMENTATION
        }
 
+       tr->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
+
        return TEE_SUCCESS;
 }