Implement ECDSA import 05/318405/5
authorJakub Wlostowski <j.wlostowski@samsung.com>
Fri, 27 Sep 2024 11:00:54 +0000 (13:00 +0200)
committerJakub Wlostowski <j.wlostowski@samsung.com>
Tue, 8 Oct 2024 08:48:12 +0000 (10:48 +0200)
Change-Id: Ib0a264b992bb3a105dd47ad02a614663ee16755f

ta/include/der_parse.h
ta/include/internal.h
ta/src/der_parse.c
ta/src/internal.c

index e845ba9577e1aed37be59a47bb5f9d371887deda..f9ac78e1c8b572e71149dba66c1e936d60feb417 100644 (file)
@@ -35,6 +35,7 @@ TEE_Result derParseAsymKey(const uint8_t *in, size_t inSize, DerData out[], size
 
 TEE_Result ecPublicToDer(const uint32_t curve, const DerData *x, const DerData *y, DerData *out);
 TEE_Result derToEcPublic(const DerData *in, uint32_t *curve, DerData *x, DerData *y);
+TEE_Result derToEcPrivate(const DerData *in, uint32_t *curve, DerData *prv, DerData *x, DerData *y);
 
 TEE_Result rsaPublicToDer(const DerData *modulus, const DerData *publicExponent, DerData *out);
 TEE_Result derToRsaPublic(const DerData *in, DerData *modulus, DerData *publicExponent);
index 04e8b73b37c0af3c13ed54a3df25c17310eec0af..5e03571b5b4254a1e7bdfcc011c058b3755749fb 100644 (file)
@@ -107,8 +107,9 @@ TEE_Result KM_PublickeyToDer(uint32_t obj_type, TEE_ObjectHandle keyHndl, KM_Bin
 
 TEE_Result KM_EcpublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der);
 
-TEE_Result KM_DerToEcpublic(void *data, uint32_t data_size, uint32_t key_type,
-                                                               TEE_ObjectHandle *decKeyHndl);
+TEE_Result KM_DerToEcpublic(void *data, uint32_t data_size, TEE_ObjectHandle *decKeyHndl);
+
+TEE_Result KM_DerToEcprivate(void *data, uint32_t data_size, TEE_ObjectHandle *decKeyHndl);
 
 TEE_Result KM_RsapublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der);
 
index c523f312351bb59184e4596d4ef6c9ed2d4b2474..549b84d592134e5ac2155a0a3728dfba0f7bba30 100644 (file)
@@ -41,6 +41,8 @@ enum {
        TAG_OCTET_STRING = 0x04,
        TAG_NULL = 0x05,
        TAG_OID = 0x06,
+       TAG_PARAMS = 0xA0,
+       TAG_PUB_KEY = 0xA1,
        TAG_SEQUENCE = 0x30,
 };
 
@@ -238,6 +240,8 @@ static int checkTagLength(const uint8_t *der, size_t remaining_len, size_t *len)
                der[offset] != TAG_OCTET_STRING &&
                der[offset] != TAG_NULL &&
                der[offset] != TAG_OID &&
+               der[offset] != TAG_PARAMS &&
+               der[offset] != TAG_PUB_KEY &&
                der[offset] != TAG_SEQUENCE  )
                return -1;
        offset++;
@@ -362,8 +366,10 @@ static TEE_Result OidToCurve(const uint8_t *binary, const size_t binLen, uint32_
                *curve = TEE_ECC_CURVE_NIST_P256;
        else if(binLen == sizeof(OID_SECP384R1) && memcmp(binary, OID_SECP384R1, binLen) == 0 )
                *curve = TEE_ECC_CURVE_NIST_P384;
-       else
+       else {
+               LOG("EC not supported by tz-backend");
                return TEE_ERROR_GENERIC;
+       }
        return TEE_SUCCESS;
 }
 
@@ -515,6 +521,106 @@ TEE_Result parseDerToElems(const DerData *in,
        return ret;
 }
 
+// Specification : https://www.rfc-editor.org/rfc/rfc5915
+// ECPrivateKey ::= SEQUENCE {
+//     version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+//     privateKey     OCTET STRING,                                                            <-- bitStrPrivate
+//     parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,          <-- algoParam
+//     publicKey  [1] BIT STRING OPTIONAL                                                      <-- bitStrPublic
+// }
+TEE_Result parseDerToElemsEcPriv(const DerData *in,
+                                                            DerData *algoParam,
+                                                            DerData *bitStrPrivate,
+                                                            DerData *bitStrPublic)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       int offset = 0, offset_increase = 0;
+       size_t tmp_len = 0;
+       uint8_t *der = in->data;
+       size_t der_len = in->size;
+
+       // Initialize
+       algoParam->data = NULL;
+       algoParam->size = 0;
+       bitStrPrivate->data = NULL;
+       bitStrPrivate->size = 0;
+       bitStrPublic->data = NULL;
+       bitStrPublic->size = 0;
+
+       // Outermost Tag & Length : Sequence
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0) {
+               LOG("Incorrect DER format");
+               return TEE_ERROR_GENERIC;
+       }
+       offset += offset_increase; // Tag + Length
+
+       // Omit Version Integer
+       offset += 3;
+
+       // Private key
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0) {
+               LOG("Failed getting private key value");
+               return TEE_ERROR_GENERIC;
+       }
+       offset += offset_increase; // Tag + Length
+
+       bitStrPrivate->data = der + offset;
+       bitStrPrivate->size = tmp_len;
+
+       offset += bitStrPrivate->size; // Size
+
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0) {
+               LOG("Failed parsing params tag");
+               return TEE_ERROR_GENERIC;
+       }
+       offset += offset_increase; // Tag + Length
+
+       // Algo Param
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0) {
+               LOG("Failed getting algortihm parameters");
+               return TEE_ERROR_GENERIC;
+       }
+       offset += offset_increase; // Tag + Length
+
+       algoParam->data = der + offset;
+       algoParam->size = tmp_len;
+
+       offset += algoParam->size; // Size
+
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0) {
+               LOG("Failed parsing public key tag");
+               return TEE_ERROR_GENERIC;
+       }
+       offset += offset_increase; // Tag + Length
+
+       // Second Inner Tag & Length : Bit String
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0) {
+               LOG("Failed getting public key value");
+               return TEE_ERROR_GENERIC;
+       }
+       offset += offset_increase; // Tag + Length
+
+       // Check Leading Zero in bit string (number of unused bits at the end)
+       if(*(der + offset) != 0x00) {
+               LOG("Expected 0 unused bits. Got: %d", *(der + offset));
+               return TEE_ERROR_GENERIC;
+       }
+       ++offset;
+       --tmp_len; // excluding leading 0x00.
+
+       // Public key
+       bitStrPublic->data = der + offset;
+       bitStrPublic->size = tmp_len;
+
+       return ret;
+}
+
 // Specification : https://tools.ietf.org/html/rfc5480
 // SubjectPublicKeyInfo  ::=  SEQUENCE  {
 //      algorithm               AlgorithmIdentifier,
@@ -699,6 +805,55 @@ TEE_Result derToEcPublic(const DerData *in, uint32_t *curve, DerData *x, DerData
        return ret;
 }
 
+TEE_Result derToEcPrivate(const DerData *in, uint32_t *curve, DerData *prv, DerData *x, DerData *y)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       int offset = 0;
+       size_t len_xy = 0;
+
+       DerData algoParam = {0x00, };
+       DerData publicKey = {0x00, };
+
+       // Initialize
+       prv->data = NULL;
+       prv->size = 0;
+       x->data = NULL;
+       x->size = 0;
+       y->data = NULL;
+       y->size = 0;
+
+       ret = parseDerToElemsEcPriv(in, &algoParam, prv, &publicKey);
+       if(ret != TEE_SUCCESS) {
+               LOG("Failed parsing EC private key");
+               return TEE_ERROR_GENERIC;
+       }
+
+       // Get TEE CURVE
+       ret = OidToCurve(algoParam.data, algoParam.size, curve);
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed parsing OID to curve value");
+               return TEE_ERROR_GENERIC;
+       }
+
+       // Check public key format
+       if (publicKey.data[offset++] != 0x04) { // Uncompressed public key
+               LOG("Public key should be in uncompressed format");
+               return TEE_ERROR_GENERIC;
+       }
+
+       len_xy = (publicKey.size - 1) / 2;
+       // Set X
+       x->data = publicKey.data + offset;
+       x->size = len_xy;
+       offset += len_xy;
+       // Set Y
+       y->data = publicKey.data + offset;
+       y->size = len_xy;
+       offset += len_xy;
+
+       return ret;
+}
+
 // -- RSA PK Algorithm and Key
 // algorithm AlgorithmIdentifier:
 //      algorithm:
index 9d389b2777973ef6abc2da36d2fa792486ab0bf7..69ee39c183e5f5ccbd06c30558a1c0a4710a0032 100644 (file)
@@ -208,6 +208,10 @@ TEE_Result KM_CreateAsymKey(tz_data_type type, KM_BinaryData der, TEE_ObjectHand
                attrCount = RSA_PRIVATE_ATTRIBUTES_SIZE;
                attrId = RSA_PRIVATE_ATTRIBUTES;
                break;
+       case TYPE_AKEY_PUBLIC_EC:
+               return KM_DerToEcpublic(der.data, der.data_size, hndl);
+       case TYPE_AKEY_PRIVATE_EC:
+               return KM_DerToEcprivate(der.data, der.data_size, hndl);
        default:
                LOG("Data type(tz_algo_type=%u) not supported by import methods", type);
                return TEE_ERROR_BAD_PARAMETERS;
@@ -808,8 +812,7 @@ clean:
        return ret;
 }
 
-TEE_Result KM_DerToEcpublic(void *data, uint32_t data_size, uint32_t key_type,
-                                                               TEE_ObjectHandle *decKeyHndl)
+TEE_Result KM_DerToEcpublic(void *data, uint32_t data_size, TEE_ObjectHandle *decKeyHndl)
 {
        TEE_Result ret = TEE_SUCCESS;
        uint32_t b = 0, curve = 0;
@@ -833,7 +836,41 @@ TEE_Result KM_DerToEcpublic(void *data, uint32_t data_size, uint32_t key_type,
                return ret;
        }
 
-       ret = KM_CreateTransientObject(key_type, maxObjectSizeBits, attr, sizeof(attr)/sizeof(*attr), decKeyHndl);
+       ret = KM_CreateTransientObject(TEE_TYPE_ECDSA_PUBLIC_KEY, maxObjectSizeBits, attr, sizeof(attr)/sizeof(*attr), decKeyHndl);
+       if(ret != TEE_SUCCESS) {
+               LOG("Failed to create a transient object. ret=%x", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+TEE_Result KM_DerToEcprivate(void *data, uint32_t data_size, TEE_ObjectHandle *decKeyHndl)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       uint32_t b = 0, curve = 0;
+       DerData x = {NULL, 0}, y = {NULL, 0}, prv = {NULL, 0}, der = {data, data_size};
+       TEE_Attribute attr[4];
+       uint32_t maxObjectSizeBits = 0;
+
+       ret = derToEcPrivate(&der, &curve, &prv, &x, &y);
+       if(ret != TEE_SUCCESS) {
+               LOG("Failed to get Data from DER");
+               return ret;
+       }
+
+       KM_InitValueAttribute(&attr[0], TEE_ATTR_ECC_CURVE, curve, b);
+       KM_InitRefAttribute(&attr[1], TEE_ATTR_ECC_PRIVATE_VALUE, prv.data, prv.size);
+       KM_InitRefAttribute(&attr[2], TEE_ATTR_ECC_PUBLIC_VALUE_X, x.data, x.size);
+       KM_InitRefAttribute(&attr[3], TEE_ATTR_ECC_PUBLIC_VALUE_Y, y.data, y.size);
+
+       ret = KM_EccCurveToKeyBitSize(curve, &maxObjectSizeBits);
+       if(ret != TEE_SUCCESS) {
+               LOG("Failed to get key bits size from curve. curve=%x", curve);
+               return ret;
+       }
+
+       ret = KM_CreateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, maxObjectSizeBits, attr, sizeof(attr)/sizeof(*attr), decKeyHndl);
        if(ret != TEE_SUCCESS) {
                LOG("Failed to create a transient object. ret=%x", ret);
                return ret;