/** * @file ID2HLSEWrapper.c * @author NXP Semiconductors * @version 1.0 * @par License * * Copyright 2017,2020 NXP * SPDX-License-Identifier: Apache-2.0 * * @par Description * Host Lib wrapper API implementation over the A71CL host library * * @par HISTORY * */ #include #include "HLSEAPI.h" #include "a71cl_api.h" #include "ax_api.h" #include "nxLog_hostLib.h" // Storgae size of 5K #define HLSE_MAX_STORAGE_SIZE 5000 /// Create handle #define HLSE_CREATE_HANDLE(HLSE_READ_ONLY, HLSE_OBJECT_TYPE, HLSE_OBJECT_INDEX) ((HLSE_READ_ONLY ? 0x80000000 : 0x00000000) | HLSE_OBJECT_TYPE | HLSE_OBJECT_INDEX) /// Get Object Type #define HLSE_GET_OBJECT_TYPE(HLSE_OBJECT_HANDLE) (HLSE_OBJECT_HANDLE & 0x7FFF0000) /// Get Object Index #define HLSE_GET_OBJECT_INDEX(HLSE_OBJECT_HANDLE) (U8)((HLSE_OBJECT_HANDLE & 0x000000FF)) /// Get Object Full Index #define HLSE_GET_OBJECT_FULL_INDEX(HLSE_OBJECT_HANDLE) ((HLSE_OBJECT_HANDLE & 0x0000FFFF)) /// Get Logical object class #define HLSE_GET_LOGICAL_OBJECT_CLASS(HLSE_OBJECT_TYPE) (U8)((HLSE_OBJECT_TYPE & 0x00FF0000) >> 16) /// Get logical object type #define HLSE_GET_LOGICAL_OBJECT_TYPE(objClass) ((objClass << 16u) & 0x00FF0000u) /// Max num of Asymmetric keys supported #define HLSE_MAX_ASYMMETRIC_KEYS 1 /// RSA Public key size #define HLSE_RSA_PUBLIC_KEY_SIZE 256 /// RSA Public exponent size #define HLSE_RSA_PUBLIC_EXPONENT_SIZE 4 /// Maintains the Public key returned by the Secure Element when Key Generation is used static U8 sPublicKeys[HLSE_MAX_ASYMMETRIC_KEYS][HLSE_RSA_PUBLIC_KEY_SIZE + HLSE_RSA_PUBLIC_EXPONENT_SIZE + 2 + 2]; static U16 sPublicKeysLen[HLSE_MAX_ASYMMETRIC_KEYS]; //******************************************************************* // Object Operations - defined in HLSEObjects.h //******************************************************************* static U8 IsDataValidCertificate(U8* storageData, U16 storageDataLen, U16* certificateSize) { U8 TagLen = 1; U16 dataLen = 0; if (storageDataLen > 6) { // Tag should be 0x30 if (storageData[0] == 0x30) { if ((storageData[1] & 0x1F) == 0x1F) { TagLen = 2; if (storageData[2] & 0x80) { TagLen = 3; } } if (storageData[TagLen] & 0x80) { if (storageData[TagLen] == 0x81) dataLen = storageData[TagLen + 1] + 2 + TagLen; else { dataLen = storageData[TagLen + 1] * 256 + storageData[TagLen + 2] + 3 + TagLen; } } else dataLen = storageData[TagLen] + 1 + TagLen; *certificateSize = dataLen; return 1; // valid } } return 0; // invalid } HLSE_RET_CODE HLSE_EnumerateObjects(HLSE_OBJECT_TYPE objectType, HLSE_OBJECT_HANDLE* objectHandles, U16* objectHandlesLen) { U8 storageData[HLSE_MAX_STORAGE_SIZE]; U16 storageDataLen = sizeof(storageData); U8 certExists = 0, symKeyExists = 0, asymKeyExists = 0; U16 objCount = 0; // the Module always exists U16 lReturn; #ifndef HLSE_IGNORE_PARAM_CHECK //objectHandles is NULL, then all that the function does is return (in \p *objectHandlesLen) a number of HLSE_OBJECT_HANDLE which would suffice // to hold the returned list. HLSE_SW_OK is returned by the function. //If objectHandles is not NULL, then objectHandlesLen must contain the number of handles in the buffer objectHandles if (objectHandles != NULL && objectHandlesLen == NULL) { return HLSE_ERR_API_ERROR; } if (objectHandlesLen == NULL) { return HLSE_ERR_API_ERROR; } #endif // Read record # 0 and check the data to see if it's a certificate in TLV format lReturn = CL_FreeReadServiceData(0, storageData, &storageDataLen); if (lReturn == HLSE_SW_OK) { U16 certificateSize = 0; certExists = IsDataValidCertificate(storageData, storageDataLen, &certificateSize); } // If in PERSONALIZED mode (i.e. there is an ID2 data) then we assume there is a Symmetric and Assymmetric key { sCL_ID iD2Id; lReturn = CL_GetID((U8*)&iD2Id, sizeof(sCL_ID)); if (lReturn == HLSE_SW_OK) { symKeyExists = 1; asymKeyExists = 1; } } // GP Get Status ? if (objectType == HLSE_MODULE) { objCount++; } // How to check if the KEK exists or not???? else if (objectType == HLSE_KEK_KEY) { objCount++; } else if (objectType != HLSE_CERTIFICATE/* && objectType != HLSE_DATA*/) { if (objectType == HLSE_MODULE || objectType == HLSE_ANY_TYPE) { objCount++; } if (objectType == HLSE_KEK_KEY || objectType == HLSE_ANY_TYPE) { objCount++; } if (asymKeyExists && (objectType == HLSE_KEY_PAIR || objectType == HLSE_ANY_TYPE)) objCount++; // public key too??? else if (symKeyExists && (objectType == HLSE_SYMMETRIC_KEY || objectType == HLSE_ANY_TYPE)) objCount++; } // read Certificate/Data objects if (objectType == HLSE_CERTIFICATE /*|| objectType == HLSE_DATA */|| objectType == HLSE_ANY_TYPE) { if (certExists) { objCount++; } } if (objectHandles == NULL) { *objectHandlesLen = objCount; return HLSE_SW_OK; } if (objectHandles != NULL && objectHandlesLen != NULL && *objectHandlesLen < objCount) { *objectHandlesLen = objCount; return HLSE_ERR_BUF_TOO_SMALL; } *objectHandlesLen = 0; if (objectType == HLSE_MODULE || objectType == HLSE_ANY_TYPE) { objectHandles[(*objectHandlesLen)++] = HLSE_CREATE_HANDLE(1, HLSE_MODULE, 0); } else if (objectType == HLSE_KEK_KEY || objectType == HLSE_ANY_TYPE) { objectHandles[(*objectHandlesLen)++] = HLSE_CREATE_HANDLE(1, HLSE_KEK_KEY, 0); } else if (objectType != HLSE_CERTIFICATE && objectType != HLSE_DATA) { if (asymKeyExists && (objectType == HLSE_KEY_PAIR || objectType == HLSE_ANY_TYPE)) objectHandles[(*objectHandlesLen)++] = HLSE_CREATE_HANDLE(false, HLSE_KEY_PAIR, 0); // public key too??? else if (symKeyExists && (objectType == HLSE_SYMMETRIC_KEY || objectType == HLSE_ANY_TYPE)) objectHandles[(*objectHandlesLen)++] = HLSE_CREATE_HANDLE(false, HLSE_SYMMETRIC_KEY, 0); } // add Certificate objects if (objectType == HLSE_CERTIFICATE /*|| objectType == HLSE_DATA */ || objectType == HLSE_ANY_TYPE) { if (certExists) { objectHandles[(*objectHandlesLen)++] = HLSE_CREATE_HANDLE(false, HLSE_CERTIFICATE, 0); } } return HLSE_SW_OK; } HLSE_RET_CODE HLSE_SetObjectAttribute(HLSE_OBJECT_HANDLE hObject, HLSE_ATTRIBUTE* attribute) { #ifndef HLSE_IGNORE_PARAM_CHECK if ((attribute == NULL) || (hObject == HLSE_ANY_TYPE)) { return HLSE_ERR_API_ERROR; } #endif //*************************** // HLSE_KEY_PAIR //*************************** if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_KEY_PAIR) { // NOTE: A key pair cannot be re-generated!!! if (attribute->type == HLSE_ATTR_OBJECT_VALUE) { if (attribute->value == NULL) return HLSE_ERR_API_ERROR; return CL_SecurityStorage(attribute->value, attribute->valueLen); } else if (attribute->type == HLSE_ATTR_WRAPPED_OBJECT_VALUE) { if (attribute->value == NULL || attribute->valueLen != sizeof(HLSE_KEK_WRAPPED_OBJECT_PARAMS)) return HLSE_ERR_API_ERROR; { HLSE_KEK_WRAPPED_OBJECT_PARAMS* data; data = (HLSE_KEK_WRAPPED_OBJECT_PARAMS*)(attribute->value); return CL_SecurityStorageWithKEK(data->value, data->valueLen, data->KEK, data->KEKLen); } } else return HLSE_ERR_API_ERROR; } ////*************************** //// HLSE_PUBLIC_KEY ////*************************** //else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_PUBLIC_KEY) { // if (attribute->value == NULL || attribute->valueLen == 0) // return HLSE_ERR_API_ERROR; // if (attribute->type == HLSE_ATTR_OBJECT_VALUE) // return A71_SetEccPublicKey(HLSE_GET_OBJECT_INDEX(hObject), (U8*)(attribute->value), attribute->valueLen); // else // return HLSE_ERR_API_ERROR; //} //*************************** // HLSE_SYMMETRIC_KEY //*************************** else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_SYMMETRIC_KEY) { if (attribute->value == NULL) return HLSE_ERR_API_ERROR; if (attribute->type == HLSE_ATTR_OBJECT_VALUE) { if (attribute->value == NULL) return HLSE_ERR_API_ERROR; return CL_SecurityStorage(attribute->value, attribute->valueLen); } else if (attribute->type == HLSE_ATTR_WRAPPED_OBJECT_VALUE) { if (attribute->value == NULL || attribute->valueLen != sizeof(HLSE_KEK_WRAPPED_OBJECT_PARAMS)) return HLSE_ERR_API_ERROR; { HLSE_KEK_WRAPPED_OBJECT_PARAMS* data; data = (HLSE_KEK_WRAPPED_OBJECT_PARAMS*)(attribute->value); return CL_SecurityStorageWithKEK(data->value, data->valueLen, data->KEK, data->KEKLen); } } else return HLSE_ERR_API_ERROR; } //*************************** // HLSE_KEK_KEY //*************************** else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_KEK_KEY) { if (attribute->value == NULL) return HLSE_ERR_API_ERROR; if (attribute->type == HLSE_ATTR_WRAPPED_OBJECT_VALUE) { if (attribute->value == NULL || attribute->valueLen != sizeof(HLSE_KEK_WRAPPED_OBJECT_PARAMS)) return HLSE_ERR_API_ERROR; { HLSE_KEK_WRAPPED_OBJECT_PARAMS* data; data = (HLSE_KEK_WRAPPED_OBJECT_PARAMS*)(attribute->value); return CL_SetKEKValue(data->KEK, data->KEKLen, data->value, data->valueLen); } } else if (attribute->type == HLSE_ATTR_EXTERNAL_AUTH) { if (attribute->value == NULL || attribute->valueLen != 16) return HLSE_ERR_API_ERROR; return CL_ExternalAuthenticate(attribute->value, attribute->valueLen); } else return HLSE_ERR_API_ERROR; } //*************************** // HLSE_CERTIFICATE //*************************** else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_CERTIFICATE ) { // NOTE: Assuming the object is updated/created in either Plain Injection mode or Authentication mode only if (attribute->value == NULL) return HLSE_ERR_API_ERROR; // NOTE: currently allowing only one certificate with index 0 if (HLSE_GET_OBJECT_INDEX(hObject) != 0) return HLSE_ERR_IDENT_IDX_RANGE; // Plain Injection Mode if (attribute->type == HLSE_ATTR_OBJECT_VALUE) { U16 certificateSize = 0; U16 remainingSize; U16 dataOffset = 0; U8 recordNum = 0; U16 chunkSize = 255; if (attribute->value == NULL) return HLSE_ERR_API_ERROR; // The Certificate data must be in TLV format if (!IsDataValidCertificate(attribute->value, attribute->valueLen, &certificateSize)) return HLSE_ERR_TLV_MISSING; remainingSize = attribute->valueLen; while (remainingSize) { U16 lReturn; U16 sentLength = (remainingSize >= chunkSize ? chunkSize : remainingSize); lReturn = CL_UpdateServiceData(recordNum, NULL, 0, (U8*)attribute->value + dataOffset, sentLength); if (lReturn != SW_OK) return lReturn; recordNum++; dataOffset += sentLength; remainingSize -= sentLength; } return SW_OK; } else if (attribute->type == HLSE_ATTR_WRAPPED_OBJECT_VALUE) { if (attribute->value == NULL || attribute->valueLen != sizeof(HLSE_KEK_WRAPPED_OBJECT_PARAMS)) return HLSE_ERR_API_ERROR; { U16 certificateSize = 0; U16 remainingSize; U16 dataOffset = 0; U8 recordNum = 0; U16 chunkSize = 224; HLSE_KEK_WRAPPED_OBJECT_PARAMS* data; data = (HLSE_KEK_WRAPPED_OBJECT_PARAMS*)(attribute->value); // The Certificate data must be in TLV format if (!IsDataValidCertificate(data->value, data->valueLen, &certificateSize)) return HLSE_ERR_TLV_MISSING; remainingSize = data->valueLen; while (remainingSize) { U16 lReturn; U16 sentLength = (remainingSize >= chunkSize ? chunkSize : remainingSize); lReturn = CL_UpdateServiceData(recordNum, data->KEK, data->KEKLen, (U8*)data->value + dataOffset, sentLength); if (lReturn != SW_OK) return lReturn; recordNum++; dataOffset += sentLength; remainingSize -= sentLength; } return SW_OK; } } } else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_DATA) { // NOTE: Assuming the object is updated/created in either Plain Injection mode or Authentication mode only if (attribute->value == NULL) return HLSE_ERR_API_ERROR; // NOTE: currently allowing only one certificate with index 0 if (HLSE_GET_OBJECT_INDEX(hObject) != 0) return HLSE_ERR_IDENT_IDX_RANGE; // Plain Injection Mode if (attribute->type == HLSE_ATTR_OBJECT_VALUE) { U16 remainingSize; U16 dataOffset = 0; U8 recordNum = 0; U16 chunkSize = 255; if (attribute->value == NULL) return HLSE_ERR_API_ERROR; remainingSize = attribute->valueLen; while (remainingSize) { U16 lReturn; U16 sentLength = (remainingSize >= chunkSize ? chunkSize : remainingSize); lReturn = CL_UpdateServiceData(recordNum, NULL, 0, (U8*)attribute->value + dataOffset, sentLength); if (lReturn != SW_OK) return lReturn; recordNum++; dataOffset += sentLength; remainingSize -= sentLength; } return SW_OK; } else if (attribute->type == HLSE_ATTR_WRAPPED_OBJECT_VALUE) { if (attribute->value == NULL || attribute->valueLen != sizeof(HLSE_KEK_WRAPPED_OBJECT_PARAMS)) return HLSE_ERR_API_ERROR; { U16 remainingSize; U16 dataOffset = 0; U8 recordNum = 0; U16 chunkSize = 224; HLSE_KEK_WRAPPED_OBJECT_PARAMS* data; data = (HLSE_KEK_WRAPPED_OBJECT_PARAMS*)(attribute->value); remainingSize = data->valueLen; while (remainingSize) { U16 lReturn; U16 sentLength = (remainingSize >= chunkSize ? chunkSize : remainingSize); lReturn = CL_UpdateServiceData(recordNum, data->KEK, data->KEKLen, (U8*)data->value + dataOffset, sentLength); if (lReturn != SW_OK) return lReturn; recordNum++; dataOffset += sentLength; remainingSize -= sentLength; } return SW_OK; } } } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLSE_GetObjectAttribute(HLSE_OBJECT_HANDLE hObject, HLSE_ATTRIBUTE* attribute) { HLSE_RET_CODE lReturn = HLSE_SW_OK; #ifndef HLSE_IGNORE_PARAM_CHECK // allow only specific type if (hObject == HLSE_ANY_TYPE) { return HLSE_ERR_API_ERROR; } if (attribute == NULL) { return HLSE_ERR_API_ERROR; } #endif // { Check if user requets to obtain the length only if (attribute->value == NULL) { // return in attribute->valueLen a number of bytes which would suffice to hold the value to be returned if (attribute->type == HLSE_ATTR_OBJECT_TYPE) { attribute->valueLen = sizeof(HLSE_OBJECT_TYPE); return HLSE_SW_OK; } else if (attribute->type == HLSE_ATTR_OBJECT_INDEX) { attribute->valueLen = sizeof(HLSE_OBJECT_INDEX); return HLSE_SW_OK; } else if (attribute->type == HLSE_ATTR_MODULE_MODE) { attribute->valueLen = 1; return HLSE_SW_OK; } else if (attribute->type == HLSE_ATTR_MODULE_CL_ID) { attribute->valueLen = 256 + 3; return HLSE_SW_OK; } else if (attribute->type == HLSE_ATTR_VENDOR_INFO) { attribute->valueLen = sizeof(sCL_VendorInfo); return HLSE_SW_OK; } else if (attribute->type == HLSE_ATTR_MODULE_RANDOM) { attribute->valueLen = 16; return HLSE_SW_OK; } else if (((HLSE_GET_OBJECT_TYPE(hObject) == HLSE_KEY_PAIR) || (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_PUBLIC_KEY)) && (attribute->type == HLSE_ATTR_RSA_MODULUS)) { attribute->valueLen = sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)]; return HLSE_SW_OK; } else if (((HLSE_GET_OBJECT_TYPE(hObject) == HLSE_KEY_PAIR) || (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_PUBLIC_KEY)) && (attribute->type == HLSE_ATTR_RSA_PUBLIC_EXPONENT)) { attribute->valueLen = HLSE_RSA_PUBLIC_EXPONENT_SIZE; return HLSE_SW_OK; } else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_CERTIFICATE /*|| HLSE_GET_OBJECT_TYPE(hObject) == HLSE_DATA*/) { // length will be retrieved later on GetObjectData() } else { // type requested not found return HLSE_ERR_API_ERROR; } } // } end section obtaining only the length if (attribute->type == HLSE_ATTR_OBJECT_TYPE) { if (attribute->valueLen >= sizeof(HLSE_OBJECT_TYPE)) { HLSE_OBJECT_TYPE type = HLSE_GET_OBJECT_TYPE(hObject); memcpy(attribute->value, &type, sizeof(HLSE_OBJECT_TYPE)); attribute->valueLen = sizeof(HLSE_OBJECT_TYPE); return HLSE_SW_OK; } else { return HLSE_ERR_BUF_TOO_SMALL; } } else if (attribute->type == HLSE_ATTR_OBJECT_INDEX) { if (attribute->valueLen >= sizeof(HLSE_OBJECT_INDEX)) { HLSE_OBJECT_INDEX index = HLSE_GET_OBJECT_FULL_INDEX(hObject); memcpy(attribute->value, &index, sizeof(HLSE_OBJECT_INDEX)); attribute->valueLen = sizeof(HLSE_OBJECT_INDEX); return HLSE_SW_OK; } else { return HLSE_ERR_BUF_TOO_SMALL; } } //else if (attribute->type == HLSE_ATTR_READ_ONLY) { // if (attribute->valueLen >= sizeof(U8)) { // U8 objState = ((hObject & 0x80000000) ? 1 : 0); // memcpy(attribute->value, &objState, 1); // attribute->valueLen = 1; // return HLSE_SW_OK; // } // else { // return HLSE_ERR_BUF_TOO_SMALL; // } //} else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_MODULE) { if (attribute->type == HLSE_ATTR_MODULE_CL_ID) { if (attribute->valueLen < 40) { attribute->valueLen = 40; return HLSE_ERR_BUF_TOO_SMALL; } return CL_GetID(attribute->value, attribute->valueLen); } if (attribute->type == HLSE_ATTR_MODULE_MODE) { U8 val; if (attribute->valueLen < 1) { attribute->valueLen = 1; return HLSE_ERR_BUF_TOO_SMALL; } val = CL_IsAppletInAuthenticationMode(); if (val) val = HLSE_AUTHENTICATION_MODE; else val = HLSE_DEFAULT_OR_PLAIN_MODE; memcpy(attribute->value, &val, 1); return HLSE_SW_OK; } if (attribute->type == HLSE_ATTR_VENDOR_INFO) { if (attribute->valueLen < sizeof(sCL_VendorInfo)) { attribute->valueLen = sizeof(sCL_VendorInfo); return HLSE_ERR_BUF_TOO_SMALL; } attribute->valueLen = sizeof(sCL_VendorInfo); return CL_GetVendorInfo((sCL_VendorInfo*)attribute->value); } if (attribute->type == HLSE_ATTR_MODULE_RANDOM) { if (attribute->valueLen < 16) { attribute->valueLen = 16; return HLSE_ERR_BUF_TOO_SMALL; } return CL_GetChallenge(attribute->value, (const U8)attribute->valueLen); } } else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_KEY_PAIR || HLSE_GET_OBJECT_TYPE(hObject) == HLSE_PUBLIC_KEY) { if (attribute->type == HLSE_ATTR_RSA_MODULUS) { if (attribute->valueLen < (sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] - 8)) { attribute->valueLen = sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] - 8; return HLSE_ERR_BUF_TOO_SMALL; } memcpy(attribute->value, sPublicKeys[HLSE_GET_OBJECT_INDEX(hObject)] + 2, sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] - 8); attribute->valueLen = sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] - 8; return HLSE_SW_OK; } if (attribute->type == HLSE_ATTR_RSA_PUBLIC_EXPONENT) { if (attribute->valueLen < HLSE_RSA_PUBLIC_EXPONENT_SIZE) { attribute->valueLen = HLSE_RSA_PUBLIC_EXPONENT_SIZE; return HLSE_ERR_BUF_TOO_SMALL; } memcpy(attribute->value, sPublicKeys[HLSE_GET_OBJECT_INDEX(hObject)] + sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] - HLSE_RSA_PUBLIC_EXPONENT_SIZE, HLSE_RSA_PUBLIC_EXPONENT_SIZE); attribute->valueLen = HLSE_RSA_PUBLIC_EXPONENT_SIZE; return HLSE_SW_OK; } } else { if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_CERTIFICATE || HLSE_GET_OBJECT_TYPE(hObject) == HLSE_DATA) { if (attribute->type == HLSE_ATTR_OBJECT_VALUE) { U8 oneRecord[255]; U16 oneRecordLen = sizeof(oneRecord); U8 recordNum = HLSE_GET_OBJECT_INDEX(hObject); // parse the data U16 certificateSize = 0; lReturn = CL_FreeReadServiceData(recordNum, oneRecord, &oneRecordLen); if (lReturn != HLSE_SW_OK) { return lReturn; } /* if (IsDataValidCertificate(oneRecord, oneRecordLen, &certificateSize))*/ { if (attribute->value == NULL) { attribute->valueLen = certificateSize; return HLSE_SW_OK; } if (attribute->valueLen < certificateSize) { attribute->valueLen = certificateSize; return HLSE_ERR_BUF_TOO_SMALL; } // read all the records until end of certificate { attribute->valueLen = certificateSize; if (certificateSize <= oneRecordLen) { // All the data has been read in the first apdu memcpy(attribute->value, oneRecord, certificateSize); return HLSE_SW_OK; } else { U16 dataOffset = oneRecordLen; // copy the laready record memcpy((U8*)attribute->value, oneRecord, oneRecordLen); certificateSize -= oneRecordLen; while (certificateSize) { U16 actualBytes; oneRecordLen = sizeof(oneRecord); recordNum++; lReturn = CL_FreeReadServiceData(recordNum, oneRecord, &oneRecordLen); if (lReturn != HLSE_SW_OK) { return lReturn; } actualBytes = (certificateSize < oneRecordLen ? certificateSize : oneRecordLen); memcpy((U8*)attribute->value + dataOffset, oneRecord, actualBytes); certificateSize -= actualBytes; dataOffset += actualBytes; } } } } return HLSE_SW_OK; } } } return HLSE_ERR_API_ERROR; } #define HLSE_INTERNAL_KEK 0 #define HLSE_INTERNAL_ID2 1 #define HLSE_INTERNAL_TYPE 2 #define HLSE_INTERNAL_LENGTH 3 #define HLSE_INTERNAL_N 4 #define HLSE_INTERNAL_D 5 #define HLSE_INTERNAL_E 6 #define HLSE_INTERNAL_P 7 #define HLSE_INTERNAL_Q 8 #define HLSE_INTERNAL_DP 9 #define HLSE_INTERNAL_DQ 10 #define HLSE_INTERNAL_DPQ 11 static HLSE_RET_CODE HLSE_CreateRSAKey(HLSE_OBJECT_HANDLE hObject, HLSE_ATTRIBUTE* attributes, U16 attributesNum) { U16 lReturn = SW_OK; U8 indexes[12]; U16 keyDataFieldSize = 0; U16 keyLength = 0; U8 i; U8* keyData = NULL; U16 offset = 0; memset(indexes, attributesNum + 1, sizeof(indexes)); for (i = 0; i < attributesNum; ++i) { if (attributes[i].value == NULL || attributes[i].valueLen == 0) return HLSE_ERR_API_ERROR; if (attributes[i].type == HLSE_ATTR_KEY_CL_ID) { indexes[HLSE_INTERNAL_ID2] = i; } else if (attributes[i].type == HLSE_ATTR_KEK_VALUE) { indexes[HLSE_INTERNAL_KEK] = i; } else if (attributes[i].type == HLSE_ATTR_KEY_TYPE) { indexes[HLSE_INTERNAL_TYPE] = i; } else if (attributes[i].type == HLSE_ATTR_KEY_LENGTH) { indexes[HLSE_INTERNAL_LENGTH] = i; } else { if (attributes[i].type == HLSE_ATTR_RSA_MODULUS) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_N] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_PUBLIC_EXPONENT) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_E] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_PRIVATE_EXPONENT) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_D] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_P) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_P] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_Q) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_Q] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_DP) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_DP] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_DQ) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_DQ] = i; } else if (attributes[i].type == HLSE_ATTR_RSA_DPQ) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_DPQ] = i; } } } // no ID2 string if ( ((indexes[HLSE_INTERNAL_LENGTH] > attributesNum) && (indexes[HLSE_INTERNAL_ID2] > attributesNum)) || ((indexes[HLSE_INTERNAL_TYPE] > attributesNum)) ) return HLSE_ERR_API_ERROR; // if the key is to be generated, no key values can be passed if (indexes[HLSE_INTERNAL_LENGTH] < attributesNum && keyDataFieldSize != 0) return HLSE_ERR_API_ERROR; if (indexes[HLSE_INTERNAL_ID2] < attributesNum) { keyData = (U8*)malloc(attributes[indexes[HLSE_INTERNAL_ID2]].valueLen + 3 + keyDataFieldSize); keyData[offset++] = (U8)attributes[indexes[HLSE_INTERNAL_ID2]].valueLen; memcpy(keyData + offset, attributes[indexes[HLSE_INTERNAL_ID2]].value, attributes[indexes[HLSE_INTERNAL_ID2]].valueLen); offset += attributes[indexes[HLSE_INTERNAL_ID2]].valueLen; keyData[offset++] = *(U8*)(attributes[indexes[HLSE_INTERNAL_TYPE]].value); keyData[offset++] = HLSE_GET_OBJECT_INDEX(hObject); for (i = HLSE_INTERNAL_N; i < sizeof(indexes); ++i) { if (indexes[i] < attributesNum) { keyData[offset++] = (i == HLSE_INTERNAL_N ? etagRSA_N : i == HLSE_INTERNAL_E ? etagRSA_E : i == HLSE_INTERNAL_D ? etagRSA_D : i == HLSE_INTERNAL_P ? etagRSA_CRT_P : i == HLSE_INTERNAL_Q ? etagRSA_CRT_Q : i == HLSE_INTERNAL_DP ? etagRSA_CRT_DP : i == HLSE_INTERNAL_DQ ? etagRSA_CRT_DQ : etagRSA_CRT_INVQ); keyData[offset++] = attributes[indexes[i]].valueLen >> 8; keyData[offset++] = attributes[indexes[i]].valueLen & 0xFF; memcpy(keyData + offset, attributes[indexes[i]].value, attributes[indexes[i]].valueLen); offset += attributes[indexes[i]].valueLen; } } } // Authentication mode if (indexes[HLSE_INTERNAL_KEK] < attributesNum) { if (indexes[HLSE_INTERNAL_LENGTH] < attributesNum) { keyLength = *(U16*)(attributes[indexes[HLSE_INTERNAL_LENGTH]].value); keyLength /= 8; lReturn = CL_GenerateKeyPairWithKEK(sPublicKeys[HLSE_GET_OBJECT_INDEX(hObject)], keyLength, *(U8*)(attributes[indexes[HLSE_INTERNAL_TYPE]].value), HLSE_GET_OBJECT_INDEX(hObject), attributes[indexes[HLSE_INTERNAL_KEK]].value, attributes[indexes[HLSE_INTERNAL_KEK]].valueLen); sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] = keyLength + 8; } else { lReturn = CL_SecurityStorageWithKEK(keyData, attributes[indexes[HLSE_INTERNAL_ID2]].valueLen + 3 + keyDataFieldSize, attributes[indexes[HLSE_INTERNAL_KEK]].value, attributes[indexes[HLSE_INTERNAL_KEK]].valueLen); } } // Default or Plain mode else { if (indexes[HLSE_INTERNAL_LENGTH] < attributesNum) { keyLength = *(U16*)(attributes[indexes[HLSE_INTERNAL_LENGTH]].value); keyLength /= 8; lReturn = CL_GenerateKeyPair(sPublicKeys[HLSE_GET_OBJECT_INDEX(hObject)], keyLength, *(U8*)(attributes[indexes[HLSE_INTERNAL_TYPE]].value), HLSE_GET_OBJECT_INDEX(hObject)); sPublicKeysLen[HLSE_GET_OBJECT_INDEX(hObject)] = keyLength + 8; } else { lReturn = CL_SecurityStorage(keyData, attributes[indexes[HLSE_INTERNAL_ID2]].valueLen + 3 + keyDataFieldSize); } } free(keyData); return lReturn; } #define HLSE_INTERNAL_VALUE 4 static HLSE_RET_CODE HLSE_CreateSymmetricKey(HLSE_OBJECT_HANDLE hObject, HLSE_ATTRIBUTE* attributes, U16 attributesNum) { U16 lReturn = SW_OK; U8 indexes[5]; U16 keyDataFieldSize = 0; U8 i; U8* keyData = NULL; U16 offset = 0; memset(indexes, attributesNum + 1, sizeof(indexes)); for (i = 0; i < attributesNum; ++i) { if (attributes[i].value == NULL || attributes[i].valueLen == 0) return HLSE_ERR_API_ERROR; if (attributes[i].type == HLSE_ATTR_KEY_CL_ID) { indexes[HLSE_INTERNAL_ID2] = i; } else if (attributes[i].type == HLSE_ATTR_KEK_VALUE) { indexes[HLSE_INTERNAL_KEK] = i; } else if (attributes[i].type == HLSE_ATTR_KEY_TYPE) { indexes[HLSE_INTERNAL_TYPE] = i; } else if (attributes[i].type == HLSE_ATTR_KEY_LENGTH) { indexes[HLSE_INTERNAL_LENGTH] = i; } else { if (attributes[i].type == HLSE_ATTR_OBJECT_VALUE) { keyDataFieldSize += (3 + attributes[i].valueLen); indexes[HLSE_INTERNAL_VALUE] = i; } } } // no ID2 string if (indexes[HLSE_INTERNAL_ID2] > attributesNum || indexes[HLSE_INTERNAL_TYPE] > attributesNum) return HLSE_ERR_API_ERROR; keyData = (U8*)malloc(attributes[indexes[HLSE_INTERNAL_ID2]].valueLen + 3 + keyDataFieldSize); keyData[offset++] = (U8)attributes[indexes[HLSE_INTERNAL_ID2]].valueLen; memcpy(keyData + offset, attributes[indexes[HLSE_INTERNAL_ID2]].value, attributes[indexes[HLSE_INTERNAL_ID2]].valueLen); offset += attributes[indexes[HLSE_INTERNAL_ID2]].valueLen; keyData[offset++] = *(U8*)(attributes[indexes[HLSE_INTERNAL_TYPE]].value); keyData[offset++] = HLSE_GET_OBJECT_INDEX(hObject); if (indexes[HLSE_INTERNAL_VALUE] < attributesNum) { keyData[offset++] = *(U8*)(attributes[indexes[HLSE_INTERNAL_TYPE]].value) == e3DES ? etag3ES : etagAES; keyData[offset++] = attributes[indexes[HLSE_INTERNAL_VALUE]].valueLen >> 8; keyData[offset++] = attributes[indexes[HLSE_INTERNAL_VALUE]].valueLen & 0xFF; memcpy(keyData + offset, attributes[indexes[HLSE_INTERNAL_VALUE]].value, attributes[indexes[HLSE_INTERNAL_VALUE]].valueLen); offset += attributes[indexes[HLSE_INTERNAL_VALUE]].valueLen; } if (indexes[HLSE_INTERNAL_KEK] < attributesNum) { lReturn = CL_SecurityStorageWithKEK(keyData, attributes[indexes[HLSE_INTERNAL_ID2]].valueLen + 3 + keyDataFieldSize, attributes[indexes[HLSE_INTERNAL_KEK]].value, attributes[indexes[HLSE_INTERNAL_KEK]].valueLen); } else { lReturn = CL_SecurityStorage(keyData, attributes[indexes[HLSE_INTERNAL_ID2]].valueLen + 3 + keyDataFieldSize); } free(keyData); return lReturn; } HLSE_RET_CODE HLSE_CreateObject(HLSE_ATTRIBUTE* attributes, U16 attributesNum, HLSE_OBJECT_HANDLE* hObject) { // Sym key - create // Asym key - create + gen (w/o KEK) // certificate // Get the object type and index and create the handle HLSE_OBJECT_TYPE objType = HLSE_ANY_TYPE; HLSE_OBJECT_INDEX objIndex = 0; U16 valAttrIndex = 0; U8 readOnly = 0; HLSE_RET_CODE lReturn = HLSE_SW_OK; U8 i; #ifndef HLSE_IGNORE_PARAM_CHECK // HLSE_ATTR_OBJECT_TYPE and HLSE_ATTR_OBJECT_INDEX must appear if (attributes == NULL || hObject == NULL || attributesNum < 2) return HLSE_ERR_API_ERROR; #endif for (i = 0; i < attributesNum; ++i) { if (attributes[i].type == HLSE_ATTR_OBJECT_TYPE) { if (attributes[i].value == NULL || attributes[i].valueLen < 4) return HLSE_ERR_API_ERROR; objType = *(HLSE_OBJECT_TYPE*)(attributes[i].value); } else if (attributes[i].type == HLSE_ATTR_OBJECT_INDEX) { if (attributes[i].value == NULL || attributes[i].valueLen < 4) return HLSE_ERR_API_ERROR; objIndex = *(HLSE_OBJECT_INDEX*)(attributes[i].value); } //else if (attributes[i].type == HLSE_ATTR_READ_ONLY) { // if (attributes[i].value == NULL || attributes[i].valueLen < 1) // return HLSE_ERR_API_ERROR; // readOnly = *(U8*)(attributes[i].value); //} else if (attributes[i].type == HLSE_ATTR_OBJECT_VALUE || attributes[i].type == HLSE_ATTR_WRAPPED_OBJECT_VALUE) { valAttrIndex = i; } } *hObject = HLSE_CREATE_HANDLE(readOnly, objType, objIndex); //if (generateKeyPair) { // if (attributes[valAttrIndex].value == NULL || attributes[valAttrIndex].valueLen != sizeof(HLSE_RSA_KEY_GENERATION_PARAMS)) { // *hObject = 0; // return HLSE_ERR_API_ERROR; // } // { // HLSE_RSA_KEY_GENERATION_PARAMS* data = (HLSE_RSA_KEY_GENERATION_PARAMS*)attributes[valAttrIndex].value; // if (data->KEKLen != 0) { // lReturn = CL_GenerateKeyPairWithKEK(data->pPublicKey, data->keyLength, data->keyType, objIndex, data->KEK, data->KEKLen); // } // else { // lReturn = CL_GenerateKeyPair(data->pPublicKey, data->keyLength, data->keyType, objIndex); // } // } //} if (objType == HLSE_KEY_PAIR || objType == HLSE_PUBLIC_KEY) { lReturn = HLSE_CreateRSAKey(*hObject, attributes, attributesNum); } else if (objType == HLSE_SYMMETRIC_KEY) { lReturn = HLSE_CreateSymmetricKey(*hObject, attributes, attributesNum); } else { lReturn = HLSE_SetObjectAttribute(*hObject, &attributes[valAttrIndex]); } if (lReturn != HLSE_SW_OK) { *hObject = 0; return lReturn; } return lReturn; } HLSE_RET_CODE HLSE_EraseObject(HLSE_OBJECT_HANDLE hObject) { // delete a certificate object? return HLSE_ERR_NOT_SUPPORTED; } //******************************************************************* // Cryptographic Operations - defined in HLSECrypto.h //******************************************************************* HLSE_RET_CODE HLSE_GetSupportedMechanisms(HLSE_MECHANISM_TYPE* mechanism, U16* mechanismLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (mechanismLen == NULL) return HLSE_ERR_API_ERROR; #endif if (mechanism == NULL) { *mechanismLen = 21; return HLSE_SW_OK; } if (mechanism != NULL && mechanismLen != NULL && *mechanismLen < 21) { *mechanismLen = 21; return HLSE_ERR_BUF_TOO_SMALL; } *mechanismLen = 21; *mechanism++ = HLSE_SHA1; *mechanism++ = HLSE_SHA256; *mechanism++ = HLSE_AES_ECB_ENCRYPT; *mechanism++ = HLSE_AES_ECB_DECRYPT; *mechanism++ = HLSE_AES_CBC_ENCRYPT; *mechanism++ = HLSE_AES_CBC_DECRYPT; *mechanism++ = HLSE_DES_ECB_ENCRYPT; *mechanism++ = HLSE_DES_ECB_DECRYPT; *mechanism++ = HLSE_DES_CBC_ENCRYPT; *mechanism++ = HLSE_DES_CBC_DECRYPT; *mechanism++ = HLSE_DES_CBC_ISO9797_M1; *mechanism++ = HLSE_DES_CBC_ISO9797_M2; *mechanism++ = HLSE_AES_CBC_ISO9797_M1; *mechanism++ = HLSE_AES_CBC_ISO9797_M2; *mechanism++ = HLSE_RSA_KEY_GEN; *mechanism++ = HLSE_RSA_CRT_KEY_GEN; *mechanism++ = HLSE_RSA_NO_PADDING; *mechanism++ = HLSE_RSA_PKCS1_SHA1; *mechanism++ = HLSE_RSA_PKCS1_SHA256; *mechanism++ = HLSE_RSA_PKCS1_SHA1_PREHASH; *mechanism++ = HLSE_RSA_PKCS1_SHA256_PREHASH; return HLSE_SW_OK; } HLSE_RET_CODE HLSE_GetSupportedMechanismsForObject(HLSE_OBJECT_HANDLE hObject, HLSE_MECHANISM_TYPE* mechanism, U16* mechanismLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (mechanismLen == NULL) return HLSE_ERR_API_ERROR; #endif if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_KEY_PAIR) { if (mechanism == NULL) { *mechanismLen = 7; return HLSE_SW_OK; } if (mechanism != NULL && mechanismLen != NULL && *mechanismLen < 7) { *mechanismLen = 7; return HLSE_ERR_BUF_TOO_SMALL; } *mechanismLen = 7; *mechanism++ = HLSE_RSA_KEY_GEN; *mechanism++ = HLSE_RSA_CRT_KEY_GEN; *mechanism++ = HLSE_RSA_NO_PADDING; *mechanism++ = HLSE_RSA_PKCS1_SHA1; *mechanism++ = HLSE_RSA_PKCS1_SHA256; *mechanism++ = HLSE_RSA_PKCS1_SHA1_PREHASH; *mechanism++ = HLSE_RSA_PKCS1_SHA256_PREHASH; } else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_PUBLIC_KEY) { if (mechanism == NULL) { *mechanismLen = 3; return HLSE_SW_OK; } if (mechanism != NULL && mechanismLen != NULL && *mechanismLen < 3) { *mechanismLen = 3; return HLSE_ERR_BUF_TOO_SMALL; } *mechanismLen = 3; *mechanism++ = HLSE_RSA_NO_PADDING; *mechanism++ = HLSE_RSA_PKCS1_SHA1; *mechanism++ = HLSE_RSA_PKCS1_SHA256; } else if (HLSE_GET_OBJECT_TYPE(hObject) == HLSE_SYMMETRIC_KEY) { if (mechanism == NULL) { *mechanismLen = 12; return HLSE_SW_OK; } if (mechanism != NULL && mechanismLen != NULL && *mechanismLen < 12) { *mechanismLen = 12; return HLSE_ERR_BUF_TOO_SMALL; } *mechanismLen = 12; *mechanism++ = HLSE_AES_ECB_ENCRYPT; *mechanism++ = HLSE_AES_ECB_DECRYPT; *mechanism++ = HLSE_AES_CBC_ENCRYPT; *mechanism++ = HLSE_AES_CBC_DECRYPT; *mechanism++ = HLSE_DES_ECB_ENCRYPT; *mechanism++ = HLSE_DES_ECB_DECRYPT; *mechanism++ = HLSE_DES_CBC_ENCRYPT; *mechanism++ = HLSE_DES_CBC_DECRYPT; *mechanism++ = HLSE_DES_CBC_ISO9797_M1; *mechanism++ = HLSE_DES_CBC_ISO9797_M2; *mechanism++ = HLSE_AES_CBC_ISO9797_M1; *mechanism++ = HLSE_AES_CBC_ISO9797_M2; } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLSE_Digest(HLSE_MECHANISM_INFO* pMechanismType, U8* inData, U16 inDataLen, U8* outDigest, U16* outDigestLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if ((pMechanismType == NULL) || inData == NULL || outDigestLen == NULL) { return HLSE_ERR_API_ERROR; } #endif if (pMechanismType->mechanism == HLSE_SHA1) { if (outDigest == NULL) { *outDigestLen = 20; return HLSE_SW_OK; } if (outDigest != NULL && outDigestLen != NULL && *outDigestLen < 20) { *outDigestLen = 20; return HLSE_ERR_BUF_TOO_SMALL; } return CL_ComputeDigest(inData, (U16)inDataLen, outDigest, outDigestLen, eSHA1); } else if (pMechanismType->mechanism == HLSE_SHA256) { if (outDigest == NULL) { *outDigestLen = 32; return HLSE_SW_OK; } if (outDigest != NULL && outDigestLen != NULL && *outDigestLen < 32) { *outDigestLen = 32; return HLSE_ERR_BUF_TOO_SMALL; } return CL_ComputeDigest(inData, (U16)inDataLen, outDigest, outDigestLen, eSHA256); } return HLSE_ERR_API_ERROR; } //HLSE_RET_CODE HLSE_DigestInit(HLSE_MECHANISM_INFO* pMechanismType, HLSE_CONTEXT_HANDLE* hContext) //{ // //} // //HLSE_RET_CODE HLSE_DigestUpdate(HLSE_CONTEXT_HANDLE hContext, U8* inDataPart, U16 inDataPartLen) //{ // //} // //HLSE_RET_CODE HLSE_DigestFinal(HLSE_CONTEXT_HANDLE hContext, U8* outDigest, U16* outDigestLen) //{ // //} HLSE_RET_CODE HLSE_Sign(HLSE_MECHANISM_INFO* pMechanismType, HLSE_OBJECT_HANDLE hObject, U8* inData, U16 inDataLen, U8* outSignature, U16* outSignatureLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if ((pMechanismType == NULL) || (inData == NULL) || (outSignatureLen == NULL)) { return HLSE_ERR_API_ERROR; } #endif // RSA if (pMechanismType->mechanism == HLSE_RSA_NO_PADDING || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA256) { if (outSignature == NULL) { *outSignatureLen = 256; return HLSE_SW_OK; } if (outSignature != NULL && outSignatureLen != NULL && *outSignatureLen < 256) { *outSignatureLen = 256; return HLSE_ERR_BUF_TOO_SMALL; } return CL_AsymmetricCrypt(inData, (U16)inDataLen, eAsymSign, (pMechanismType->mechanism == HLSE_RSA_NO_PADDING ? eRSA_NOPADDING : pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eRSA_SHA1_PKCS1 : eRSA_SHA256_PKCS1), HLSE_GET_OBJECT_INDEX(hObject), outSignature, outSignatureLen); } else if (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1_PREHASH || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA256_PREHASH) { // keyLength is passed as the mechanism's parameter // inData assumed to be the hash U8 allData[512]; U16 hashLen = (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1_PREHASH ? 20 : 32); U32 keyLen; U32 PSLen; U8 sha1OID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; U8 sha256OID[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; if (outSignature == NULL) { *outSignatureLen = 256; return HLSE_SW_OK; } if (outSignature != NULL && outSignatureLen != NULL && *outSignatureLen < 256) { *outSignatureLen = 256; return HLSE_ERR_BUF_TOO_SMALL; } if (inDataLen != hashLen) { return HLSE_ERR_HASH_COMPARE_FAILS; } if (pMechanismType->pParameter == NULL || pMechanismType->ulParameterLen != sizeof(U32)) { return HLSE_ERR_API_ERROR; } keyLen = *((U32*)pMechanismType->pParameter); allData[0] = 0x00; allData[1] = 0x01; PSLen = keyLen - 3 - (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1_PREHASH ? sizeof(sha1OID) : sizeof(sha256OID)) - hashLen; memset(&(allData[2]), 0xFF, PSLen); allData[2 + PSLen] = 0x00; if (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1_PREHASH) { memcpy(&(allData[3 + PSLen]), sha1OID, sizeof(sha1OID)); memcpy(&(allData[3 + PSLen + sizeof(sha1OID)]), inData, hashLen); } else { memcpy(&(allData[3 + PSLen]), sha256OID, sizeof(sha256OID)); memcpy(&(allData[3 + PSLen + sizeof(sha256OID)]), inData, hashLen); } return CL_AsymmetricCrypt(allData, (U16)keyLen, eAsymDecrypt, eRSA_NOPADDING, HLSE_GET_OBJECT_INDEX(hObject), outSignature, outSignatureLen); } // DES else if (pMechanismType->mechanism == HLSE_DES_CBC_ISO9797_M1 || pMechanismType->mechanism == HLSE_DES_CBC_ISO9797_M2) { if (outSignature == NULL) { *outSignatureLen = 24; return HLSE_SW_OK; } if (outSignature != NULL && outSignatureLen != NULL && *outSignatureLen < 24) { *outSignatureLen = 24; return HLSE_ERR_BUF_TOO_SMALL; } return CL_SymmetricCrypt(inData, (U16)inDataLen, eSignMac, (pMechanismType->mechanism == HLSE_DES_CBC_ISO9797_M1 ? eDES_CBC_ISO9797_M1 : eDES_CBC_ISO9797_M2), HLSE_GET_OBJECT_INDEX(hObject), outSignature, outSignatureLen); } // AES else if (pMechanismType->mechanism == HLSE_AES_CBC_ISO9797_M1 || pMechanismType->mechanism == HLSE_AES_CBC_ISO9797_M2) { if (outSignature == NULL) { *outSignatureLen = 16; return HLSE_SW_OK; } if (outSignature != NULL && outSignatureLen != NULL && *outSignatureLen < 16) { *outSignatureLen = 16; return HLSE_ERR_BUF_TOO_SMALL; } return CL_SymmetricCrypt(inData, (U16)inDataLen, eSignMac, (pMechanismType->mechanism == HLSE_AES_CBC_ISO9797_M1 ? eAES_CBC_ISO9797_M1 : eAES_CBC_ISO9797_M2), HLSE_GET_OBJECT_INDEX(hObject), outSignature, outSignatureLen); } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLSE_VerifySignature(HLSE_MECHANISM_INFO* pMechanismType, HLSE_OBJECT_HANDLE hObject, U8* inData, U16 inDataLen, U8* inSignature, U16 inSignatureLen) { U8* allData = NULL; #ifndef HLSE_IGNORE_PARAM_CHECK if ((pMechanismType == NULL) || (inData == NULL) || (inSignature == NULL)) { return HLSE_ERR_API_ERROR; } #endif // RSA if (pMechanismType->mechanism == HLSE_RSA_NO_PADDING) { HLSE_RET_CODE lReturn = 0; allData = (U8*)malloc(inDataLen + inSignatureLen); memcpy(allData, inData, inDataLen); memcpy(&allData[inDataLen], inSignature, inSignatureLen); lReturn = CL_AsymmetricCrypt(allData, (U16)(inDataLen + inSignatureLen), eAsymVerifySign, (pMechanismType->mechanism == HLSE_RSA_NO_PADDING ? eRSA_NOPADDING : pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eRSA_SHA1_PKCS1 : eRSA_SHA256_PKCS1), HLSE_GET_OBJECT_INDEX(hObject), inSignature, &inSignatureLen); free(allData); if (lReturn != HLSE_SW_OK) return lReturn; return HLSE_SW_OK; } else if (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA256) { HLSE_RET_CODE lReturn = 0; U16 retDataLen = 512; U8 hash[100]; U16 hashLen = (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? 20 : 32); allData = (U8*)malloc(512); lReturn = CL_AsymmetricCrypt(inSignature, inSignatureLen, eAsymEncrypt, eRSA_NOPADDING, //(pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eRSA_SHA1_PKCS1 : eRSA_SHA256_PKCS1), HLSE_GET_OBJECT_INDEX(hObject), allData, &retDataLen); if (lReturn == HLSE_SW_OK) { // need to compute the hash of the data in order to compare with lReturn = CL_ComputeDigest(inData, inDataLen, hash, &hashLen, (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eSHA1 : eSHA256)); // need to remove padding if (lReturn == HLSE_SW_OK) { if (allData[0] != 0x00 || allData[1] != 0x01) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } else { unsigned long index = 2; for (; allData[index] != 0x00 && index < retDataLen; index++) { if (allData[index] != 0xFF) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } } index++; // now points to first data byte if (index < 11 || retDataLen <= hashLen) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } if (lReturn == HLSE_SW_OK) { if (memcmp(hash, &allData[retDataLen - hashLen], hashLen)) lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } } } } free(allData); if (lReturn != HLSE_SW_OK) return lReturn; return HLSE_SW_OK; } else if (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1_PREHASH || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA256_PREHASH) { // inData is the hash of the data HLSE_RET_CODE lReturn = 0; U16 retDataLen = 512; U8 hash[100]; U16 hashLen = (pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1_PREHASH ? 20 : 32); if (inDataLen != hashLen) { return HLSE_ERR_HASH_COMPARE_FAILS; } allData = (U8*)malloc(512); lReturn = CL_AsymmetricCrypt(inSignature, inSignatureLen, eAsymEncrypt, eRSA_NOPADDING, //(pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eRSA_SHA1_PKCS1 : eRSA_SHA256_PKCS1), HLSE_GET_OBJECT_INDEX(hObject), allData, &retDataLen); if (inDataLen != hashLen) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } if (lReturn == HLSE_SW_OK) { // no need to compute the hash of the data memcpy(hash, inData, inDataLen); // need to remove padding if (allData[0] != 0x00 || allData[1] != 0x01) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } else { unsigned long index = 2; for (; allData[index] != 0x00 && index < retDataLen; index++) { if (allData[index] != 0xFF) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } } index++; // now points to first data byte if (index < 11) { lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } if (lReturn == HLSE_SW_OK) { if (memcmp(hash, &allData[retDataLen - hashLen], hashLen)) lReturn = HLSE_ERR_HASH_COMPARE_FAILS; } } } free(allData); if (lReturn != HLSE_SW_OK) return lReturn; return HLSE_SW_OK; } // DES else if (pMechanismType->mechanism == HLSE_DES_CBC_ISO9797_M1 || pMechanismType->mechanism == HLSE_DES_CBC_ISO9797_M2) { HLSE_RET_CODE lReturn = 0; allData = (U8*)malloc(inDataLen + inSignatureLen); memcpy(allData, inData, inDataLen); memcpy(&allData[inDataLen], inSignature, inSignatureLen); lReturn = CL_SymmetricCrypt(allData, (U16)(inDataLen + inSignatureLen), eVerifyMac, (pMechanismType->mechanism == HLSE_DES_CBC_ISO9797_M1 ? eDES_CBC_ISO9797_M1 : eDES_CBC_ISO9797_M2), HLSE_GET_OBJECT_INDEX(hObject), inSignature, &inSignatureLen); free(allData); if (lReturn != HLSE_SW_OK) return lReturn; return HLSE_SW_OK; } // AES else if (pMechanismType->mechanism == HLSE_AES_CBC_ISO9797_M1 || pMechanismType->mechanism == HLSE_AES_CBC_ISO9797_M2) { HLSE_RET_CODE lReturn = 0; allData = (U8*)malloc(inDataLen + inSignatureLen); memcpy(allData, inData, inDataLen); memcpy(&allData[inDataLen], inSignature, inSignatureLen); lReturn = CL_SymmetricCrypt(inData, (U16)inDataLen, eVerifyMac, (pMechanismType->mechanism == HLSE_AES_CBC_ISO9797_M1 ? eAES_CBC_ISO9797_M1 : eAES_CBC_ISO9797_M2), HLSE_GET_OBJECT_INDEX(hObject), inSignature, &inSignatureLen); free(allData); if (lReturn != HLSE_SW_OK) return lReturn; return HLSE_SW_OK; } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLSE_DeriveKey(HLSE_MECHANISM_INFO* pMechanismType, HLSE_OBJECT_HANDLE hObject, U8* outDerivedKey, U16* outDerivedKeyLen) { return HLSE_ERR_NOT_SUPPORTED; } HLSE_RET_CODE HLSE_Encrypt(HLSE_MECHANISM_INFO* pMechanismType, HLSE_OBJECT_HANDLE hObject, U8* inData, U16 inDataLen, U8* outData, U16* outDataLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if ((pMechanismType == NULL) || (inData == NULL) || (outDataLen == NULL)) { return HLSE_ERR_API_ERROR; } #endif // RSA if (pMechanismType->mechanism == HLSE_RSA_NO_PADDING || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA256) { if (outDataLen == NULL) { *outDataLen = 256; return HLSE_SW_OK; } if (outData != NULL && outDataLen != NULL && *outDataLen < 256) { *outDataLen = 256; return HLSE_ERR_BUF_TOO_SMALL; } return CL_AsymmetricCrypt(inData, (U16)inDataLen, eAsymEncrypt, (pMechanismType->mechanism == HLSE_RSA_NO_PADDING ? eRSA_NOPADDING : pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eRSA_SHA1_PKCS1 : eRSA_SHA256_PKCS1), HLSE_GET_OBJECT_INDEX(hObject), outData, outDataLen); } // DES else if (pMechanismType->mechanism == HLSE_DES_ECB_ENCRYPT || pMechanismType->mechanism == HLSE_DES_CBC_ENCRYPT) { if (outDataLen == NULL) { *outDataLen = inDataLen; return HLSE_SW_OK; } if (outData != NULL && outDataLen != NULL && *outDataLen < inDataLen) { *outDataLen = inDataLen; return HLSE_ERR_BUF_TOO_SMALL; } return CL_SymmetricCrypt(inData, (U16)inDataLen, eEncrypt, (pMechanismType->mechanism == HLSE_DES_ECB_ENCRYPT ? eDES_ECB_NOPADDING : eDES_CBC_NOPADDING), HLSE_GET_OBJECT_INDEX(hObject), outData, outDataLen); } // AES else if (pMechanismType->mechanism == HLSE_AES_ECB_ENCRYPT || pMechanismType->mechanism == HLSE_AES_CBC_ENCRYPT) { if (outDataLen == NULL) { *outDataLen = inDataLen; return HLSE_SW_OK; } if (outData != NULL && outDataLen != NULL && *outDataLen < inDataLen) { *outDataLen = inDataLen; return HLSE_ERR_BUF_TOO_SMALL; } return CL_SymmetricCrypt(inData, (U16)inDataLen, eEncrypt, (pMechanismType->mechanism == HLSE_AES_ECB_ENCRYPT ? eAES_ECB_NOPADDING : eAES_CBC_NOPADDING), HLSE_GET_OBJECT_INDEX(hObject), outData, outDataLen); } return HLSE_ERR_API_ERROR; } HLSE_RET_CODE HLSE_Decrypt(HLSE_MECHANISM_INFO* pMechanismType, HLSE_OBJECT_HANDLE hObject, U8* inData, U16 inDataLen, U8* outData, U16* outDataLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if ((pMechanismType == NULL) || (inData == NULL) || (outDataLen == NULL)) { return HLSE_ERR_API_ERROR; } #endif // RSA if (pMechanismType->mechanism == HLSE_RSA_NO_PADDING || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 || pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA256) { if (outDataLen == NULL) { *outDataLen = 256; return HLSE_SW_OK; } if (outData != NULL && outDataLen != NULL && *outDataLen < 256) { *outDataLen = 256; return HLSE_ERR_BUF_TOO_SMALL; } return CL_AsymmetricCrypt(inData, (U16)inDataLen, eAsymDecrypt, (pMechanismType->mechanism == HLSE_RSA_NO_PADDING ? eRSA_NOPADDING : pMechanismType->mechanism == HLSE_RSA_PKCS1_SHA1 ? eRSA_SHA1_PKCS1 : eRSA_SHA256_PKCS1), HLSE_GET_OBJECT_INDEX(hObject), outData, outDataLen); } // DES else if (pMechanismType->mechanism == HLSE_DES_ECB_DECRYPT || pMechanismType->mechanism == HLSE_DES_CBC_DECRYPT) { if (outDataLen == NULL) { *outDataLen = inDataLen; return HLSE_SW_OK; } if (outData != NULL && outDataLen != NULL && *outDataLen < inDataLen) { *outDataLen = inDataLen; return HLSE_ERR_BUF_TOO_SMALL; } return CL_SymmetricCrypt(inData, (U16)inDataLen, eDecrypt, (pMechanismType->mechanism == HLSE_DES_ECB_DECRYPT ? eDES_ECB_NOPADDING : eDES_CBC_NOPADDING), HLSE_GET_OBJECT_INDEX(hObject), outData, outDataLen); } // AES else if (pMechanismType->mechanism == HLSE_AES_ECB_ENCRYPT || pMechanismType->mechanism == HLSE_AES_CBC_ENCRYPT) { if (outDataLen == NULL) { *outDataLen = inDataLen; return HLSE_SW_OK; } if (outData != NULL && outDataLen != NULL && *outDataLen < inDataLen) { *outDataLen = inDataLen; return HLSE_ERR_BUF_TOO_SMALL; } return CL_SymmetricCrypt(inData, (U16)inDataLen, eDecrypt, (pMechanismType->mechanism == HLSE_AES_ECB_DECRYPT ? eAES_ECB_NOPADDING : eAES_CBC_NOPADDING), HLSE_GET_OBJECT_INDEX(hObject), outData, outDataLen); } return HLSE_ERR_NOT_SUPPORTED; } //CK_ECDH1_DERIVE_PARAMS params; //CK_MECHANISM mechanism = { CKM_ECDH1_DERIVE, ¶ms, sizeof(params) }; //******************************************************************* // Module Operations - defined in HLSEMisc.h //******************************************************************* // Debug functions HLSE_RET_CODE HLSE_DisablePlainInjectionMode() { return CL_DisablePlainInjectionMode(); } HLSE_RET_CODE HLSE_ResetContents() { // the cached gp table no lnger reflects the actual data in the GP storage and has to be re-read // gMappingTableRead = 0; return CL_ResetContents(); } HLSE_RET_CODE HLSE_NormalizeECCSignature(U8 *signature, U16 signatureLen, U8 *normalizedSignature, U16 *normalizedSignatureLen) { return HLSE_ERR_NOT_SUPPORTED; } //******************************************************************* // Communication and Secure Channel - defined in HLSEComm.h //******************************************************************* HLSE_RET_CODE HLSE_CloseConnection(HLSE_CLOSE_CONNECTION_MODE mode) { if ((mode != HLSE_CLOSE_CONNECTION_RESET) && (mode != HLSE_CLOSE_CONNECTION_NO_RESET)) { return HLSE_ERR_API_ERROR; } return SM_Close(NULL, (U8)mode); } HLSE_RET_CODE HLSE_Connect(HLSE_CONNECTION_PARAMS* params, HLSE_COMMUNICATION_STATE *commState) { #if defined(SMCOM_JRCP_V1) || defined(SMCOM_JRCP_V2) || defined(RJCT_VCOM) SmCommState_t a71SmCommState; a71SmCommState.connType = params->connType; U16 lReturn; #ifndef HLSE_IGNORE_PARAM_CHECK if (params == NULL || commState == NULL || params->pParameter == NULL) { return HLSE_ERR_API_ERROR; } #endif // Clean the global memory memset(&sPublicKeysLen, 0, sizeof(sPublicKeysLen)); memset(&sPublicKeys, 0, sizeof(sPublicKeys)); //if (params->appletAIDLength) // lReturn = SM_RjctConnectWithAID((const char *)params->pParameter, &a71SmCommState, params->appletAID, params->appletAIDLength, commState->atr, &(commState->atrLen)); //else LOG_I("==========From wrapper========"); lReturn = SM_RjctConnect(NULL, (const char *)params->pParameter, &a71SmCommState, commState->atr, &(commState->atrLen)); if (lReturn != SW_OK) { return lReturn; } memcpy(commState, &a71SmCommState, sizeof(a71SmCommState)); return HLSE_SW_OK; #else SmCommState_t a71SmCommState; U16 lReturn; #ifndef HLSE_IGNORE_PARAM_CHECK if (params == NULL || commState == NULL || params->pParameter == NULL) { return HLSE_ERR_API_ERROR; } #endif //if (params->appletAIDLength) // lReturn = SM_ConnectWithAID(&a71SmCommState, params->appletAID, params->appletAIDLength, commState->atr, &(commState->atrLen)); //else lReturn = SM_Connect(NULL, &a71SmCommState, commState->atr, &(commState->atrLen)); if (lReturn != SW_OK) { return lReturn; } memcpy(commState, &a71SmCommState, sizeof(a71SmCommState)); return HLSE_SW_OK; #endif } HLSE_RET_CODE HLSE_ResumeConnection(HLSE_COMMUNICATION_STATE *commState, HLSE_SECURE_CHANNEL_SESSION_STATE *smState) { #ifndef HLSE_IGNORE_PARAM_CHECK if (commState == NULL || smState == NULL ) { return HLSE_ERR_API_ERROR; } #endif if (smState->type != HLSE_SCP03 || smState->ulParameterLen != sizeof(HLSE_SCP03_SESSION_STATE)) return HLSE_ERR_MEMORY; #ifdef SECURE_CHANNEL_SUPPORTED return SM_ResumeConnection((SmCommState_t *)commState, (Scp03SessionState_t*)(smState->pParameter)); #else return HLSE_ERR_NOT_SUPPORTED; #endif } HLSE_RET_CODE HLSE_SendAPDU(U8 *cmd, U16 cmdLen, U8 *resp, U16 *respLen) { #ifndef HLSE_IGNORE_PARAM_CHECK if (cmd == NULL || resp == NULL) { return HLSE_ERR_API_ERROR; } #endif return SM_SendAPDU(cmd, cmdLen, resp, respLen); } HLSE_RET_CODE HLSE_SCP_Subscribe(HLSE_SCP_SignalFunction callback, void *context) { #ifndef HLSE_IGNORE_PARAM_CHECK if (callback == NULL) { return HLSE_ERR_API_ERROR; } #endif #ifdef SECURE_CHANNEL_SUPPORTED return SCP_Subscribe((SCP_SignalFunction)callback, context); #else return HLSE_ERR_NOT_SUPPORTED; #endif } HLSE_RET_CODE HLSE_SMChannelAuthenticate(HLSE_SECURE_CHANNEL_ESTABLISH_PARAMS* params, HLSE_SECURE_CHANNEL_STATE* channelState) { #ifdef USE_SCP02 HLSE_SECURE_CHANNEL_SCP02_ESTABLISH_PARAMS* scp02EstablishParams; HLSE_SCP02_CHANNEL_STATE* scp02ChannelState; U16 counterLen = 3; #endif U16 lReturn = HLSE_ERR_API_ERROR; #ifndef HLSE_IGNORE_PARAM_CHECK if (params == NULL || channelState == NULL) { return lReturn; } if (params->type != HLSE_SCP02 || params->pParameter == NULL || params->ulParameterLen != sizeof(HLSE_SECURE_CHANNEL_SCP02_ESTABLISH_PARAMS)) return HLSE_ERR_MEMORY; if (channelState->type != HLSE_SCP02 || channelState->pParameter == NULL || channelState->ulParameterLen != sizeof(HLSE_SCP02_CHANNEL_STATE)) return HLSE_ERR_MEMORY; #endif #ifdef USE_SCP02 scp02EstablishParams = (HLSE_SECURE_CHANNEL_SCP02_ESTABLISH_PARAMS*)(params->pParameter); scp02ChannelState = (HLSE_SCP02_CHANNEL_STATE*)(channelState->pParameter); lReturn = SCP02_Authenticate(scp02EstablishParams->keyEnc, scp02EstablishParams->keyMac, scp02EstablishParams->keyDek, SCP_KEY_SIZE, scp02ChannelState->cCounter, &counterLen); if (lReturn != SW_OK) return lReturn; channelState->ulParameterLen = counterLen; return HLSE_SW_OK; #else return lReturn; #endif } HLSE_RET_CODE HLSE_SMChannelGetScpSessionState(HLSE_SECURE_CHANNEL_SESSION_STATE *channelState) { #ifndef HLSE_IGNORE_PARAM_CHECK if (channelState == NULL) { return HLSE_ERR_API_ERROR; } if (channelState->type != HLSE_SCP03 || channelState->pParameter == NULL || channelState->ulParameterLen != sizeof(HLSE_SCP03_SESSION_STATE)) return HLSE_ERR_MEMORY; #endif return SCP_GetScpSessionState((Scp03SessionState_t *)(channelState->pParameter)); } HLSE_RET_CODE HLSE_SMChannelSetScpSessionState(HLSE_SECURE_CHANNEL_SESSION_STATE *channelState) { #ifndef HLSE_IGNORE_PARAM_CHECK if (channelState == NULL) { return HLSE_ERR_API_ERROR; } #endif if (channelState->type != HLSE_SCP03 || channelState->pParameter == NULL || channelState->ulParameterLen != sizeof(HLSE_SCP03_SESSION_STATE)) return HLSE_ERR_MEMORY; SCP_SetScpSessionState((Scp03SessionState_t *)(channelState->pParameter)); return HLSE_SW_OK; } //******************************************************************* // Helper functions //*******************************************************************