add support for ECC key generation, signing, verifying 07/294807/9
authorDongsun Lee <ds73.lee@samsung.com>
Tue, 27 Jun 2023 01:57:46 +0000 (10:57 +0900)
committerDongsun Lee <ds73.lee@samsung.com>
Mon, 7 Aug 2023 10:37:10 +0000 (19:37 +0900)
Change-Id: Iaa55e9e281c0a8388414d5fd8422ff28a1efd6c9

ta/include/cmd_exec.h
ta/include/internal.h
ta/src/cmd_exec.c
ta/src/internal.c
ta/src/km_ta.c

index c4171d7ef8647c26e2a06c22fd7f6e71878b60a6..181963059600da08a0b79164406ab7b84fcc93ef 100644 (file)
@@ -32,6 +32,8 @@ TEE_Result KM_ExecCmdGenerateRSAKey(TEE_Param param[4]);
 
 TEE_Result KM_ExecCmdGenerateDSAKey(TEE_Param param[4]);
 
+TEE_Result KM_ExecCmdGenerateECKey(TEE_Param param[4]);
+
 TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4]);
 
 TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4]);
index 87357f666ad90ac023e645e9d16b72e9007c8083..603c545d8b627b54ad2a6dd9d65e348f47ca1efb 100644 (file)
@@ -118,4 +118,10 @@ static inline void KM_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID
        TEE_InitRefAttribute(attr, attributeID, buffer, lengthBytes);
 }
 
+static inline void KM_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID,
+                                                                       uint32_t a, uint32_t b)
+{
+       TEE_InitValueAttribute(attr, attributeID, a, b);
+}
+
 #endif // __INTERNAL_H__
index 79f5576d4faecb4f4cc9392639cafa87507a2a62..a46aef451c9543292431cc0d56ed9517f18076ba 100644 (file)
@@ -100,6 +100,7 @@ static uint32_t KM_IsAsymSVKeyCorrect(uint32_t commandID, TEE_ObjectHandle key)
                switch (info.objectType) {
                case TEE_TYPE_RSA_KEYPAIR:
                case TEE_TYPE_DSA_KEYPAIR:
+               case TEE_TYPE_ECDSA_KEYPAIR:
                        return 1;
                default: break;
                };
@@ -107,12 +108,13 @@ static uint32_t KM_IsAsymSVKeyCorrect(uint32_t commandID, TEE_ObjectHandle key)
                switch (info.objectType) {
                case TEE_TYPE_RSA_PUBLIC_KEY:
                case TEE_TYPE_DSA_PUBLIC_KEY:
+               case TEE_TYPE_ECDSA_PUBLIC_KEY:
                        return 1;
                default: break;
                };
        }
 
-       LOGD("Invalid key type provided for given command");
+       LOGD("Invalid key type provided for given command. objectType=%x", info.objectType);
        return 0;
 }
 
@@ -164,6 +166,17 @@ static uint32_t KM_CheckAlgoKeySize(uint32_t type, uint32_t key_size)
                        return 0;
                }
        }
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_KEYPAIR: {
+               switch (key_size) {
+               case 192:
+               case 256:
+               case 384:
+                       return 1;
+               default:
+                       return 0;
+               }
+       }
        default:
                LOG("Invalid key type provided: %x", type);
                return 0;
@@ -190,8 +203,13 @@ static uint32_t KM_AlgoHash2SignVerifyAlgo(int algo, int hash)
                }
        }
        case ALGO_ECDSA_SV: {
-               // TODO unsupported in GP API 1.0
-               return 0;
+               switch (hash) {
+               case HASH_SHA1: return TEE_ALG_ECDSA_P192;
+               case HASH_SHA256: return TEE_ALG_ECDSA_P256;
+               case HASH_SHA384: return TEE_ALG_ECDSA_P384;
+               case HASH_SHA512: return TEE_ALG_ECDSA_P521;
+               default: return 0;
+               }
        }
        default: return 0;
        }
@@ -235,21 +253,25 @@ static TEE_Result KM_SaveKeyGeneric(uint32_t isEncrypted,
        return ret;
 }
 
-static TEE_Result KM_AllocateObjId(KM_BinaryData *objId)
+static TEE_Result KM_ToTeeEccCurve(uint32_t curve, uint32_t *id)
 {
-       if (objId == NULL) {
-               LOG("objId is NULL");
-               return TEE_ERROR_GENERIC;
+       switch(curve) {
+       case EC_NIST_P192: *id = TEE_ECC_CURVE_NIST_P192; break;
+       case EC_NIST_P256: *id = TEE_ECC_CURVE_NIST_P256; break;
+       case EC_NIST_P384: *id = TEE_ECC_CURVE_NIST_P384; break;
+       default: return TEE_ERROR_BAD_PARAMETERS;
        }
+       return TEE_SUCCESS;
+}
 
-       objId->data_size = KM_KEY_ID_SIZE;
-       objId->data = malloc(objId->data_size);
-
-       if (objId->data == NULL) {
-               LOG("Failed to allocate object ID buffer");
-               return TEE_ERROR_OUT_OF_MEMORY;
+static TEE_Result KM_ToKeyBitSize(uint32_t curve, uint32_t *bitsize)
+{
+       switch(curve) {
+       case EC_NIST_P192: *bitsize = 192; break;
+       case EC_NIST_P256: *bitsize = 256; break;
+       case EC_NIST_P384: *bitsize = 384; break;
+       default: return TEE_ERROR_BAD_PARAMETERS;
        }
-
        return TEE_SUCCESS;
 }
 
@@ -595,6 +617,38 @@ TEE_Result KM_ExecCmdGenerateDSAKey(TEE_Param param[4])
                                                        sizeof(dsaParams) / sizeof(*dsaParams));
 }
 
+TEE_Result KM_ExecCmdGenerateECKey(TEE_Param param[4])
+{
+       TEE_Attribute ecParams[1];
+       uint32_t curve;
+       uint32_t keyBitSize;
+       int ret;
+
+       ret = KM_ToTeeEccCurve(param[0].value.b, &curve);
+       if (ret) {
+               LOG("Failed to convert curve, input = %d", param[0].value.b);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       ret = KM_ToKeyBitSize(param[0].value.b, &keyBitSize);
+       if (ret) {
+               LOG("Failed to convert to keyBitSize, input = %d", param[0].value.b);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       KM_InitValueAttribute(&ecParams[0], TEE_ATTR_ECC_CURVE, 0, (uint32_t) curve);
+
+       return KM_GenerateAsymKey(param[1].memref.buffer,
+                                                       param[1].memref.size,
+                                                       param[2].memref.buffer,
+                                                       param[2].memref.size,
+                                                       TEE_TYPE_ECDSA_KEYPAIR,
+                                                       TEE_TYPE_ECDSA_PUBLIC_KEY,
+                                                       keyBitSize,
+                                                       ecParams,
+                                                       sizeof(ecParams) / sizeof(*ecParams));
+}
+
 TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
 {
        TEE_Result ret = TEE_SUCCESS;
index 86fe5702610e33f60ffd94c32715406d15da3e27..870b839cc477c8e3fc0ec2c5b7a7223b74bd1d34 100644 (file)
@@ -71,12 +71,27 @@ const uint32_t DSA_PUBLIC_ATTRIBUTES[] = {
        TEE_ATTR_DSA_PUBLIC_VALUE,
 };
 
+const uint32_t ECC_PRIVATE_ATTRIBUTES[] = {
+       TEE_ATTR_ECC_CURVE,
+       TEE_ATTR_ECC_PRIVATE_VALUE,
+       TEE_ATTR_ECC_PUBLIC_VALUE_X,
+       TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+};
+
+const uint32_t ECC_PUBLIC_ATTRIBUTES[] = {
+       TEE_ATTR_ECC_CURVE,
+       TEE_ATTR_ECC_PUBLIC_VALUE_X,
+       TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+};
+
 #define arraySize(A) (sizeof(A) / sizeof(A[0]))
 
 #define RSA_PRIVATE_ATTRIBUTES_SIZE arraySize(RSA_PRIVATE_ATTRIBUTES)
 #define RSA_PUBLIC_ATTRIBUTES_SIZE arraySize(RSA_PUBLIC_ATTRIBUTES)
 #define DSA_PRIVATE_ATTRIBUTES_SIZE arraySize(DSA_PRIVATE_ATTRIBUTES)
 #define DSA_PUBLIC_ATTRIBUTES_SIZE arraySize(DSA_PUBLIC_ATTRIBUTES)
+#define ECC_PRIVATE_ATTRIBUTES_SIZE arraySize(ECC_PRIVATE_ATTRIBUTES)
+#define ECC_PUBLIC_ATTRIBUTES_SIZE arraySize(ECC_PUBLIC_ATTRIBUTES)
 
 #define MAX_ATTRIBUTES_SIZE (\
        RSA_PRIVATE_ATTRIBUTES_SIZE > DSA_PRIVATE_ATTRIBUTES_SIZE\
@@ -120,6 +135,15 @@ int KM_CheckAuthAESMode(uint32_t algo, uint32_t tagLen)
        }
 }
 
+static inline bool isValueAttr(uint32_t attrId)
+{
+       // bit[29] == 1 -> value type attribute, not a buffer attribute.
+       if (attrId & TEE_ATTR_FLAG_VALUE)
+               return true;
+       else
+               return false;
+}
+
 static TEE_Result KM_CreateTransientObject(uint32_t object_type,
                                            uint32_t max_object_size,
                                            TEE_Attribute attr[],
@@ -207,8 +231,19 @@ TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size,
                                                        TEE_ObjectHandle *hndl)
 {
        TEE_Result ret = TEE_SUCCESS;
+       uint32_t max_object_size = key_bits_size;
+
+       switch (tee_key_type) {
+       case TEE_TYPE_ECDSA_PUBLIC_KEY:
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_PUBLIC_KEY:
+       case TEE_TYPE_ECDH_KEYPAIR:
+               // Give enough room for generated keys in private format
+               max_object_size = key_bits_size * 8;
+               break;
+       }
 
-       ret = TEE_AllocateTransientObject(tee_key_type, key_bits_size, hndl);
+       ret = TEE_AllocateTransientObject(tee_key_type, max_object_size, hndl);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AllocateTransientObject has failed with=%x. key_type = %x size_bits = %u",
                        ret, tee_key_type, key_bits_size);
@@ -229,8 +264,19 @@ TEE_Result KM_CreateKeyFromKey(uint32_t tee_key_type, uint32_t key_bits_size,
                                                        TEE_ObjectHandle srcHndl, TEE_ObjectHandle *dstHndl)
 {
        TEE_Result ret = TEE_SUCCESS;
+       uint32_t max_object_size = key_bits_size;
+
+       switch (tee_key_type) {
+       case TEE_TYPE_ECDSA_PUBLIC_KEY:
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_PUBLIC_KEY:
+       case TEE_TYPE_ECDH_KEYPAIR:
+               // Give enough room for generated keys in private format
+               max_object_size = key_bits_size * 8;
+               break;
+       }
 
-       ret = TEE_AllocateTransientObject(tee_key_type, key_bits_size, dstHndl);
+       ret = TEE_AllocateTransientObject(tee_key_type, max_object_size, dstHndl);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AllocateTransientObject has failed with=%x. Arguments=(tee_key_type=%X, "
                        "key_bits_size=%d.", ret, tee_key_type, key_bits_size);
@@ -348,7 +394,47 @@ out:
        return ret;
 }
 
-static TEE_Result KM_GetAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr)
+static TEE_Result KM_GetValueAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr)
+{
+       TEE_Result ret;
+       uint32_t a, b;
+
+       if (attr == NULL) {
+               LOG("Attribute buffer is NULL");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (!isValueAttr(attrId)) {
+               LOG("attributeID is not for value. attrId=%x", attrId);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       attr->data_size = sizeof(uint32_t) * 2; // for a and b of TEE_Attribute.content.value
+       attr->data = malloc(attr->data_size);
+       if (attr->data == NULL) {
+               LOG("Failed to allocate memory for key attribute.");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+
+       ret = TEE_GetObjectValueAttribute(keyHndl, attrId, &a, &b);
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed to get object value attribute info, ret = %x", ret);
+               goto  clean;
+       }
+       memcpy(attr->data, &a, sizeof(uint32_t));
+       memcpy((attr->data) + sizeof(uint32_t), &b, sizeof(uint32_t));
+
+clean:
+       if (ret != TEE_SUCCESS) {
+               free(attr->data);
+               attr->data = NULL;
+               attr->data_size = 0;
+       }
+       return ret;
+}
+
+static TEE_Result KM_GetBufferAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr)
 {
        TEE_ObjectInfo objInfo;
        TEE_Result ret;
@@ -359,6 +445,11 @@ static TEE_Result KM_GetAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_
                return TEE_ERROR_BAD_PARAMETERS;
        }
 
+       if (isValueAttr(attrId)) {
+               LOG("attributeID is not for buffer. attrId=%x", attrId);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
        /*
         * TODO current key size is used as maximum attribute size because prompting the size with NULL
         * buffer in TEE_GetObjectBufferAttribute doesn't work in simulator.
@@ -392,6 +483,14 @@ clean:
        return ret;
 }
 
+static TEE_Result KM_GetAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr)
+{
+       if (isValueAttr(attrId))
+               return KM_GetValueAttribute(keyHndl, attrId, attr);
+       else
+               return KM_GetBufferAttribute(keyHndl, attrId, attr);
+}
+
 static TEE_Result KM_EncryptAsymKeyInternal(TEE_ObjectHandle keyHndl, const KM_PwdData *pwd,
                                                                                        const uint32_t *attrIds, const uint32_t attrsCount,
                                                                                        KM_BinaryData *encKey, KM_BinaryData *tag)
@@ -535,6 +634,7 @@ static TEE_Result KM_CreateDecryptedAsymKey(void *data, uint32_t dataSize, uint3
        TEE_Attribute attributes[attrsCount];
        uint32_t i = 0;
        uint32_t maxObjectSizeBits = 0;
+       uint32_t *a, *b;
 
        if (KM_DeserializeFlag(&data, &dataSize, &maxObjectSizeBits)) {
                LOG("Failed to deserialize object size");
@@ -547,7 +647,13 @@ static TEE_Result KM_CreateDecryptedAsymKey(void *data, uint32_t dataSize, uint3
                        return TEE_ERROR_BAD_PARAMETERS;
                }
 
-               KM_InitRefAttribute(&attributes[i], attrIDs[i], readAttr[i].data, readAttr[i].data_size);
+               if (isValueAttr(attrIDs[i])) {
+                       a = readAttr[i].data;
+                       b = readAttr[i].data + sizeof(uint32_t);
+                       KM_InitValueAttribute(&attributes[i], attrIDs[i], *a, *b);
+               } else {
+                       KM_InitRefAttribute(&attributes[i], attrIDs[i], readAttr[i].data, readAttr[i].data_size);
+               }
        }
 
        return KM_CreateTransientObject(keyType, maxObjectSizeBits, attributes, attrsCount, hndl);
@@ -646,6 +752,16 @@ TEE_Result KM_EncryptAsymKey(TEE_ObjectHandle keyHndl, const KM_PwdData *pwd,
                return KM_EncryptAsymKeyInternal(keyHndl, pwd,
                                                                                DSA_PUBLIC_ATTRIBUTES, DSA_PUBLIC_ATTRIBUTES_SIZE,
                                                                                encKey, tag);
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_KEYPAIR:
+               return KM_EncryptAsymKeyInternal(keyHndl, pwd,
+                                                                               ECC_PRIVATE_ATTRIBUTES, ECC_PRIVATE_ATTRIBUTES_SIZE,
+                                                                               encKey, tag);
+       case TEE_TYPE_ECDSA_PUBLIC_KEY:
+       case TEE_TYPE_ECDH_PUBLIC_KEY:
+               return KM_EncryptAsymKeyInternal(keyHndl, pwd,
+                                                                               ECC_PUBLIC_ATTRIBUTES, ECC_PUBLIC_ATTRIBUTES_SIZE,
+                                                                               encKey, tag);
        default:
                LOG("Invalid object type provided for asymmetric key encryption");
                return TEE_ERROR_BAD_PARAMETERS;
@@ -885,6 +1001,16 @@ TEE_Result KM_DecryptAsymKey(const KM_BinaryData *id, KM_PwdData* pwd, TEE_Objec
                ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
                        DSA_PUBLIC_ATTRIBUTES, DSA_PUBLIC_ATTRIBUTES_SIZE, decKeyHndl);
                break;
+       case TEE_TYPE_ECDSA_KEYPAIR:
+       case TEE_TYPE_ECDH_KEYPAIR:
+               ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
+                       ECC_PRIVATE_ATTRIBUTES, ECC_PRIVATE_ATTRIBUTES_SIZE, decKeyHndl);
+               break;
+       case TEE_TYPE_ECDSA_PUBLIC_KEY:
+       case TEE_TYPE_ECDH_PUBLIC_KEY:
+               ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
+                       ECC_PUBLIC_ATTRIBUTES, ECC_PUBLIC_ATTRIBUTES_SIZE, decKeyHndl);
+               break;
        default:
                LOG("Invalid object type provided for decrypted key creation");
                ret = TEE_ERROR_BAD_PARAMETERS;
@@ -906,7 +1032,7 @@ TEE_Result KM_CreateOperation(TEE_ObjectHandle op_key_hndl, uint32_t algo,
        TEE_GetObjectInfo(op_key_hndl, &info);
 
        bits = KM_ObjectSizeBits(&info);
-       LOGD("Operation key size: %d alg: %x", bits, algo);
+       LOGD("Operation key size: %d alg: %x mode: %x", bits, algo, mode);
        ret = TEE_AllocateOperation(hndl, algo, mode, bits);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AllocateOperation has failed with=%x.", ret);
index 39a612362a5a531bc115871edac464874e29984b..972648ca3ae576b7ff6fecf538834ac9ddc5d1b9 100644 (file)
@@ -168,6 +168,11 @@ TEE_Result TA_InvokeCommandEntryPoint(
                ret = KM_ExecCmdGenerateDSAKey(param);
                break;
        }
+       case CMD_GENERATE_EC_KEYPAIR: {
+               LOGD("!!! Generating EC key pair !!!");
+               ret = KM_ExecCmdGenerateECKey(param);
+               break;
+       }
        default: {
                LOG("Unknown commandID=%d.", commandID);
                ret = TEE_ERROR_BAD_PARAMETERS;