Support exporting RSA public key from TZ 55/306655/3
authorDongsun Lee <ds73.lee@samsung.com>
Sat, 24 Feb 2024 02:16:05 +0000 (11:16 +0900)
committerDongsun Lee <ds73.lee@samsung.com>
Mon, 26 Feb 2024 04:15:32 +0000 (13:15 +0900)
Change-Id: I543834b72106cb77a6bb891c92f5b4f0f467c8e5

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

index ca9e77423ce7266d415ae3bb52c744a84774f67c..e845ba9577e1aed37be59a47bb5f9d371887deda 100644 (file)
@@ -33,6 +33,13 @@ typedef struct {
  */
 TEE_Result derParseAsymKey(const uint8_t *in, size_t inSize, DerData out[], size_t outSize);
 
-TEE_Result ecPublicToDer(const uint32_t curve, DerData *x, DerData *y, DerData *out);
-
+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 rsaPublicToDer(const DerData *modulus, const DerData *publicExponent, DerData *out);
+TEE_Result derToRsaPublic(const DerData *in, DerData *modulus, DerData *publicExponent);
+
+TEE_Result dsaPublicToDer(const DerData *prime, const DerData *subPrime, const DerData *base,
+                                                       const DerData *publicValue, DerData *out);
+TEE_Result derToDsaPublic(const DerData *in, DerData *prime, DerData *subPrime, DerData *base,
+                                                       DerData *publicValue);
index 483d117a766d260d87be37e7daea7610b10e2bc0..04e8b73b37c0af3c13ed54a3df25c17310eec0af 100644 (file)
@@ -103,10 +103,17 @@ void KM_DestroyData(void *objId, uint32_t objId_size);
 
 TEE_Result KM_EccCurveToKeyBitSize(uint32_t curve, uint32_t *bitsize);
 
+TEE_Result KM_PublickeyToDer(uint32_t obj_type, TEE_ObjectHandle keyHndl, KM_BinaryData *der);
+
 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_RsapublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der);
+
+TEE_Result KM_DsapublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der);
+
 TEE_Result KM_GetValueAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr);
 
 TEE_Result KM_GetBufferAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr);
index e572ae9a93e74490da0531339c1ef289fa667656..c523f312351bb59184e4596d4ef6c9ed2d4b2474 100644 (file)
@@ -13,6 +13,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
+
 #include <assert.h>
 #include <stdbool.h>
 #include <string.h>
@@ -38,6 +39,7 @@ enum {
        TAG_INT = 0x02,
        TAG_BIT_STRING = 0x03,
        TAG_OCTET_STRING = 0x04,
+       TAG_NULL = 0x05,
        TAG_OID = 0x06,
        TAG_SEQUENCE = 0x30,
 };
@@ -152,11 +154,19 @@ fail:
 
 // https://datatracker.ietf.org/doc/html/rfc5480#section-2.1.1.1
 // https://learn.microsoft.com/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN
-static const char OID_SECP192R1[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01};
-static const char OID_SECP256R1[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07};
-static const char OID_SECP384R1[5] = {0x2B, 0x81, 0x04, 0x00, 0x22};
+static const unsigned char OID_SECP192R1[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01};
+static const unsigned char OID_SECP256R1[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07};
+static const unsigned char OID_SECP384R1[5] = {0x2B, 0x81, 0x04, 0x00, 0x22};
+
+static const unsigned char ALGO_ID_ECPUBLIC[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01};
+// OID DER Encoder : https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
+// https://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
+// OID rsaEncryption(1.2.840.113549.1.1.1)
+static const unsigned char ALGO_ID_RSAENCRYPTION[9] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 0x01, 0x01};
+// https://oid-rep.orange-labs.fr/get/1.2.840.10040.4.1
+// OID id-dsa(1.2.840.10040.4.1)
+static const unsigned char ALGO_ID_ID_DSA[7] = {0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01};
 
-static const char ALGO_ID_ECPUBLIC[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01};
 
 static size_t toOidSize(uint32_t tee_ec_curve)
 {
@@ -200,7 +210,7 @@ static size_t lenToBinary(size_t len, uint8_t *binary)
        return 0;
 }
 
-static size_t binaryToLen(uint8_t *binary, size_t *len)
+static size_t binaryToLen(const uint8_t *binary, size_t *len)
 {
        uint8_t width = 0;
        if(*binary <= 0x7F) {
@@ -210,7 +220,7 @@ static size_t binaryToLen(uint8_t *binary, size_t *len)
                width = 0x7F & *binary;
                switch(width) {
                case 1:
-                   *len = *(binary+1);
+                       *len = *(binary+1);
                        return 2;
                case 2:
                        *len = ((*(binary+1)) << 8) + (*(binary+2));
@@ -220,6 +230,113 @@ static size_t binaryToLen(uint8_t *binary, size_t *len)
        return 0;
 }
 
+static int checkTagLength(const uint8_t *der, size_t remaining_len, size_t *len)
+{
+       int offset = 0, len_width = 0;
+       if (der[offset] != TAG_INT &&
+               der[offset] != TAG_BIT_STRING &&
+               der[offset] != TAG_OCTET_STRING &&
+               der[offset] != TAG_NULL &&
+               der[offset] != TAG_OID &&
+               der[offset] != TAG_SEQUENCE  )
+               return -1;
+       offset++;
+       len_width = binaryToLen(der+offset, len);
+       if (len_width < 0)
+               return -1;
+       offset += len_width;
+       if ((offset + *len) > remaining_len)
+               return -1;
+       return offset;
+}
+
+static int checkAlgoId(const uint8_t *der, size_t remaining_len,
+                                                       const uint8_t* algo_id, size_t algo_id_len,
+                                                       bool *same)
+{
+       int offset = 0, offset_increase = 0;
+       size_t tmp_len = 0;
+       offset_increase = checkTagLength(der + offset, remaining_len, &tmp_len);
+       if (offset_increase < 0) {
+               *same = false;
+               return -1;
+       }
+       offset += offset_increase;
+
+       if ((memcmp(der +offset, algo_id, algo_id_len) != 0)
+                       || tmp_len != algo_id_len)
+               *same = false;
+
+       offset += tmp_len;
+       *same = true;
+
+       return offset;
+}
+
+
+static bool needsAddLeadingZero(const DerData *integer) {
+       // Need to add 0x00 to the head of integer not to make integer negative.
+       return (integer->data[0] >= 0x80);
+}
+static size_t getIntegerValueLength(const DerData *integer)
+{
+       if(needsAddLeadingZero(integer)) {
+               return 1 + integer->size;
+       } else {
+               return integer->size;
+       }
+}
+static size_t getIntegerTotalLenght(const DerData *integer)
+{
+       size_t total_len = 1 + toLenSize(getIntegerValueLength(integer)) + getIntegerValueLength(integer);
+       return total_len;
+};
+static size_t integerValueToBinary(const DerData *integer, uint8_t *binary)
+{
+       size_t offset = 0;
+       if(needsAddLeadingZero(integer))
+               binary[offset++] = 0x00;
+
+       memcpy(binary + offset, integer->data, integer->size);
+       offset += integer->size;
+       return offset;
+}
+static size_t integerDerToBinary(const DerData *der, uint8_t *binary)
+{
+       size_t offset = 0;
+       size_t tmp_len = 0;
+
+       binary[offset++] = TAG_INT;
+       tmp_len = lenToBinary(getIntegerValueLength(der), binary + offset);
+       offset += tmp_len;
+       tmp_len = integerValueToBinary(der, binary + offset);
+       offset += tmp_len;
+
+       return offset;
+}
+static size_t parseInteger(const uint8_t *der, const size_t der_len, DerData *integer)
+{
+       int offset = 0;
+       int offset_increase = 0;
+       size_t tmp_len = 0;
+
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return 0;
+       if(*(der + offset) == 0x00) {
+               ++offset; // Ignore leading 0x00
+               --tmp_len;
+       }
+       // Set publicExponent
+       integer->data = (uint8_t *) der + offset;
+       integer->size = tmp_len;
+       offset += tmp_len;
+
+       return offset;
+}
+
+
 static TEE_Result curveToOid(uint32_t tee_ec_curve, uint8_t *binary)
 {
        switch(tee_ec_curve) {
@@ -252,75 +369,210 @@ static TEE_Result OidToCurve(const uint8_t *binary, const size_t binLen, uint32_
 
 // Specification : https://tools.ietf.org/html/rfc5480
 // SubjectPublicKeyInfo  ::=  SEQUENCE  {
-//     algorithm         AlgorithmIdentifier,
-//     subjectPublicKey  BIT STRING
+//      algorithm               AlgorithmIdentifier,
+//      subjectPublicKey  BIT STRING                                     <-- bitStrNoZero : No leading 0x00
 // }
 // AlgorithmIdentifier  ::=  SEQUENCE  {
-//     algorithm   OBJECT IDENTIFIER,
-//     parameters  ANY DEFINED BY algorithm OPTIONAL
+//      algorithm   OBJECT IDENTIFIER,                                 <-- algoOid
+//      parameters  ANY DEFINED BY algorithm OPTIONAL   <-- algoParam
 // }
-// subjectPublicKey - ECPoint ::= OCTET STRING
-//     https://www.secg.org/SEC1-Ver-1.0.pdf p10~p11
-// [Example]
-// https://stackoverflow.com/questions/56772982/build-pem-file-by-having-ec-public-key-coordinates
-// // SubjectPublicKeyInfo
-// 30 XA
-//    // AlgorithmIdentifier
-//    30 XB
-//       // AlgorithmIdentifier.id (id-ecPublicKey (1.2.840.10045.2.1))
-//       06 07 2A 86 48 CE 3D 02 01
-//       // AlgorithmIdentifier.parameters, using the named curve id (1.2.840.10045.3.1.7)
-//       06 08 2A 86 48 CE 3D 03 01 07
-//    // SubjectPublicKeyInfo.subjectPublicKey
-//    03 XC 00
-//       // Uncompressed public key
-//       04
-//       // Q.X
-//       81 01 EC E4 74 64 A6 EA D7 0C F6 9A 6E 2B D3 D8
-//       86 91 A3 26 2D 22 CB A4 F7 63 5E AF F2 66 80 A8
-//       // Q.Y
-//       D8 A1 2B A6 1D 59 92 35 F6 7D 9C B4 D5 8F 17 83
-//       D3 CA 43 E7 8F 0A 5A BA A6 24 07 99 36 C0 C3 A9
-
-TEE_Result ecPublicToDer(const uint32_t curve, DerData *x, DerData *y, DerData *out)
+TEE_Result pubkeyElemsToDer(const DerData *algoOid,
+                                                       const DerData *algoParam,
+                                                       const DerData *bitStrNoZero, // Without Leading 0x00
+                                                       DerData *out)
 {
        TEE_Result ret = TEE_SUCCESS;
-       size_t curve_oid_len = toOidSize(curve);
+       uint8_t *der = NULL;
        size_t offset = 0;
        size_t tmp_len = 0;
-       uint8_t *der = NULL;
-       size_t len_xy = 1 + 1 + x->size + y->size; //  1(00: unused) + 1(04:uncompressed format)
-       size_t len_algo = 1 + toLenSize(sizeof(ALGO_ID_ECPUBLIC)) + sizeof(ALGO_ID_ECPUBLIC)
-                                       + 1 + toLenSize(curve_oid_len) + curve_oid_len;
-       size_t len_total =  1 + toLenSize(len_algo) + len_algo +
-                                               1 + toLenSize(len_xy) + len_xy;
 
-       der = (uint8_t *) TEE_Malloc( 1 + toLenSize(len_total) + len_total, 0); // 1: TAG Size, + Length Size + len_total: Total Body Size
+       size_t len_d1_algo_value = algoOid->size + algoParam->size;
+       size_t len_d1_algo_total = 1 + toLenSize(len_d1_algo_value) + len_d1_algo_value;
+       size_t len_d1_pub_total = 1 + toLenSize(1 + bitStrNoZero->size) + (1 + bitStrNoZero->size);
+       size_t len_d0_value = len_d1_algo_total + len_d1_pub_total;
+       size_t len_d0_total = 1 + toLenSize(len_d0_value) + len_d0_value;
+
+       der = (uint8_t *) TEE_Malloc(len_d0_total, 0);
        if(der == NULL) {
                ret = TEE_ERROR_OUT_OF_MEMORY;
                goto clean;
        }
 
-       if (curve_oid_len == 0) {
+       // Tag & Lenght for depth 0
+       der[offset++] = TAG_SEQUENCE;
+       tmp_len = lenToBinary(len_d0_value, der + offset);
+       if (tmp_len == 0) {
                ret = TEE_ERROR_GENERIC;
                goto clean;
        }
+       offset += tmp_len;
 
+       // Body for depth 0 : Sequence of algorithm and subjectPublicKey
+
+       // Tag & Length for algorithm(depth 1)
        der[offset++] = TAG_SEQUENCE;
-       tmp_len = lenToBinary(len_total, der + offset);
+       tmp_len = lenToBinary(len_d1_algo_value, der + offset);
        if (tmp_len == 0) {
                ret = TEE_ERROR_GENERIC;
                goto clean;
        }
        offset += tmp_len;
+       // Value for algorithm(depth 2)
+       memcpy(der + offset, algoOid->data, algoOid->size);
+       offset += algoOid->size;
+       memcpy(der + offset, algoParam->data, algoParam->size);
+       offset += algoParam->size;
 
-       der[offset++] = TAG_SEQUENCE;
-       tmp_len = lenToBinary(len_algo, der + offset);
+       // Tag & Length for subjectPublicKey(depth 1)
+       der[offset++] = TAG_BIT_STRING;
+       tmp_len = lenToBinary(1 + bitStrNoZero->size, der + offset);
        if (tmp_len == 0) {
                ret = TEE_ERROR_GENERIC;
                goto clean;
        }
        offset += tmp_len;
+       // Value for subjectPublicKey(depth 2)
+       der[offset++] = 0x00; // leading zero in bit string
+       memcpy(der + offset, bitStrNoZero->data, bitStrNoZero->size);
+       offset += bitStrNoZero->size;
+
+       // Set output
+       out->data = der;
+       out->size = offset;
+clean:
+       if(ret != TEE_SUCCESS)
+               TEE_Free(der);
+
+       return ret;
+}
+
+TEE_Result parseDerToElems(const DerData *in,
+                                                       DerData *algoOid,
+                                                       DerData *algoParam,
+                                                       DerData *bitStrNoZero)
+{
+       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
+       algoOid->data = NULL;
+       algoOid->size = 0;
+       algoParam->data = NULL;
+       algoParam->size = 0;
+       bitStrNoZero->data = NULL;
+       bitStrNoZero->size = 0;
+
+       // Outermost Tag & Length : Sequence
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+
+       // First Inner Tag & Length : Sequence
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+
+       // Algorithm Identifier OID
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       algoOid->data = der + offset;
+       algoOid->size = offset_increase +tmp_len;
+
+       offset += algoOid->size; // Tag + Length + Value
+
+       // Algo Param
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       algoParam->data = der + offset;
+       algoParam->size = offset_increase +tmp_len;
+
+       offset += algoParam->size; // Tag + Length + Value
+
+       // Seeond Inner Tag & Length : Bit String
+       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
+       offset += offset_increase; // Tag + Length
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       // Check Leading Zero in bit string
+       if( *(der+offset) != 0x00)
+               return TEE_ERROR_GENERIC;
+       ++offset;
+       --tmp_len; // excluding leading 0x00.
+
+       // bitStrNoZero
+       bitStrNoZero->data = der + offset;
+       bitStrNoZero->size = tmp_len;
+
+       offset += bitStrNoZero->size; // Value
+
+       return ret;
+}
+
+// Specification : https://tools.ietf.org/html/rfc5480
+// SubjectPublicKeyInfo  ::=  SEQUENCE  {
+//      algorithm               AlgorithmIdentifier,
+//      subjectPublicKey  BIT STRING
+// }
+// AlgorithmIdentifier  ::=  SEQUENCE  {
+//      algorithm   OBJECT IDENTIFIER,
+//      parameters  ANY DEFINED BY algorithm OPTIONAL
+// }
+// subjectPublicKey - ECPoint ::= OCTET STRING
+//      https://www.secg.org/SEC1-Ver-1.0.pdf p10~p11
+// [Example]
+// https://stackoverflow.com/questions/56772982/build-pem-file-by-having-ec-public-key-coordinates
+// // SubjectPublicKeyInfo
+// 30 XA
+//     // AlgorithmIdentifier
+//     30 XB
+//        // AlgorithmIdentifier.id (id-ecPublicKey (1.2.840.10045.2.1))
+//        06 07 2A 86 48 CE 3D 02 01
+//        // AlgorithmIdentifier.parameters, using the named curve id (1.2.840.10045.3.1.7)
+//        06 08 2A 86 48 CE 3D 03 01 07
+//     // SubjectPublicKeyInfo.subjectPublicKey
+//     03 XC 00
+//        // Uncompressed public key
+//        04
+//        // Q.X
+//        81 01 EC E4 74 64 A6 EA D7 0C F6 9A 6E 2B D3 D8
+//        86 91 A3 26 2D 22 CB A4 F7 63 5E AF F2 66 80 A8
+//        // Q.Y
+//        D8 A1 2B A6 1D 59 92 35 F6 7D 9C B4 D5 8F 17 83
+//        D3 CA 43 E7 8F 0A 5A BA A6 24 07 99 36 C0 C3 A9
+
+TEE_Result ecPublicToDer(const uint32_t curve, const DerData *x, const DerData *y, DerData *out)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       size_t curve_oid_len = toOidSize(curve);
+       DerData algoOid = {0x00, };
+       DerData algoParam = {0x00, };
+       DerData bitStrNoZero = {0x00, };
+       size_t offset = 0;
+       size_t tmp_len = 0;
+       size_t len_algoOid_total = 0;
+       size_t len_algo_param_total = 0;
+       size_t len_xy = 0;
+       uint8_t *der = NULL;
+
+       // Generate algoOid DER.
+       len_algoOid_total = 1 + toLenSize(sizeof(ALGO_ID_ECPUBLIC)) + sizeof(ALGO_ID_ECPUBLIC);
+       algoOid.data = (uint8_t *) TEE_Malloc(len_algoOid_total, 0);
+       if(algoOid.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       algoOid.size = len_algoOid_total;
+
+       der = algoOid.data;
+       offset = 0;
 
        der[offset++] = TAG_OID;
        tmp_len = lenToBinary(sizeof(ALGO_ID_ECPUBLIC), der + offset);
@@ -332,6 +584,18 @@ TEE_Result ecPublicToDer(const uint32_t curve, DerData *x, DerData *y, DerData *
        memcpy(der + offset, ALGO_ID_ECPUBLIC, sizeof(ALGO_ID_ECPUBLIC));
        offset += sizeof(ALGO_ID_ECPUBLIC);
 
+       // Generate algoParam DER.
+       len_algo_param_total = 1 + toLenSize(curve_oid_len) + curve_oid_len;
+       algoParam.data = (uint8_t *) TEE_Malloc(len_algo_param_total, 0);
+       if(algoParam.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       algoParam.size = len_algo_param_total;
+
+       der = algoParam.data;
+       offset = 0;
+
        der[offset++] = TAG_OID;
        tmp_len = lenToBinary(curve_oid_len, der + offset);
        if (tmp_len == 0) {
@@ -342,50 +606,46 @@ TEE_Result ecPublicToDer(const uint32_t curve, DerData *x, DerData *y, DerData *
        curveToOid(curve, der + offset);
        offset += curve_oid_len;
 
-       der[offset++] = TAG_BIT_STRING;
-       tmp_len = lenToBinary(len_xy, der + offset);
-       if (tmp_len == 0) {
-               ret = TEE_ERROR_GENERIC;
+       // Generate bitStrNoZero DER.
+       len_xy = 1 + x->size + y->size; //  1(04:uncompressed format)
+       bitStrNoZero.data = (uint8_t *) TEE_Malloc(len_xy, 0);
+       if(bitStrNoZero.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
                goto clean;
        }
-       offset += tmp_len;
-       der[offset++] = 0x00; // dummy 0x00
+       bitStrNoZero.size = len_xy;
+
+       der = bitStrNoZero.data;
+       offset = 0;
+
        der[offset++] = 0x04; // Uncompressed public key
        memcpy(der + offset, x->data, x->size);
        offset += x->size;
        memcpy(der + offset, y->data, y->size);
        offset += y->size;
 
-       out->data = der;
-       out->size = offset;
-
+       // Generate the entire DER.
+       ret = pubkeyElemsToDer(&algoOid, &algoParam, &bitStrNoZero, out);
 clean:
-       if(ret != TEE_SUCCESS)
-               TEE_Free(der);
+       TEE_Free(algoOid.data);
+       TEE_Free(algoParam.data);
+       TEE_Free(bitStrNoZero.data);
 
        return ret;
 }
 
-static size_t checkTagLength(uint8_t *der, size_t remaining_len, size_t *len)
-{
-       size_t offset = 0, len_width = 0;
-       if (der[offset++] != TAG_SEQUENCE)
-               return 0;
-       len_width = binaryToLen(der+offset, len);
-       if (len_width == 0)
-               return 0;
-       offset += len_width;
-       if ((offset + *len) > remaining_len)
-               return 0;
-       return offset;
-}
-
 TEE_Result derToEcPublic(const DerData *in, uint32_t *curve, DerData *x, DerData *y)
 {
        TEE_Result ret = TEE_SUCCESS;
-       size_t offset = 0, tmp_len = 0, len_xy = 0, offset_increase = 0;
-       uint8_t *der = in->data;
-       size_t der_len = in->size;
+       int offset = 0, offset_increase = 0;
+       size_t tmp_len = 0;
+       uint8_t *der = NULL;
+       size_t der_len = 0, len_xy = 0;
+       bool same_algo_id = false;
+
+       DerData algoOid = {0x00, };
+       DerData algoParam = {0x00, };
+       DerData publicKey = {0x00, };
 
        // Initialize
        x->data = NULL;
@@ -393,50 +653,40 @@ TEE_Result derToEcPublic(const DerData *in, uint32_t *curve, DerData *x, DerData
        y->data = NULL;
        y->size = 0;
 
-       // Outermost Tag & Length
-       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
-       offset += offset_increase;
-       if(offset_increase == 0)
+       ret = parseDerToElems(in, &algoOid, &algoParam, &publicKey);
+       if(ret != TEE_SUCCESS)
                return TEE_ERROR_GENERIC;
 
-       // First Inner Tag & Length
-       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
-       offset += offset_increase;
-       if(offset_increase == 0)
+       // Check Algorithm Identifier
+       offset_increase = checkAlgoId(algoOid.data + offset, algoOid.size - offset,
+                                                                       ALGO_ID_ECPUBLIC, sizeof(ALGO_ID_ECPUBLIC),
+                                                                       &same_algo_id);
+       if(offset_increase < 0 || same_algo_id != true)
                return TEE_ERROR_GENERIC;
 
-       // Tag & Length of Algorithm Identifier OID
+       offset = 0;
+       offset_increase = 0;
+       der = algoParam.data;
+       der_len = algoParam.size;
+       // Parse algoParam for curve
        offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
        offset += offset_increase;
-       if(offset_increase == 0)
-               return TEE_ERROR_GENERIC;
-       // Check Algorithm Identifier for EC Public Key
-       if (memcmp(der+offset, ALGO_ID_ECPUBLIC, sizeof(ALGO_ID_ECPUBLIC) != 0) ||
-               tmp_len != sizeof(ALGO_ID_ECPUBLIC))
-               return TEE_ERROR_GENERIC;
-       offset += sizeof(ALGO_ID_ECPUBLIC);
-
-       // Tag & Length of Curve OID
-       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
-       offset += offset_increase;
-       if(offset_increase == 0)
+       if(offset_increase < 0)
                return TEE_ERROR_GENERIC;
        // Get TEE CURVE
        ret = OidToCurve(der+offset, tmp_len, curve);
        if (ret != TEE_SUCCESS)
                return TEE_ERROR_GENERIC;
 
-       // Second Inner Tag & Length
-       offset_increase = checkTagLength(der + offset, der_len - offset, &tmp_len);
-       offset += offset_increase;
-       if(offset_increase == 0)
-               return TEE_ERROR_GENERIC;
-
-       offset ++; // Skip unused 0x00
+       offset = 0;
+       offset_increase = 0;
+       der = publicKey.data;
+       der_len = publicKey.size;
+       // Check public key format
        if (der[offset++] != 0x04) // Uncompressed public key
                return TEE_ERROR_GENERIC;
 
-       len_xy = (tmp_len - 2) / 2;
+       len_xy = (der_len - 1) / 2;
        // Set X
        x->data = der + offset;
        x->size = len_xy;
@@ -448,3 +698,394 @@ TEE_Result derToEcPublic(const DerData *in, uint32_t *curve, DerData *x, DerData
 
        return ret;
 }
+
+// -- RSA PK Algorithm and Key
+// algorithm AlgorithmIdentifier:
+//      algorithm:
+//              rsaEncryption OBJECT IDENTIFIER ::= {
+//                      iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 1 }
+//      parameters: NULL ( 05 00 )
+// subjectPublicKey BIT STRING:
+//      RSAPublicKey ::= SEQUENCE {
+//              modulus                 INTEGER, -- n
+//              publicExponent  INTEGER  -- e
+//      }
+// [Example]
+// 30 <== ASN.1 Sequence Tag
+// 81 <== Next Length is 1 byte
+// 9f <== Length : 9f = 159 (300d ~ to end)
+//     30 <== ASN.1 Sequence Tag
+//     0d <== Length 0d=13
+//             06 09 2a864886f70d010101 <== OBJECT :rsaEncryption
+//             05 00
+//     03 <== ASN.1 Bit String Tag
+//     81 <== Next Length is 1 byte
+//     8d <== Length : 8d = 141 (0030 ~ to end).
+//             BitString. The leading byte means the number of bits that are not used at the end byte. Usally 0x00.
+//             00 3081 ~ to end
+//                     30 <== ASN.1 Sequence Tag
+//                     81 <== Next Length is 1 byte
+//                     89 <== Length : 89 = 137 (0281 ~ to end)
+//                             02 <== ASN.1 Integer Tag
+//                             81 <== Next Length is 1 byte
+//                             81 <== Length : 81 = 129 (00c0 ~ 11b5)
+//                                     Integer(Modulus Value)
+//                                     00c0b3dbc9cddcd76dee0bc9bdfa71243c01275fbed37043cc406308f4932d980588bafa3c87cbe8c66dc293d7094f4584814314cffeb30ad9c94c397fa9f2dbae59d048001f8d18ec2748b6c8af6c29c4ee4a22520066b697ea6e834dd23c9a1419b1291875e9c8fa4aecb9a5edccded46396cbcaaa891db48ef3d64d1df311b5
+//                             02 <== ASN.1 Integer Tag
+//                             03 <== Length 03
+//                                     Integer(Exponent Value)
+//                                     010001
+TEE_Result rsaPublicToDer(const DerData *modulus, const DerData *publicExponent, DerData *out)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       DerData algoOid = {0x00, };
+       DerData algoParam = {0x00, }; // Don't need to free algoParam.data.
+       DerData bitStrNoZero = {0x00, };
+       unsigned char nullParam[2] = {0x05, 0x00};
+       size_t offset = 0;
+       size_t tmp_len = 0;
+       size_t len_algoOid_total = 0;
+       size_t len_modulus_total = 0;
+       size_t len_seqinbit_value = 0;
+       size_t len_seqinbit_total = 0;
+       size_t len_pubExp_total = 0;
+       uint8_t *der = NULL;
+
+       // Generate algoOid DER.
+       len_algoOid_total = 1 + toLenSize(sizeof(ALGO_ID_RSAENCRYPTION)) + sizeof(ALGO_ID_RSAENCRYPTION);
+       algoOid.data = (uint8_t *) TEE_Malloc(len_algoOid_total, 0);
+       if(algoOid.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       algoOid.size = len_algoOid_total;
+
+       der = algoOid.data;
+       offset = 0;
+
+       der[offset++] = TAG_OID;
+       tmp_len = lenToBinary(sizeof(ALGO_ID_RSAENCRYPTION), der + offset);
+       if (tmp_len == 0) {
+               ret = TEE_ERROR_GENERIC;
+               goto clean;
+       }
+       offset += tmp_len;
+       memcpy(der + offset, ALGO_ID_RSAENCRYPTION, sizeof(ALGO_ID_RSAENCRYPTION));
+       offset += sizeof(ALGO_ID_RSAENCRYPTION);
+
+       // Set algoParam DER.
+       algoParam.data = nullParam;
+       algoParam.size = sizeof(nullParam);
+
+       // Generate bitStrNoZero DER.
+       len_modulus_total = getIntegerTotalLenght(modulus);
+       len_pubExp_total = getIntegerTotalLenght(publicExponent);
+       len_seqinbit_value = len_modulus_total + len_pubExp_total;
+       len_seqinbit_total = 1 + toLenSize(len_seqinbit_value) + len_seqinbit_value;
+
+       bitStrNoZero.data = (uint8_t *) TEE_Malloc(len_seqinbit_total, 0);
+       if(bitStrNoZero.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       bitStrNoZero.size = len_seqinbit_total;
+
+       der = bitStrNoZero.data;
+       offset = 0;
+
+       // Sequence of module & public exponet
+       der[offset++] = TAG_SEQUENCE;
+       tmp_len = lenToBinary(len_seqinbit_value, der + offset);
+       if (tmp_len == 0) {
+               ret = TEE_ERROR_GENERIC;
+               goto clean;
+       }
+       offset += tmp_len;
+       // Integer of modulus
+       tmp_len = integerDerToBinary(modulus, der + offset);
+       offset += tmp_len;
+       // Integer of public exponent
+       tmp_len = integerDerToBinary(publicExponent, der + offset);
+       offset += tmp_len;
+
+       // Generate the entire DER.
+       ret = pubkeyElemsToDer(&algoOid, &algoParam, &bitStrNoZero, out);
+
+clean:
+       TEE_Free(algoOid.data);
+       TEE_Free(bitStrNoZero.data);
+
+       return ret;
+}
+
+
+TEE_Result derToRsaPublic(const DerData *in, DerData *modulus, DerData *publicExponent)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       int offset = 0, offset_increase = 0;
+       size_t tmp_len = 0;
+       bool same_algo_id = false;
+
+       DerData algoOid = {0x00, };
+       DerData algoParam = {0x00, };
+       DerData publicKey = {0x00, };
+
+       ret = parseDerToElems(in, &algoOid, &algoParam, &publicKey);
+       if(ret != TEE_SUCCESS) {
+               return TEE_ERROR_GENERIC;
+       }
+
+       // Check Algorithm Identifier
+       offset_increase = checkAlgoId(algoOid.data + offset, algoOid.size - offset,
+                                                                       ALGO_ID_RSAENCRYPTION, sizeof(ALGO_ID_RSAENCRYPTION),
+                                                                       &same_algo_id);
+       if(offset_increase < 0 || same_algo_id != true)
+               return TEE_ERROR_GENERIC;
+
+       offset = 0;
+       offset_increase = 0;
+       // Parse PublicKey
+       offset_increase = checkTagLength(publicKey.data + offset, publicKey.size - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+
+       // Parse for modulus
+       offset_increase = checkTagLength(publicKey.data + offset, publicKey.size - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       if(*(publicKey.data + offset) == 0x00) {
+               ++offset; // Ignore leading 0x00
+               --tmp_len;
+       }
+       // Set modulus
+       modulus->data = publicKey.data + offset;
+       modulus->size = tmp_len;
+       offset += tmp_len;
+
+       // Parse for publicExponent
+       offset_increase = checkTagLength(publicKey.data + offset, publicKey.size - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       if(*(publicKey.data + offset) == 0x00) {
+               ++offset; // Ignore leading 0x00
+               --tmp_len;
+       }
+       // Set publicExponent
+       publicExponent->data = publicKey.data + offset;
+       publicExponent->size = tmp_len;
+       offset += tmp_len;
+
+       return ret;
+}
+
+//     -- DSA PK Algorithm, Key, and Parameters
+// algorithm AlgorithmIdentifier:
+//      algorithm:
+//              id-dsa OBJECT IDENTIFIER ::= {
+//                iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }
+//      parameters:
+//              DSS-Parms ::= SEQUENCE {
+//                p  INTEGER,
+//                q  INTEGER,
+//                g  INTEGER
+//              }
+// subjectPublicKey BIT STRING:
+//      DSAPublicKey ::= INTEGER --  public key, y
+// 30 <== ASN.1 Sequence Tag
+// 82 <== Next Length is 2 byte
+// 01be <== Length : 01be = 446 (3082 ~ to end)
+//     30 <== ASN.1 Sequence Tag
+//     82 <== Next Length is 2 byte
+//     0133 <== Length : 0133 = 307 (0607 ~ e4d4)
+//             06 07 2a8648ce380401(OID_id_dsa)
+//             30 <== ASN.1 Sequence Tag
+//             82 <== Next Length is 2 byte
+//             0126 <== Length : 0126 = 294 (0281 ~ e4d4)
+//                     // https://datatracker.ietf.org/doc/html/rfc5480#section-2.2 의 DSS-Parms
+//                     // https://www-archive.mozilla.org/projects/security/pki/jss/javadoc/org/mozilla/jss/crypto/pqgparams
+//                     02 <== ASN.1 Integer Tag
+//                     81 <== Next Length is 1 byte
+//                     81 <== Length : 81 = 129 (0094 ~ 9e2f)
+//                             Integer : P(DSA prime parameter)
+//                             0094a11b020e5d9cd49e42bc344b6eaa615078b7774c17cdf89618d66a162bbe87afbe96d494422fa50697fc7ab839acca684ce3b9ec44fc9d8ef7cc1df635d29f00f40f245d1f93344ec19f81841d6d43f4f487bb9779b8018129ebd2e3803358367654137dce2611f6238d1b8a58d1bbb44d288f899d05ce4eef1da1af429e2f
+//                     02 <== ASN.1 Integer Tag
+//                     1d <== Length 1d=29
+//                             Integer : Q(DSA sub-prime parameter)
+//                             009b6e5fac8c16ffa6a375afaa995af235c90b9c2198f8bd0d4389457b
+//                     02 <== ASN.1 Integer Tag
+//                     81 <== Next Length is 1 byte
+//                     80 <== Length : 80 = 128 (23c4 ~ e4d4)
+//                             Integer : G (DSA base parameter)
+//                             23c46881fb79fbfe04c2c778c644fa1597d84711d11c9f69be6a8bc0201ea1c00447dba7a65e2d433f77851003a141b7751a7aff978c111379d4a1f573d9d708120392253f1829e5d7a7533f0d1112ca4b99dfaae40976c910b4d3655b17cdc6781d33b4b4bc4d240eb89d924798a6664f5867e2486cea23ac6c9abcd2abe4d4
+//     03 <== ASN.1 Bit String Tag
+//     81 <== Next Length is 1 byte
+//     84 <== Length : 84 = 132 (0002 ~ to end).
+//             00 <== leading zero in Bit String
+//             02 <== ASN.1 Integer Tag
+//             81 <== Next Length is 1 byte
+//             80 <== Length : 80 = 128 (6630 ~ to end)
+//             6630248c41f1743f62bc3093d8ea6035a8320babd0598e893a76de01d427e34559d4d8e2eef6bee19776c386e3acd39d08bfcb7b94d42a256a89f36a90554bc2e66fc9e4e2a823d4ee880a97d21ad8b8da44c0a8e96997d5041ccf198fff53880667d44e81f688a9c63bc8eca0f2253d279f4c8bb044034a4a9142e80a84eb01
+
+TEE_Result dsaPublicToDer(const DerData *prime, const DerData *subPrime, const DerData *base,
+                                                       const DerData *publicValue, DerData *out)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       DerData algoOid = {0x00, };
+       DerData algoParam = {0x00, };
+       DerData bitStrNoZero = {0x00, };
+       size_t offset = 0;
+       size_t tmp_len = 0;
+       size_t len_algoOid_total = 0;
+       size_t len_prime_total = 0;
+       size_t len_subprime_total = 0;
+       size_t len_base_total = 0;
+       size_t len_algo_param_value = 0;
+       size_t len_algo_param_total = 0;
+       size_t len_pubkeyBitstr_value = 0;
+
+       uint8_t *der = NULL;
+
+       // Generate algoOid DER.
+       len_algoOid_total = 1 + toLenSize(sizeof(ALGO_ID_ID_DSA)) + sizeof(ALGO_ID_ID_DSA);
+       algoOid.data = (uint8_t *) TEE_Malloc(len_algoOid_total, 0);
+       if(algoOid.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       algoOid.size = len_algoOid_total;
+
+       der = algoOid.data;
+       offset = 0;
+
+       der[offset++] = TAG_OID;
+       tmp_len = lenToBinary(sizeof(ALGO_ID_ID_DSA), der + offset);
+       if (tmp_len == 0) {
+               ret = TEE_ERROR_GENERIC;
+               goto clean;
+       }
+       offset += tmp_len;
+       memcpy(der + offset, ALGO_ID_ID_DSA, sizeof(ALGO_ID_ID_DSA));
+       offset += sizeof(ALGO_ID_ID_DSA);
+
+       // Generate algoParam DER.
+       len_prime_total = getIntegerTotalLenght(prime);
+       len_subprime_total = getIntegerTotalLenght(subPrime);
+       len_base_total = getIntegerTotalLenght(base);
+       len_algo_param_value = len_prime_total + len_subprime_total + len_base_total;
+       len_algo_param_total = 1 + toLenSize(len_algo_param_value) + len_algo_param_value;
+
+       algoParam.data = (uint8_t *) TEE_Malloc(len_algo_param_total, 0);
+       if(algoParam.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       algoParam.size = len_algo_param_total;
+
+       der = algoParam.data;
+       offset = 0;
+
+       // Encode Tag & Lenght
+       der[offset++] = TAG_SEQUENCE;
+       tmp_len = lenToBinary(len_algo_param_value, der + offset);
+       if (tmp_len == 0) {
+               ret = TEE_ERROR_GENERIC;
+               goto clean;
+       }
+       offset += tmp_len;
+       // Encode Value
+       tmp_len = integerDerToBinary(prime, der + offset);
+       offset += tmp_len;
+       tmp_len = integerDerToBinary(subPrime, der + offset);
+       offset += tmp_len;
+       tmp_len = integerDerToBinary(base, der + offset);
+       offset += tmp_len;
+
+       // Generate bitStrNoZero DER.
+       len_pubkeyBitstr_value = getIntegerTotalLenght(publicValue);
+
+       bitStrNoZero.data = (uint8_t *) TEE_Malloc(len_pubkeyBitstr_value, 0);
+       if(bitStrNoZero.data == NULL) {
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+       bitStrNoZero.size = len_pubkeyBitstr_value;
+
+       der = bitStrNoZero.data;
+       offset = 0;
+
+       // integer of public value
+       tmp_len = integerDerToBinary(publicValue, der + offset);
+       offset += tmp_len;
+
+       // Generate the entire DER.
+       ret = pubkeyElemsToDer(&algoOid, &algoParam, &bitStrNoZero, out);
+clean:
+       TEE_Free(algoOid.data);
+       TEE_Free(algoParam.data);
+       TEE_Free(bitStrNoZero.data);
+
+       return ret;
+}
+
+
+TEE_Result derToDsaPublic(const DerData *in, DerData *prime, DerData *subPrime, DerData *base,
+                                                       DerData *publicValue)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       int offset = 0, offset_increase = 0;
+       size_t tmp_len = 0;
+       bool same_algo_id = false;
+
+       DerData algoOid = {0x00, };
+       DerData algoParam = {0x00, };
+       DerData publicKey = {0x00, };
+
+       ret = parseDerToElems(in, &algoOid, &algoParam, &publicKey);
+       if(ret != TEE_SUCCESS)
+               return TEE_ERROR_GENERIC;
+
+       // Check Algorithm Identifier
+       offset_increase = checkAlgoId(algoOid.data + offset, algoOid.size - offset,
+                                                                       ALGO_ID_ID_DSA, sizeof(ALGO_ID_ID_DSA),
+                                                                       &same_algo_id);
+       if(offset_increase < 0 || same_algo_id != true)
+               return TEE_ERROR_GENERIC;
+
+       offset = 0;
+       offset_increase = 0;
+       // Parse algoParam Tag & Length
+       offset_increase = checkTagLength(algoParam.data + offset, algoParam.size - offset, &tmp_len);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       // Parse algoParam for prime
+       offset_increase = parseInteger(algoParam.data + offset, algoParam.size - offset, prime);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       // Parse algoParam for subprime
+       offset_increase = parseInteger(algoParam.data + offset, algoParam.size - offset, subPrime);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+       // Parse algoParam for base
+       offset_increase = parseInteger(algoParam.data + offset, algoParam.size - offset, base);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+
+       offset = 0;
+       offset_increase = 0;
+       // Parse publicValue
+       offset_increase = parseInteger(publicKey.data + offset, publicKey.size - offset, publicValue);
+       offset += offset_increase;
+       if(offset_increase < 0)
+               return TEE_ERROR_GENERIC;
+
+       return ret;
+}
index 9869635e50f38a52bd08c22bd29f5316143cca5b..7f0ef6752ae59c20b7ffb35365a5d8e7657ae9c3 100644 (file)
@@ -752,6 +752,16 @@ TEE_Result KM_EccCurveToKeyBitSize(uint32_t curve, uint32_t *bitsize)
        return TEE_SUCCESS;
 }
 
+TEE_Result KM_PublickeyToDer(uint32_t obj_type, TEE_ObjectHandle keyHndl, KM_BinaryData *der)
+{
+       switch (obj_type) {
+               case TYPE_AKEY_PUBLIC_EC:  return KM_EcpublickeyToDer(keyHndl, der);
+               case TYPE_AKEY_PUBLIC_RSA: return KM_RsapublickeyToDer(keyHndl, der);
+               case TYPE_AKEY_PUBLIC_DSA: return KM_DsapublickeyToDer(keyHndl, der);
+       }
+       return TEE_ERROR_NOT_SUPPORTED;
+}
+
 TEE_Result KM_EcpublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der)
 {
        TEE_Result ret = TEE_SUCCESS;
@@ -790,8 +800,8 @@ TEE_Result KM_EcpublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der)
        der->data_size = der_out.size;
 clean:
        if (ret != TEE_SUCCESS) {
-               TEE_Free(der->data);
-               der->data = NULL;
+               TEE_Free(der_out.data);
+               der_out.data = NULL;
        }
        TEE_Free(x.data);
        TEE_Free(y.data);
@@ -832,6 +842,101 @@ TEE_Result KM_DerToEcpublic(void *data, uint32_t data_size, uint32_t key_type,
        return ret;
 }
 
+TEE_Result KM_RsapublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       KM_BinaryData modulus, public_exponent;
+       DerData der_modulus, der_public_exponent, der_out;
+
+       // initialize;
+       modulus.data = NULL;
+       public_exponent.data = NULL;
+       der_out.data = NULL;
+
+       ret = KM_GetAttribute(keyHndl, TEE_ATTR_RSA_MODULUS, &modulus);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       ret = KM_GetAttribute(keyHndl, TEE_ATTR_RSA_PUBLIC_EXPONENT, &public_exponent);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       der_modulus.data = modulus.data;
+       der_modulus.size = modulus.data_size;
+       der_public_exponent.data = public_exponent.data;
+       der_public_exponent.size = public_exponent.data_size;
+
+       ret = rsaPublicToDer(&der_modulus, &der_public_exponent, &der_out);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       der->data = der_out.data;
+       der->data_size = der_out.size;
+clean:
+       if (ret != TEE_SUCCESS) {
+               TEE_Free(der_out.data);
+               der_out.data = NULL;
+       }
+       TEE_Free(modulus.data);
+       TEE_Free(public_exponent.data);
+       return ret;
+}
+
+TEE_Result KM_DsapublickeyToDer(TEE_ObjectHandle keyHndl, KM_BinaryData *der)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       KM_BinaryData prime, subprime, base, public_value;
+       DerData der_prime, der_subprime, der_base, der_public_value, der_out;
+
+       // initialize;
+       prime.data = NULL;
+       subprime.data = NULL;
+       base.data = NULL;
+       public_value.data = NULL;
+       der_out.data = NULL;
+
+       ret = KM_GetAttribute(keyHndl, TEE_ATTR_DSA_PRIME, &prime);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       ret = KM_GetAttribute(keyHndl, TEE_ATTR_DSA_SUBPRIME, &subprime);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+       ret = KM_GetAttribute(keyHndl, TEE_ATTR_DSA_BASE, &base);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       ret = KM_GetAttribute(keyHndl, TEE_ATTR_DSA_PUBLIC_VALUE, &public_value);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       der_prime.data = prime.data;
+       der_prime.size = prime.data_size;
+       der_subprime.data = subprime.data;
+       der_subprime.size = subprime.data_size;
+       der_base.data = base.data;
+       der_base.size = base.data_size;
+       der_public_value.data = public_value.data;
+       der_public_value.size = public_value.data_size;
+
+       ret = dsaPublicToDer(&der_prime, &der_subprime, &der_base, &der_public_value, &der_out);
+       if (ret != TEE_SUCCESS)
+               goto clean;
+
+       der->data = der_out.data;
+       der->data_size = der_out.size;
+clean:
+       if (ret != TEE_SUCCESS) {
+               TEE_Free(der_out.data);
+               der_out.data = NULL;
+       }
+       TEE_Free(prime.data);
+       TEE_Free(subprime.data);
+       TEE_Free(base.data);
+       TEE_Free(public_value.data);
+       return ret;
+}
+
 TEE_Result KM_EncryptAsymKey(TEE_ObjectHandle keyHndl, const KM_PwdData *pwd,
                                                        KM_BinaryData *encKey, KM_BinaryData *tag)
 {
@@ -1277,19 +1382,21 @@ TEE_Result KM_GetData(void *data, uint32_t expected_data_size, KM_BinaryData *ob
        KM_BinaryData buffer = {0, NULL};
        size_t tmp_len = 0;
 
-       if(obj_type == TYPE_AKEY_PUBLIC_EC) {
+       if(obj_type == TYPE_AKEY_PUBLIC_EC ||
+          // obj_type == TYPE_AKEY_PUBLIC_DSA || // Exporting DSA public key is not supported yet.
+          obj_type == TYPE_AKEY_PUBLIC_RSA) {
                if (with_pwd) {
                        ret = KM_DecryptAsymKey(obj_id, pwdData, &hndl);
                } else {
                        ret = KM_OpenKey(obj_id->data, obj_id->data_size, &hndl);
                }
                if (ret != TEE_SUCCESS) {
-                       LOG("Fail to open ec public key.");
+                       LOG("Fail to open public key.");
                        goto clean;
                }
-               ret = KM_EcpublickeyToDer(hndl, &buffer);
+               ret = KM_PublickeyToDer(obj_type, hndl, &buffer);
                if (ret != TEE_SUCCESS) {
-                       LOG("Fail to convert ec public key to der format");
+                       LOG("Fail to convert public key to der format");
                        goto clean;
                }
                if (buffer.data_size != expected_data_size) {
@@ -1380,19 +1487,21 @@ TEE_Result KM_GetDataSize(uint32_t *data_size, KM_BinaryData *obj_id,
                 } else {
                        *data_size = info.dataSize;
                 }
-       } else if (obj_type == TYPE_AKEY_PUBLIC_EC) {
+       } else if (obj_type == TYPE_AKEY_PUBLIC_EC ||
+                  // obj_type == TYPE_AKEY_PUBLIC_DSA ||  // Exporting DSA public key is not supported yet.
+                          obj_type == TYPE_AKEY_PUBLIC_RSA) {
                if (with_pwd) {
                        ret = KM_DecryptAsymKey(obj_id, pwdData, &hndl);
                } else {
                        ret = KM_OpenKey(obj_id->data, obj_id->data_size, &hndl);
                }
                if (ret != TEE_SUCCESS) {
-                       LOG("Fail to open ec public key.");
+                       LOG("Fail to open public key.");
                        goto clean;
                }
-               ret = KM_EcpublickeyToDer(hndl, &der);
+               ret = KM_PublickeyToDer(obj_type, hndl, &der);
                if (ret != TEE_SUCCESS) {
-                       LOG("Fail to convert ec public key to der format");
+                       LOG("Fail to convert public key to der format");
                        goto clean;
                }
                *data_size = der.data_size;