TEE_Result TEE_AEUpdate(TEE_OperationHandle op, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { size_t req_dlen; if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0)) TEE_Panic(0); if (op->info.operationClass != TEE_OPERATION_AE) TEE_Panic(0); if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ req_dlen = ROUNDDOWN(op->buffer_offs + srcLen, op->block_size); if (*destLen < req_dlen) { *destLen = req_dlen; return TEE_ERROR_SHORT_BUFFER; } tee_buffer_update(op, utee_authenc_update_payload, srcData, srcLen, destData, destLen); return TEE_SUCCESS; }
TEE_Result TEE_CipherDoFinal(TEE_OperationHandle op, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { TEE_Result res; uint8_t *dst = destData; size_t acc_dlen = 0; size_t tmp_dlen; size_t req_dlen; if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0)) TEE_Panic(0); if (op->info.operationClass != TEE_OPERATION_CIPHER) TEE_Panic(0); if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); /* * Check that the final block doesn't require padding for those * algorithms that requires client to supply padding. */ if (op->info.algorithm == TEE_ALG_AES_ECB_NOPAD || op->info.algorithm == TEE_ALG_AES_CBC_NOPAD || op->info.algorithm == TEE_ALG_DES_ECB_NOPAD || op->info.algorithm == TEE_ALG_DES_CBC_NOPAD || op->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || op->info.algorithm == TEE_ALG_DES3_CBC_NOPAD) { if (((op->buffer_offs + srcLen) % op->block_size) != 0) return TEE_ERROR_BAD_PARAMETERS; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ req_dlen = op->buffer_offs + srcLen; if (*destLen < req_dlen) { *destLen = req_dlen; return TEE_ERROR_SHORT_BUFFER; } tmp_dlen = *destLen - acc_dlen; tee_buffer_update(op, utee_cipher_update, srcData, srcLen, dst, &tmp_dlen); dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; res = utee_cipher_final(op->state, op->buffer, op->buffer_offs, dst, &tmp_dlen); if (res != TEE_SUCCESS) TEE_Panic(res); acc_dlen += tmp_dlen; op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; *destLen = acc_dlen; return TEE_SUCCESS; }
TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle op, const void *srcData, size_t srcLen, void *destData, size_t *destLen, void *tag, size_t *tagLen) { TEE_Result res; uint8_t *dst = destData; size_t acc_dlen = 0; size_t tmp_dlen; size_t req_dlen; if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0) || tag == NULL || tagLen == NULL) TEE_Panic(0); if (op->info.operationClass != TEE_OPERATION_AE) TEE_Panic(0); if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ req_dlen = op->buffer_offs + srcLen; if (*destLen < req_dlen) { *destLen = req_dlen; return TEE_ERROR_SHORT_BUFFER; } /* * Need to check this before update_payload since sync would be lost if * we return short buffer after that. */ if (*tagLen < op->ae_tag_len) { *tagLen = op->ae_tag_len; return TEE_ERROR_SHORT_BUFFER; } tmp_dlen = *destLen - acc_dlen; tee_buffer_update(op, utee_authenc_update_payload, srcData, srcLen, dst, &tmp_dlen); dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; res = utee_authenc_enc_final(op->state, op->buffer, op->buffer_offs, dst, &tmp_dlen, tag, tagLen); if (res != TEE_SUCCESS) TEE_Panic(res); acc_dlen += tmp_dlen; *destLen = acc_dlen; op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; return res; }
TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res; size_t req_dlen; uint64_t dl; if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen, operation->block_size); if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; goto out; } dl = *destLen; res = tee_buffer_update(operation, utee_authenc_update_payload, srcData, srcLen, destData, &dl); *destLen = dl; operation->operationState = TEE_OPERATION_STATE_ACTIVE; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; }
TEE_Result TEE_CipherUpdate(TEE_OperationHandle op, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { size_t req_dlen; if (op == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0)) TEE_Panic(0); if (op->info.operationClass != TEE_OPERATION_CIPHER) TEE_Panic(0); if ((op->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); /* Calculate required dlen */ req_dlen = ((op->buffer_offs + srcLen) / op->block_size) * op->block_size; if (op->buffer_two_blocks) { if (req_dlen > op->block_size * 2) req_dlen -= op->block_size * 2; else req_dlen = 0; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ if (*destLen < req_dlen) { *destLen = req_dlen; return TEE_ERROR_SHORT_BUFFER; } tee_buffer_update(op, utee_cipher_update, srcData, srcLen, destData, destLen); return TEE_SUCCESS; }
TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res; size_t req_dlen; uint64_t dl; if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.operationClass != TEE_OPERATION_CIPHER) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* Calculate required dlen */ req_dlen = ((operation->buffer_offs + srcLen) / operation->block_size) * operation->block_size; if (operation->buffer_two_blocks) { if (req_dlen > operation->block_size * 2) req_dlen -= operation->block_size * 2; else req_dlen = 0; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; goto out; } dl = *destLen; res = tee_buffer_update(operation, utee_cipher_update, srcData, srcLen, destData, &dl); *destLen = dl; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(0); return res; }
TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen, void *tag, uint32_t tagLen) { TEE_Result res; uint8_t *dst = destData; size_t acc_dlen = 0; uint64_t tmp_dlen; size_t req_dlen; if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0) || (tag == NULL && tagLen != 0)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ req_dlen = operation->buffer_offs + srcLen; if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; goto out; } tmp_dlen = *destLen - acc_dlen; res = tee_buffer_update(operation, utee_authenc_update_payload, srcData, srcLen, dst, &tmp_dlen); if (res != TEE_SUCCESS) goto out; dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; res = utee_authenc_dec_final(operation->state, operation->buffer, operation->buffer_offs, dst, &tmp_dlen, tag, tagLen); if (res != TEE_SUCCESS) goto out; /* Supplied tagLen should match what we initiated with */ if (tagLen != operation->ae_tag_len) res = TEE_ERROR_MAC_INVALID; acc_dlen += tmp_dlen; *destLen = acc_dlen; operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_MAC_INVALID) TEE_Panic(res); return res; }
TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen, void *tag, uint32_t *tagLen) { TEE_Result res; uint8_t *dst = destData; size_t acc_dlen = 0; uint64_t tmp_dlen; size_t req_dlen; uint64_t tl; if (operation == TEE_HANDLE_NULL || (srcData == NULL && srcLen != 0) || destLen == NULL || (destData == NULL && *destLen != 0) || tag == NULL || tagLen == NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. * * Need to check this before update_payload since sync would be lost if * we return short buffer after that. */ res = TEE_ERROR_GENERIC; req_dlen = operation->buffer_offs + srcLen; if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; } if (*tagLen < operation->ae_tag_len) { *tagLen = operation->ae_tag_len; res = TEE_ERROR_SHORT_BUFFER; } if (res == TEE_ERROR_SHORT_BUFFER) goto out; tl = *tagLen; tmp_dlen = *destLen - acc_dlen; if (operation->block_size > 1) { res = tee_buffer_update(operation, utee_authenc_update_payload, srcData, srcLen, dst, &tmp_dlen); if (res != TEE_SUCCESS) goto out; dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; res = utee_authenc_enc_final(operation->state, operation->buffer, operation->buffer_offs, dst, &tmp_dlen, tag, &tl); } else { res = utee_authenc_enc_final(operation->state, srcData, srcLen, dst, &tmp_dlen, tag, &tl); } *tagLen = tl; if (res != TEE_SUCCESS) goto out; acc_dlen += tmp_dlen; *destLen = acc_dlen; operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; }