TAG_OCTET_STRING = 0x04,
TAG_NULL = 0x05,
TAG_OID = 0x06,
+ TAG_PARAMS = 0xA0,
+ TAG_PUB_KEY = 0xA1,
TAG_SEQUENCE = 0x30,
};
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++;
*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;
}
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,
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:
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;
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;
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;