⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ismacryp.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Authors: Jean le Feuvre *				Copyright (c) 2005-200X ENST *					All rights reserved * *  This file is part of GPAC / LASeR decoder module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/modules/ipmp.h>#include <gpac/crypt.h>#include <gpac/ismacryp.h>#include <gpac/base_coding.h>#include <gpac/download.h>#include <gpac/internal/terminal_dev.h>#define OMA_DRM_MP4MCenum{	ISMAEA_STATE_ERROR,	ISMAEA_STATE_SETUP,	ISMAEA_STATE_PLAY,};typedef struct {	GF_Crypt *crypt;	char key[16], salt[8];	u64 last_IV;	u32 state;	u32 nb_allow_play;	Bool is_oma;} ISMAEAPriv;static void ISMA_KMS_NetIO(void *cbck, GF_NETIO_Parameter *par){}static GF_Err ISMA_GetGPAC_KMS(ISMAEAPriv *priv, GF_Channel *ch, char *kms_url){	GF_Err e;	FILE *t;	GF_DownloadSession * sess;	if (!strnicmp(kms_url, "(ipmp)", 6)) return GF_NOT_SUPPORTED;	else if (!strnicmp(kms_url, "(uri)", 5)) kms_url += 5;	else if (!strnicmp(kms_url, "file://", 7)) kms_url += 7;	e = GF_OK;	/*try local*/	t = (strstr(kms_url, "://") == NULL) ? fopen(kms_url, "r") : NULL;	if (t) {		fclose(t);		return gf_ismacryp_gpac_get_info(ch->esd->ESID, kms_url, priv->key, priv->salt);	}	/*note that gpac doesn't have TLS support -> not really usefull. As a general remark, ISMACryp	is supported as a proof of concept, crypto and IPMP being the last priority on gpac...*/	GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[ISMA E&A] Fetching ISMACryp key for channel %d\n", ch->esd->ESID) );	sess = gf_term_download_new(ch->service, kms_url, 0, ISMA_KMS_NetIO, ch);	if (!sess) return GF_IO_ERR;	while (1) {		e = gf_dm_sess_get_stats(sess, NULL, NULL, NULL, NULL, NULL, NULL);		if (e) break;	}	if (e==GF_EOS) {		e = gf_ismacryp_gpac_get_info(ch->esd->ESID, (char *) gf_dm_sess_get_cache_name(sess), priv->key, priv->salt);	}	gf_term_download_del(sess);	return e;}static GF_Err ISMA_Setup(ISMAEAPriv *priv, GF_IPMPEvent *evt){	GF_Err e;	GF_ISMACrypConfig *cfg = (GF_ISMACrypConfig*)evt->config_data;	priv->state = ISMAEA_STATE_ERROR;	if (cfg->scheme_type != GF_4CC('i','A','E','C')) return GF_NOT_SUPPORTED;	if (cfg->scheme_version != 1) return GF_NOT_SUPPORTED;	if (!cfg->kms_uri) return GF_NON_COMPLIANT_BITSTREAM;	/*try to fetch the keys*/	/*base64 inband encoding*/	if (!strnicmp(cfg->kms_uri, "(key)", 5)) {		char data[100];		gf_base64_decode((char*)cfg->kms_uri+5, strlen(cfg->kms_uri)-5, data, 100);		memcpy(priv->key, data, sizeof(char)*16);		memcpy(priv->salt, data+16, sizeof(char)*8);	}	/*hexadecimal inband encoding*/	else if (!strnicmp(cfg->kms_uri, "(key-hexa)", 10)) {		u32 v;		char szT[3], *k;		u32 i;		szT[2] = 0;		if (strlen(cfg->kms_uri) < 10+32+16) return GF_NON_COMPLIANT_BITSTREAM;		k = (char *)cfg->kms_uri + 10;		for (i=0; i<16; i++) { 			szT[0] = k[2*i]; szT[1] = k[2*i + 1];			sscanf(szT, "%X", &v); 			priv->key[i] = v;		}		k = (char *)cfg->kms_uri + 10 + 32;		for (i=0; i<8; i++) { 			szT[0] = k[2*i]; szT[1] = k[2*i + 1];			sscanf(szT, "%X", &v); 			priv->salt[i] = v;		}	}	/*MPEG4-IP KMS*/	else if (!stricmp(cfg->kms_uri, "AudioKey") || !stricmp(cfg->kms_uri, "VideoKey")) {		if (!gf_ismacryp_mpeg4ip_get_info((char *) cfg->kms_uri, priv->key, priv->salt)) {			return GF_BAD_PARAM;		}	}	/*gpac default scheme is used, fetch file from KMS and load keys*/	else if (cfg->scheme_uri && !stricmp(cfg->scheme_uri, "urn:gpac:isma:encryption_scheme")) {		e = ISMA_GetGPAC_KMS(priv, evt->channel, (char *) cfg->kms_uri);		if (e) return e;	}	/*hardcoded keys*/	else {		static u8 mysalt[] = { 8,7,6,5,4,3,2,1, 0,0,0,0,0,0,0,0 };		static u8 mykey[][16]  = {	{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,	  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 } };		memcpy(priv->salt, mysalt, sizeof(char)*8);		memcpy(priv->key, mykey, sizeof(char)*16);	}	priv->state = ISMAEA_STATE_SETUP;	//priv->nb_allow_play = 1;	return GF_OK;}static GF_Err ISMA_Access(ISMAEAPriv *priv, GF_IPMPEvent *evt){	GF_Err e;	char IV[16];		if (evt->event_type==GF_IPMP_TOOL_GRANT_ACCESS) {		if (priv->state != ISMAEA_STATE_SETUP) return GF_SERVICE_ERROR;		assert(!priv->crypt);		//if (!priv->nb_allow_play) return GF_AUTHENTICATION_FAILURE;		//priv->nb_allow_play--;				/*init decrypter*/		priv->crypt = gf_crypt_open("AES-128", "CTR");		if (!priv->crypt) return GF_IO_ERR;		memset(IV, 0, sizeof(char)*16);		memcpy(IV, priv->salt, sizeof(char)*8);		e = gf_crypt_init(priv->crypt, priv->key, 16, IV);		if (e) return e;		priv->state = ISMAEA_STATE_PLAY;		return GF_OK;	}	if (evt->event_type==GF_IPMP_TOOL_RELEASE_ACCESS) {		if (priv->state != ISMAEA_STATE_PLAY) return GF_SERVICE_ERROR;		if (priv->crypt) gf_crypt_close(priv->crypt);		priv->crypt = NULL;		priv->state = ISMAEA_STATE_SETUP;		return GF_OK;	}	return GF_BAD_PARAM;}static GF_Err ISMA_ProcessData(ISMAEAPriv *priv, GF_IPMPEvent *evt){	if (!priv->crypt) return GF_SERVICE_ERROR;		if (!evt->is_encrypted) return GF_OK;	/*resync IV*/	if (!priv->last_IV || (priv->last_IV != evt->isma_BSO)) {		char IV[17];		u64 count;		u32 remain;		GF_BitStream *bs;		count = evt->isma_BSO / 16;		remain = (u32) (evt->isma_BSO % 16);		/*format IV to begin of counter*/		bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE);		gf_bs_write_u8(bs, 0);	/*begin of counter*/		gf_bs_write_data(bs, priv->salt, 8);		gf_bs_write_u64(bs, (s64) count);		gf_bs_del(bs);		gf_crypt_set_state(priv->crypt, IV, 17);		/*decrypt remain bytes*/		if (remain) {			char dummy[20];			gf_crypt_decrypt(priv->crypt, dummy, remain);		}		priv->last_IV = evt->isma_BSO;	}	/*decrypt*/	gf_crypt_decrypt(priv->crypt, evt->data, evt->data_size);	priv->last_IV += evt->data_size;	return GF_OK;}#ifdef OMA_DRM_MP4MCstatic GF_Err OMA_DRM_Setup(ISMAEAPriv *priv, GF_IPMPEvent *evt){	GF_OMADRM2Config *cfg = (GF_OMADRM2Config*)evt->config_data;	priv->state = ISMAEA_STATE_ERROR;	if (cfg->scheme_type != GF_4CC('o','d','k','m')) return GF_NOT_SUPPORTED;	if (cfg->scheme_version != 0x00000200) return GF_NOT_SUPPORTED;	priv->is_oma = 1;	return GF_NOT_SUPPORTED;	/*TODO: call DRM agent, fetch keys*/	if (!cfg->kms_uri) return GF_NON_COMPLIANT_BITSTREAM;	priv->state = ISMAEA_STATE_SETUP;	//priv->nb_allow_play = 1;	return GF_OK;}#endifstatic GF_Err ISMA_Process(GF_IPMPTool *plug, GF_IPMPEvent *evt){	ISMAEAPriv *priv = (ISMAEAPriv *)plug->udta;	switch (evt->event_type) {	case GF_IPMP_TOOL_SETUP:		if (evt->config_data_code == GF_4CC('i','s','m','a')) return ISMA_Setup(priv, evt);#ifdef OMA_DRM_MP4MC		if (evt->config_data_code == GF_4CC('o','d','r','m')) return OMA_DRM_Setup(priv, evt);#endif		return GF_NOT_SUPPORTED;			case GF_IPMP_TOOL_GRANT_ACCESS:	case GF_IPMP_TOOL_RELEASE_ACCESS:		if (priv->is_oma) {		} else {			return ISMA_Access(priv, evt);		}	case GF_IPMP_TOOL_PROCESS_DATA:		return ISMA_ProcessData(priv, evt);	}	return GF_OK;}void DeleteISMACrypTool(GF_IPMPTool *plug){	ISMAEAPriv *priv = (ISMAEAPriv *)plug->udta;	/*in case something went wrong*/	if (priv->crypt) gf_crypt_close(priv->crypt);	free(priv);	free(plug);}GF_IPMPTool *NewISMACrypTool(){	ISMAEAPriv *priv;	GF_IPMPTool *tmp;		GF_SAFEALLOC(tmp, GF_IPMPTool);	if (!tmp) return NULL;	GF_SAFEALLOC(priv, ISMAEAPriv);	tmp->udta = priv;	tmp->process = ISMA_Process;	GF_REGISTER_MODULE_INTERFACE(tmp, GF_IPMP_TOOL_INTERFACE, "GPAC ISMACryp tool", "gpac distribution")	return (GF_IPMPTool *) tmp;}GF_EXPORTBool QueryInterface(u32 InterfaceType){	switch (InterfaceType) {	case GF_IPMP_TOOL_INTERFACE:		return 1;	default:		return 0;	}}GF_EXPORTGF_BaseInterface *LoadInterface(u32 InterfaceType){	switch (InterfaceType) {	case GF_IPMP_TOOL_INTERFACE:		return (GF_BaseInterface *)NewISMACrypTool();	default:		return NULL;	}}GF_EXPORTvoid ShutdownInterface(GF_BaseInterface *ifce){	switch (ifce->InterfaceType) {	case GF_IPMP_TOOL_INTERFACE:		DeleteISMACrypTool((GF_IPMPTool *)ifce);		break;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -