📄 aacs_api.c
字号:
/* * * Copyright (c) Sigma Designs, Inc. 2005-2006. All rights reserved. * */#ifdef TEST_TIMING#define ALLOW_OS_CODE#include <sys/time.h>#include <time.h>#include <stdio.h>static struct timeval tv1, tv2;#endif /* TEST_TIMING */#include "rmdrm/include/rmdrm.h"#include "aacs_api.h"#include "aacs_interface.h"#include "aacs_cci.h"#ifdef TEST_TIMINGstatic void timing_info(struct timeval *tv1, struct timeval *tv2, const RMascii *message){ RMint32 tv_sec, tv_usec; tv_sec = tv2->tv_sec - tv1->tv_sec; tv_usec = tv2->tv_usec - tv1->tv_usec; if (tv_usec < 0) { tv_sec--; tv_usec = 1000000 + tv_usec; } printf("TIMING INFO %s : %lu s %lu us\n", message, tv_sec, tv_usec);}#endif /* TEST_TIMING */#ifdef TEST_TIMING#define TIMING_START() gettimeofday(&tv1, NULL);#else#define TIMING_START()#endif /* TEST_TIMING */#ifdef TEST_TIMING#define TIMING_END() gettimeofday(&tv2, NULL); timing_info(&tv1, &tv2, __func__);#else#define TIMING_END()#endif /* TEST_TIMING *//* handle to the AACS shared library */static struct aacs_interface_s *g_aacs;/** * Open AACS module. * * The AACS module also needs some RUA memory, already mapped, in order to * communicate bigger chunks of data to the XPU efficiently. The gbus address * and the mapped address should be given as parameters, along with the size * allocated. Also, to identify which XPU to use (in case of several chips), * chip should be set to the requested index (0 for the first one, ...). * * @param gbus_memory - gbus address of memory allocated for AACS * @param mapped_memory - CPU virtual address of memory allocated for AACS * @param mem_size - size of memory allocated for AACS * @param chip - chip index * @return AACS handle, NULL on error (and aacs_error is set) */struct aacs_handle * aacs_open(RMuint32 gbus_memory, RMuint32 mapped_memory, RMuint32 mem_size, RMuint32 chip){ struct aacs_handle *handle = NULL; TIMING_START(); /* Try to load the shared library if not done yet */ if (g_aacs == NULL) g_aacs = load_drm(AACS, NULL); if (g_aacs) handle = g_aacs->aacs_open(gbus_memory, mapped_memory, mem_size, chip); TIMING_END(); return handle;}/** * Open AACS module (preloaded). * * The AACS module also needs some RUA memory, already mapped, in order to * communicate bigger chunks of data to the XPU efficiently. The gbus address * and the mapped address should be given as parameters, along with the size * allocated. Also, to identify which XPU to use (in case of several chips), * chip should be set to the requested index (0 for the first one, ...). * * @param gbus_memory - gbus address of memory allocated for AACS * @param mapped_memory - CPU virtual address of memory allocated for AACS * @param mem_size - size of memory allocated for AACS * @param chip - chip index * @param xtask_slot_id - image slot # for the preloaded xtask. * @param dmx_cphr - params for Demux CipherOnlyTask AES decryption (NULL to use XPU AES cipher) * (pointer must point to RUA memory!) * * @return AACS handle, NULL on error (and aacs_error is set) */struct aacs_handle * aacs_open_preloaded(RMuint32 gbus_memory, RMuint32 mapped_memory, RMuint32 mem_size, RMuint32 chip, RMuint32 xtask_slot_id, struct demux_cipher *dmx_cphr){ struct aacs_handle *handle = NULL; TIMING_START(); /* Try to load the shared library if not done yet */ if (g_aacs == NULL) g_aacs = load_drm(AACS, NULL); if (g_aacs) handle = g_aacs->aacs_open_preloaded(gbus_memory, mapped_memory, mem_size, chip, xtask_slot_id, dmx_cphr); TIMING_END(); return handle;}/** * Instanciates a new AACS engine. * * To manipulate the AACS device (drive, network, ...), a table of callbacks * and a callback context have to be provided. * * @param aacs_handle - handle on the opened library * @param flags - flags (BD-ROM/BD-RE/HD-DVD...) * @param callbacks - table of callbacks, see aacs_callbacks.h * @param callback_context - context holding drive and non volatile info * @return AACS context, NULL on error (and aacs_error is set) */struct aacs_context * aacs_instantiate(struct aacs_handle *aacs_handle, RMuint32 flags, struct aacs_callbacks_s *callbacks, void *callback_context){ struct aacs_context *aacs_context = NULL; TIMING_START(); if (g_aacs) aacs_context = g_aacs->aacs_instantiate(aacs_handle,flags,callbacks,callback_context); TIMING_END(); return aacs_context;}/** * Authenticate the content * * This function authenticates the content and performs various other * operations, depending on the AACS flavor chosen. For BD-ROM, it verifies the * DRL, computes the Bus Key, the Media Key and processes the SKB(s). * * @param aacs_context - aacs_context initialized with init_aacs * @return RM_OK on success */RMstatus aacs_authenticate(struct aacs_context *aacs_context){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_authenticate(aacs_context); TIMING_END(); return status;}/** * Performs AACS content revocation (content hashing) * * @param aacs_context - aacs_context initialized with init_aacs * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_content_revocation(struct aacs_context *aacs_context){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_content_revocation(aacs_context); TIMING_END(); return status;}/** * Ready title for playback * * This function performs various operation to make a title ready. It outputs * the basic title usage for AACS. * * aacs_content_ready should have been called at least once before calling * aacs_content_unit_ready. * * @param aacs_context - aacs_context initialized with init_aacs * @param title_id - Title number for BD-ROM/BD-RE, ... * @param basic_cci - Basic Title Usage for AACS * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_title_ready(struct aacs_context *aacs_context, RMuint32 title_id, RMuint8 basic_cci[AACS_BCCI_SIZE]){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_title_ready(aacs_context, title_id, basic_cci); TIMING_END(); return status;}RMstatus aacs_clip_ready(struct aacs_context *aacs_context, RMuint16 clip_id, RMuint8 bd_directory, RMuint8 cci[AACS_SCCI_SIZE]) { RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_clip_ready(aacs_context, clip_id, bd_directory, cci); TIMING_END(); return status;}RMstatus aacs_clips_ready(struct aacs_context *aacs_context, struct clip_info *clip_info, RMuint32 no_clips) { RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_clips_ready(aacs_context, clip_info,no_clips); TIMING_END(); return status;}RMstatus aacs_decrypt_thumbnail(struct aacs_context *aacs_context, enum bdav_tn_type tn_type, RMuint8 bd_directory, RMuint8 *tn_sub_in, RMuint8 *tn_sub_out, RMuint32 n_tn_sub, RMuint8 cci[AACS_SCCI_SIZE]) { RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_decrypt_thumbnail(aacs_context, tn_type, bd_directory, tn_sub_in, tn_sub_out, n_tn_sub, cci); TIMING_END(); return status;}/** * Read AACS PSR * * This function returns the value of a given AACS PSR (0 or 1) * * @param aacs_context - aacs_context initialized with init_aacs * @param psr - number of the AACS PSR to get (0 or 1) * @param psr_value - returned value of the PSR * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_get_psr(struct aacs_context *aacs_context, enum aacs_psr psr, RMuint32 *psr_value){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_get_psr(aacs_context, psr, psr_value); TIMING_END(); return status;}/** * Read BD-J Root Certificate Hash * * @param aacs_context - aacs_context initialized with init_aacs * @param hash - 20 bytes long buffer to receive the SHA1 * @param aid - returned Applicant ID * @param csn - returned Content Sequence Number * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_get_bdj_hash(struct aacs_context *aacs_context, RMuint16 *aid, RMuint32 *csn, RMuint8 hash[AACS_SHA1_SIZE]){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_get_bdj_hash(aacs_context, aid, csn, hash); TIMING_END(); return status;}/** * Read Pre-Recorded Media Serial Number * * @param aacs_context - aacs_context initialized with init_aacs * @param pmsn - 16 bytes buffer to receive the pmsn * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_get_pmsn(struct aacs_context *aacs_context, RMuint8 pmsn[AACS_PMSN_SIZE]){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_get_pmsn(aacs_context, pmsn); TIMING_END(); return status;}/** * Get AACS Volume ID * * @param aacs_context - aacs_context initialized with init_aacs * @param vid - 16 bytes buffer to receive the VolumeID * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_get_volume_id(struct aacs_context *aacs_context, RMuint8 vid[AACS_VID_SIZE]){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_get_volume_id(aacs_context, vid); TIMING_END(); return status;}/** * Cancel AACS Processing * * @param aacs_context - aacs_context initialized with init_aacs * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_cancel(struct aacs_context *aacs_context){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_cancel(aacs_context); TIMING_END(); return status;}/** * Set AACS KCD params (implementation specific) * * This function can be called with a NULL aacs_context. In that case, the * handle is used and on the next creation of a context, the KCD data will be * used. If aacs_context is not NULL, then the KCD is set immediately * * @param aacs_handle - aacs_handle returned by aacs_open * @param aacs_context - context (can be NULL) * @param data - data to process to get the KCD * @param size - size of the data to process < KCD_MAX_SIZE * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_set_kcd(struct aacs_context *aacs_context, const RMuint8 *data, RMuint32 size){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_set_kcd(aacs_context, data, size); TIMING_END(); return status;}/** * Generate random 128bits * * @param aacs_handle - aacs_handle returned by aacs_open * @param rnd - 16 bytes buffer to received random data * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_random_gen(struct aacs_context *aacs_context, RMuint8 *rnd){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_random_gen(aacs_context, rnd); TIMING_END(); return status;}/** * Get decryption information * * @param aacs_context - aacs_context initialized with init_aacs * @param xtask_pid - returned PID of the xtask * @param cookie - decryption cookie, returned * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_get_decrypt_info(struct aacs_context *aacs_context, RMuint32 *xtask_pid, void **cookie){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_get_decrypt_info(aacs_context, xtask_pid, cookie); TIMING_END(); return status;}/** * For BD+, on title initialize, send a FUT to the core in order to perform the * Media Transform. * * @param aacs_context - aacs_context initialized with init_aacs * @param data - fixup table data * @param size - data size * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_send_fut(struct aacs_context *aacs_context, RMuint8 *data, RMuint32 size){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_send_fut(aacs_context, data, size); TIMING_END(); return status;}/** * For BD+, set the Media Transform parameters for a given slot. * * @param aacs_context - aacs_context initialized with init_aacs * @param slot_id - slot to setup * @param clip_id - Clip ID * @param sp_id - Secret Parameter Identifier * @param sp - Secret Parameter * @param fm_id - Forensic Mark ID * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_set_sp(struct aacs_context *aacs_context, RMuint8 slot_id, RMuint32 clip_id, RMuint16 sp_id, RMuint8 sp[BDP_SP_SIZE], RMuint8 fm_id[BDP_FM_SIZE]){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_set_sp(aacs_context, slot_id, clip_id, sp_id, sp, fm_id); TIMING_END(); return status;}/** * Terminate a AACS session * * @param aacs_context - aacs_context initialized with init_aacs * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_finalize(struct aacs_context *aacs_context){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_finalize(aacs_context); TIMING_END(); return status;}/** * Close AACS module, free allocated resources * * @return RM_OK on success, RM_ERROR on error and aacs_error is set */RMstatus aacs_close(struct aacs_handle *aacs_handle){ RMstatus status = RM_ERROR; TIMING_START(); if (g_aacs) status = g_aacs->aacs_close(aacs_handle); TIMING_END(); return status;}/** * Error reporting, not thread safe, global (not per handle/context) * * @return last error code encountered */RMuint32 dummy_error = AACS_E_ERROR;RMuint32 * __aacs_error_func(void);RMuint32 * __aacs_error_func(void) { if (g_aacs) return g_aacs->__aacs_error_func(); else return &dummy_error;}/** * Translate a AACS basic CCI into a rmcci. See aacs_title_ready for basic_cci * format. * * @param basic_cci - basic CCI in aacs_title_ready format. * @return pointer to CCI struct (should be copied), NULL on error */struct aacs_cci_info *aacs_bcci2rmcci(RMuint8 basic_cci[AACS_BCCI_SIZE]){ struct aacs_cci_info *aacs_cci = NULL; TIMING_START(); if (g_aacs) aacs_cci = g_aacs->aacs_bcci2rmcci(basic_cci); TIMING_END(); return aacs_cci;}struct aacs_cci_info *aacs_scci2rmcci(RMuint8 cci[AACS_SCCI_SIZE]) { struct aacs_cci_info *aacs_cci = NULL; TIMING_START(); if (g_aacs) aacs_cci = g_aacs->aacs_scci2rmcci(cci); TIMING_END(); return aacs_cci;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -