* See the License for the specific language governing permissions and
* limitations under the License
*/
+
#include <assert.h>
#include <stdbool.h>
#include <string.h>
TAG_INT = 0x02,
TAG_BIT_STRING = 0x03,
TAG_OCTET_STRING = 0x04,
+ TAG_NULL = 0x05,
TAG_OID = 0x06,
TAG_SEQUENCE = 0x30,
};
// 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)
{
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) {
width = 0x7F & *binary;
switch(width) {
case 1:
- *len = *(binary+1);
+ *len = *(binary+1);
return 2;
case 2:
*len = ((*(binary+1)) << 8) + (*(binary+2));
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) {
// 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);
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) {
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;
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;
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;
+}