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

📄 ismacryp.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre - 2005 *					All rights reserved * *  This file is part of GPAC / Media Tools sub-project * *  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/ismacryp.h>#include <gpac/xml.h>#include <gpac/base_coding.h>#include <gpac/constants.h>#include <gpac/internal/isomedia_dev.h>#include <gpac/crypt.h>typedef struct {	GF_List *tcis;	Bool has_common_key;	Bool in_text_header;} ISMACrypInfo; void isma_ea_node_start(void *sax_cbck, const char *node_name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes){	GF_XMLAttribute *att;	GF_TrackCryptInfo *tkc;	u32 i;	ISMACrypInfo *info = (ISMACrypInfo *)sax_cbck;		if (!strcmp(node_name, "OMATextHeader")) {		info->in_text_header = 1;		return;	}	if (!strcmp(node_name, "ISMACrypTrack") || !strcmp(node_name, "OMATrack")) {		GF_SAFEALLOC(tkc, GF_TrackCryptInfo);		gf_list_add(info->tcis, tkc);		if (!strcmp(node_name, "OMATrack")) {			tkc->enc_type = 1;			/*default to AES 128 in OMA*/			tkc->encryption = 2;		}		for (i=0; i<nb_attributes; i++) {			att = (GF_XMLAttribute *) &attributes[i];			if (!stricmp(att->name, "trackID") || !stricmp(att->name, "ID")) {				if (!strcmp(att->value, "*")) info->has_common_key = 1;				else tkc->trackID = atoi(att->value);			}			else if (!stricmp(att->name, "key")) {				char *sKey = att->value;				if (!strnicmp(sKey, "0x", 2)) sKey += 2;				if (strlen(sKey) == 32) {					u32 j;					for (j=0; j<32; j+=2) {						u32 v;						char szV[5];						sprintf(szV, "%c%c", sKey[j], sKey[j+1]);						sscanf(szV, "%x", &v);						tkc->key[j/2] = v;					}				} else {					GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMA E&A] Key is not 16-bytes long - skipping\n"));				}			}			else if (!stricmp(att->name, "salt")) {				u32 len, j;				char *sKey = att->value;				if (!strnicmp(sKey, "0x", 2)) sKey += 2;				len = strlen(sKey);				for (j=0; j<len; j+=2) {					char szV[5];					u32 v;					sprintf(szV, "%c%c", sKey[j], sKey[j+1]);					sscanf(szV, "%x", &v);					tkc->salt[j/2] = v;				}			}			else if (!stricmp(att->name, "kms_URI")) strcpy(tkc->KMS_URI, att->value);			else if (!stricmp(att->name, "rightsIssuerURL")) strcpy(tkc->KMS_URI, att->value);			else if (!stricmp(att->name, "scheme_URI")) strcpy(tkc->Scheme_URI, att->value);			else if (!stricmp(att->name, "selectiveType")) {				if (!stricmp(att->value, "Rap")) tkc->sel_enc_type = GF_ISMACRYP_SELENC_RAP;				else if (!stricmp(att->value, "Non-Rap")) tkc->sel_enc_type = GF_ISMACRYP_SELENC_NON_RAP;				else if (!stricmp(att->value, "Rand")) tkc->sel_enc_type = GF_ISMACRYP_SELENC_RAND;				else if (!strnicmp(att->value, "Rand", 4)) {					tkc->sel_enc_type = GF_ISMACRYP_SELENC_RAND_RANGE;					tkc->sel_enc_range = atoi(&att->value[4]);				}				else if (sscanf(att->value, "%d", &tkc->sel_enc_range)==1) {					if (tkc->sel_enc_range==1) tkc->sel_enc_range = 0;					else tkc->sel_enc_type = GF_ISMACRYP_SELENC_RANGE;				}			}			else if (!stricmp(att->name, "ipmpType")) {				if (!stricmp(att->value, "None")) tkc->ipmp_type = 0;				else if (!stricmp(att->value, "IPMP")) tkc->sel_enc_type = 1;				else if (!stricmp(att->value, "IPMPX")) tkc->sel_enc_type = 2;			}			else if (!stricmp(att->name, "ipmpDescriptorID")) tkc->ipmp_desc_id = atoi(att->value);			else if (!stricmp(att->name, "encryptionMethod")) {				if (!strcmp(att->value, "AES_128_CBC")) tkc->encryption = 1;				else if (!strcmp(att->value, "None")) tkc->encryption = 0;				else if (!strcmp(att->value, "AES_128_CTR") || !strcmp(att->value, "default")) tkc->encryption = 2;			}			else if (!stricmp(att->name, "contentID")) strcpy(tkc->Scheme_URI, att->value);			else if (!stricmp(att->name, "rightsIssuerURL")) strcpy(tkc->KMS_URI, att->value);			else if (!stricmp(att->name, "transactionID")) {				if (strlen(att->value)<=16) strcpy(tkc->TransactionID, att->value);			}			else if (!stricmp(att->name, "textualHeaders")) {			}		}	}}void isma_ea_node_end(void *sax_cbck, const char *node_name, const char *name_space){	ISMACrypInfo *info = (ISMACrypInfo *)sax_cbck;	if (!strcmp(node_name, "OMATextHeader")) {		info->in_text_header = 0;		return;	}}void isma_ea_text(void *sax_cbck, const char *text, Bool is_cdata){	u32 len;	GF_TrackCryptInfo *tkc;	ISMACrypInfo *info = (ISMACrypInfo *)sax_cbck;	if (!info->in_text_header) return;	tkc = (GF_TrackCryptInfo *) gf_list_last(info->tcis);	len = strlen(text);	if (len+tkc->TextualHeadersLen > 5000) return;	if (tkc->TextualHeadersLen) {		tkc->TextualHeadersLen ++;		tkc->TextualHeaders[tkc->TextualHeadersLen] = 0;	}	memcpy(tkc->TextualHeaders + tkc->TextualHeadersLen, text, sizeof(char)*len);	tkc->TextualHeadersLen += len;	tkc->TextualHeaders[tkc->TextualHeadersLen] = 0;}static void del_crypt_info(ISMACrypInfo *info){	while (gf_list_count(info->tcis)) {		GF_TrackCryptInfo *tci = (GF_TrackCryptInfo *)gf_list_last(info->tcis);		gf_list_rem_last(info->tcis);		free(tci);	}	gf_list_del(info->tcis);	free(info);}static ISMACrypInfo *load_crypt_file(const char *file){	GF_Err e;	ISMACrypInfo *info;	GF_SAXParser *sax;	GF_SAFEALLOC(info, ISMACrypInfo);	info->tcis = gf_list_new();	sax = gf_xml_sax_new(isma_ea_node_start, isma_ea_node_end, isma_ea_text, info);	e = gf_xml_sax_parse_file(sax, file, NULL);	gf_xml_sax_del(sax);	if (e<0) {		del_crypt_info(info);		return NULL;	}	return info;}GF_EXPORTGF_Err gf_ismacryp_gpac_get_info(u32 stream_id, char *drm_file, char *key, char *salt){	GF_Err e;	u32 i, count;	ISMACrypInfo *info;	GF_TrackCryptInfo *tci;	e = GF_OK;	info = load_crypt_file(drm_file);	if (!info) return GF_NOT_SUPPORTED;	count = gf_list_count(info->tcis);	for (i=0; i<count; i++) {		tci = (GF_TrackCryptInfo *) gf_list_get(info->tcis, i);		if ((info->has_common_key && !tci->trackID) || (tci->trackID == stream_id) ) {			memcpy(key, tci->key, sizeof(char)*16);			memcpy(salt, tci->salt, sizeof(char)*8);			e = GF_OK;			break;		}	}	del_crypt_info(info);	return e;}GF_EXPORTBool gf_ismacryp_mpeg4ip_get_info(char *kms_uri, char *key, char *salt){	char szPath[1024], catKey[24];	u32 i, x;	Bool got_it;	FILE *kms;	strcpy(szPath, getenv("HOME"));	strcat(szPath , "/.kms_data"); 	got_it = 0;	kms = fopen(szPath, "r");	while (kms && !feof(kms)) {		if (!fgets(szPath, 1024, kms)) break;		szPath[strlen(szPath) - 1] = 0;		if (stricmp(szPath, kms_uri)) continue;		for (i=0; i<24; i++) {			if (!fscanf(kms, "%x", &x)) break;			catKey[i] = x;		}		if (i==24) got_it = 1;		break;	}	if (kms) fclose(kms);	if (got_it) {		/*watchout, MPEG4IP stores SALT|KEY, NOT KEY|SALT*/		memcpy(key, catKey+8, sizeof(char)*16);		memcpy(salt, catKey, sizeof(char)*8);		return 1;	}	return 0;}#ifndef GPAC_READ_ONLYstatic GFINLINE void resync_IV(GF_Crypt *mc, u64 BSO, char *salt){	char IV[17];	u64 count;	u32 remain;	GF_BitStream *bs;	count = BSO / 16;	remain = (u32) (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, salt, 8);	gf_bs_write_u64(bs, (s64) count);	gf_bs_del(bs);	gf_crypt_set_state(mc, IV, 17);	/*decrypt remain bytes*/	if (remain) {		char dummy[20];		gf_crypt_decrypt(mc, dummy, remain);	}}GF_EXPORTGF_Err gf_ismacryp_decrypt_track(GF_ISOFile *mp4, GF_TrackCryptInfo *tci, void (*progress)(void *cbk, u32 done, u32 total), void *cbk){	GF_Err e;	Bool use_sel_enc;	u32 track, count, i, j, si, is_avc;	GF_ISOSample *samp;	GF_ISMASample *ismasamp;	GF_Crypt *mc;	unsigned char IV[17];	u32 IV_size;	Bool prev_sample_encrypted;	GF_ESD *esd;	track = gf_isom_get_track_by_id(mp4, tci->trackID);	e = gf_isom_get_ismacryp_info(mp4, track, 1, &is_avc, NULL, NULL, NULL, NULL, &use_sel_enc, &IV_size, NULL);	is_avc = (is_avc==GF_4CC('2','6','4','b')) ? 1 : 0;			mc = gf_crypt_open("AES-128", "CTR");	if (!mc) {		GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMA E&A] Cannot open AES-128 CTR cryptography\n", tci->trackID));		return GF_IO_ERR;	}	memset(IV, 0, sizeof(char)*16);	memcpy(IV, tci->salt, sizeof(char)*8);	e = gf_crypt_init(mc, tci->key, 16, IV);	if (e) {		gf_crypt_close(mc);		GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMA E&A] cannot initialize AES-128 CTR (%s)\n", gf_error_to_string(e)));		return GF_IO_ERR;	}	GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[ISMA E&A] Decrypting track ID %d - KMS: %s%s\n", tci->trackID, tci->KMS_URI, use_sel_enc ? " - Selective Decryption" : ""));	/*start as initialized*/	prev_sample_encrypted = 1;	/* decrypt each sample */	count = gf_isom_get_sample_count(mp4, track);	for (i = 0; i < count; i++) {		samp = gf_isom_get_sample(mp4, track, i+1, &si); 		ismasamp = gf_isom_get_ismacryp_sample(mp4, track, samp, si);		free(samp->data);		samp->data = ismasamp->data;		samp->dataLength = ismasamp->dataLength;		ismasamp->data = NULL;		ismasamp->dataLength = 0;		/* Decrypt payload */		if (ismasamp->flags & GF_ISOM_ISMA_IS_ENCRYPTED) {			/*restore IV*/			if (!prev_sample_encrypted) resync_IV(mc, ismasamp->IV, tci->salt);			gf_crypt_decrypt(mc, samp->data, samp->dataLength);		}		prev_sample_encrypted = (ismasamp->flags & GF_ISOM_ISMA_IS_ENCRYPTED);		gf_isom_ismacryp_delete_sample(ismasamp);		/*replace AVC start codes (0x00000001) by nalu size*/		if (is_avc) {			u32 nalu_size;			u32 remain = samp->dataLength;			char *start, *end;			start = samp->data;			end = start + 4;			while (remain>4) {				if (!end[0] && !end[1] && !end[2] && (end[3]==0x01)) {					nalu_size = end - start - 4;					start[0] = (nalu_size>>24)&0xFF;					start[1] = (nalu_size>>16)&0xFF;					start[2] = (nalu_size>>8)&0xFF;					start[3] = (nalu_size)&0xFF;					start = end;					end = start+4;					continue;				}				end++;				remain--;			}			nalu_size = end - start - 4;			start[0] = (nalu_size>>24)&0xFF;			start[1] = (nalu_size>>16)&0xFF;			start[2] = (nalu_size>>8)&0xFF;			start[3] = (nalu_size)&0xFF;		}		gf_isom_update_sample(mp4, track, i+1, samp, 1);		gf_isom_sample_del(&samp);		gf_set_progress("ISMA Decrypt", i+1, count);	}	gf_crypt_close(mc);	/*and remove protection info*/	e = gf_isom_remove_ismacryp_protection(mp4, track, 1);	if (e) {		GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMA E&A] Error ISMACryp signature from trackID %d: %s\n", tci->trackID, gf_error_to_string(e)));	}	/*remove all IPMP ptrs*/	esd = gf_isom_get_esd(mp4, track, 1);	if (esd) {		while (gf_list_count(esd->IPMPDescriptorPointers)) {			GF_Descriptor *d = (GF_Descriptor *)gf_list_get(esd->IPMPDescriptorPointers, 0);			gf_list_rem(esd->IPMPDescriptorPointers, 0);			gf_odf_desc_del(d);		}		gf_isom_change_mpeg4_description(mp4, track, 1, esd);		gf_odf_desc_del((GF_Descriptor *)esd);	}	/*update OD track if any*/	track = 0;	for (i=0; i<gf_isom_get_track_count(mp4); i++) {		GF_ODCodec *cod;		if (gf_isom_get_media_type(mp4, i+1) != GF_ISOM_MEDIA_OD) continue;		/*remove all IPMPUpdate commads...*/		samp = gf_isom_get_sample(mp4, i+1, 1, &si);		cod = gf_odf_codec_new();		gf_odf_codec_set_au(cod, samp->data, samp->dataLength);		gf_odf_codec_decode(cod);		for (j=0; j<gf_list_count(cod->CommandList); j++) {			GF_IPMPUpdate *com = (GF_IPMPUpdate *)gf_list_get(cod->CommandList, j);			if (com->tag != GF_ODF_IPMP_UPDATE_TAG) continue;			gf_list_rem(cod->CommandList, j);			j--;			gf_odf_com_del((GF_ODCom **)&com);		}		free(samp->data);		samp->data = NULL;		samp->dataLength = 0;		gf_odf_codec_encode(cod, 1);		gf_odf_codec_get_au(cod, &samp->data, &samp->dataLength);		gf_odf_codec_del(cod);		gf_isom_update_sample(mp4, i+1, 1, samp, 1);		gf_isom_sample_del(&samp);		/*remove IPMPToolList if any*/			if (mp4->moov->iods && (mp4->moov->iods->descriptor->tag == GF_ODF_ISOM_IOD_TAG) ) {			GF_IsomInitialObjectDescriptor *iod = (GF_IsomInitialObjectDescriptor *)mp4->moov->iods->descriptor;			if (iod->IPMPToolList) gf_odf_desc_del((GF_Descriptor*) iod->IPMPToolList);			iod->IPMPToolList = NULL;		}		break;	}	return GF_OK;}GF_EXPORTGF_Err gf_ismacryp_decrypt_file(GF_ISOFile *mp4, const char *drm_file){	GF_Err e;	u32 i, idx, count, common_idx, nb_tracks, scheme_type, cur_tk;	const char *scheme_URI, *KMS_URI;	ISMACrypInfo *info;	GF_TrackCryptInfo *a_tci, tci;	count = 0;	info = NULL;	if (drm_file) {		info = load_crypt_file(drm_file);		if (!info) {			GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMA E&A] Cannot open or validate xml file %s\n", drm_file));			return GF_NOT_SUPPORTED;		}		count = gf_list_count(info->tcis);	}	common_idx=0;	if (info && info->has_common_key) {		for (common_idx=0; common_idx<count; common_idx++) {			a_tci = (GF_TrackCryptInfo *)gf_list_get(info->tcis, common_idx);			if (!a_tci->trackID) break;		}

⌨️ 快捷键说明

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