GF_EXPORT GF_Err gf_crypt_init(GF_Crypt *td, void *key, u32 lenofkey, const void *IV) { GF_Err e; u32 sizes[MAX_KEY_SIZES]; u32 i, num_of_sizes, ok = 0; u32 key_size = gf_crypt_get_key_size(td); if ((lenofkey > key_size) || (lenofkey==0)) return GF_BAD_PARAM; num_of_sizes = gf_crypt_get_supported_key_sizes(td, sizes); if (num_of_sizes) { for (i=0; i < num_of_sizes; i++) { if (lenofkey == sizes[i]) { ok = 1; break; } } } else if (lenofkey <= gf_crypt_get_key_size(td)) { ok = 1; } if (ok == 0) { /* not supported key size */ key_size = gf_crypt_get_key_size(td); if (sizes != NULL) { for (i = 0; i < num_of_sizes; i++) { if (lenofkey <= sizes[i]) { key_size = sizes[i]; break; } } } else { /* well every key size is supported! */ key_size = lenofkey; } } else { key_size = lenofkey; } td->keyword_given = (char*)gf_malloc(sizeof(char)*gf_crypt_get_key_size(td)); if (td->keyword_given==NULL) return GF_OUT_OF_MEM; memmove(td->keyword_given, key, lenofkey); td->akey = (char*)gf_malloc(sizeof(char)*td->algo_size); if (td->akey==NULL) { gf_free(td->keyword_given); return GF_OUT_OF_MEM; } if (td->mode_size > 0) { td->abuf = (char*)gf_malloc(sizeof(char)*td->mode_size); if (td->abuf==NULL) { gf_free(td->keyword_given); gf_free(td->akey); return GF_OUT_OF_MEM; } } e = td->_init_mcrypt(td->abuf, (void *) key, key_size, (void *) IV, gf_crypt_get_block_size(td)); if (e!=GF_OK) { gf_free(td->keyword_given); gf_free(td->akey); gf_free(td->abuf); return e; } e = gf_crypt_set_key(td, (void *) td->keyword_given, key_size, IV); if (e!=GF_OK) internal_end_mcrypt(td); return e; }
static GF_Err CENC_ProcessData(ISMAEAPriv *priv, GF_IPMPEvent *evt) { GF_Err e; GF_BitStream *pleintext_bs, *cyphertext_bs, *sai_bs; char IV[17]; bin128 KID; char *buffer; u32 max_size, i, subsample_count; u64 BSO; GF_CENCSampleAuxInfo *sai; e = GF_OK; pleintext_bs = cyphertext_bs = sai_bs = NULL; buffer = NULL; max_size = 4096; if (!priv->crypt) return GF_SERVICE_ERROR; if (!evt->is_encrypted || !evt->IV_size) return GF_OK; cyphertext_bs = gf_bs_new(evt->data, evt->data_size, GF_BITSTREAM_READ); sai_bs = gf_bs_new(evt->sai, evt->saiz, GF_BITSTREAM_READ); pleintext_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); buffer = (char*)gf_malloc(sizeof(char) * max_size); sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); if (!sai) { e = GF_IO_ERR; goto exit; } memset(sai, 0, sizeof(GF_CENCSampleAuxInfo)); sai->IV_size = evt->IV_size; /*read sample auxiliary information from bitstream*/ gf_bs_read_data(sai_bs, (char *)KID, 16); gf_bs_read_data(sai_bs, (char *)sai->IV, sai->IV_size); sai->subsample_count = gf_bs_read_u16(sai_bs); if (sai->subsample_count) { sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry)); for (i = 0; i < sai->subsample_count; i++) { sai->subsamples[i].bytes_clear_data = gf_bs_read_u16(sai_bs); sai->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(sai_bs); } } for (i = 0; i < priv->KID_count; i++) { if (!strncmp((const char *)KID, (const char *)priv->KIDs[i], 16)) { memmove(priv->key, priv->keys[i], 16); break; } } if (priv->first_crypted_samp) { memmove(IV, sai->IV, sai->IV_size); if (sai->IV_size == 8) memset(IV+8, 0, sizeof(char)*8); e = gf_crypt_init(priv->crypt, priv->key, 16, IV); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) ); e = GF_IO_ERR; goto exit; } priv->first_crypted_samp = GF_FALSE; } else { if (priv->is_cenc) { GF_BitStream *bs; bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE); gf_bs_write_u8(bs, 0); /*begin of counter*/ gf_bs_write_data(bs,(char *)sai->IV, sai->IV_size); if (sai->IV_size == 8) gf_bs_write_u64(bs, 0); /*0-padded if IV_size == 8*/ gf_bs_del(bs); gf_crypt_set_state(priv->crypt, IV, 17); } e = gf_crypt_set_key(priv->crypt, priv->key, 16, IV); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) ); e = GF_IO_ERR; goto exit; } } subsample_count = 0; BSO = 0; while (gf_bs_available(cyphertext_bs)) { assert(subsample_count < sai->subsample_count); /*read clear data and write it to pleintext bitstream*/ if (max_size < sai->subsamples[subsample_count].bytes_clear_data) { buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_clear_data); max_size = sai->subsamples[subsample_count].bytes_clear_data; } gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data); gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data); /*now read encrypted data, decrypted it and write to pleintext bitstream*/ if (max_size < sai->subsamples[subsample_count].bytes_encrypted_data) { buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_encrypted_data); max_size = sai->subsamples[subsample_count].bytes_encrypted_data; } gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data); gf_crypt_decrypt(priv->crypt, buffer, sai->subsamples[subsample_count].bytes_encrypted_data); gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data); /*update IV for next subsample*/ if (priv->is_cenc) { BSO += sai->subsamples[subsample_count].bytes_encrypted_data; if (gf_bs_available(cyphertext_bs)) { char next_IV[17]; u64 prev_block_count, salt_portion, block_count_portion; u32 remain; GF_BitStream *bs, *tmp; prev_block_count = BSO / 16; remain = BSO % 16; tmp = gf_bs_new((const char *)sai->IV, 16, GF_BITSTREAM_READ); bs = gf_bs_new(next_IV, 17, GF_BITSTREAM_WRITE); gf_bs_write_u8(bs, 0); /*begin of counter*/ salt_portion = gf_bs_read_u64(tmp); block_count_portion = gf_bs_read_u64(tmp); /*reset the block counter to zero without affecting the other 64 bits of the IV*/ if (prev_block_count > 0xFFFFFFFFFFFFFFFFULL - block_count_portion) block_count_portion = prev_block_count - (0xFFFFFFFFFFFFFFFFULL - block_count_portion) - 1; else block_count_portion += prev_block_count; gf_bs_write_u64(bs, salt_portion); gf_bs_write_u64(bs, block_count_portion); gf_crypt_set_state(priv->crypt, next_IV, 17); /*decrypt remain bytes*/ if (remain) { char dummy[20]; gf_crypt_decrypt(priv->crypt, dummy, remain); } gf_bs_del(bs); gf_bs_del(tmp); } } subsample_count++; } if (buffer) gf_free(buffer); gf_bs_get_content(pleintext_bs, &buffer, &evt->data_size); memmove(evt->data, buffer, evt->data_size); exit: if (pleintext_bs) gf_bs_del(pleintext_bs); if (sai_bs) gf_bs_del(sai_bs); if (cyphertext_bs) gf_bs_del(cyphertext_bs); if (buffer) gf_free(buffer); if (sai && sai->subsamples) gf_free(sai->subsamples); if (sai) gf_free(sai); return e; }
static GF_Err CENC_ProcessData(ISMAEAPriv *priv, GF_IPMPEvent *evt) { GF_Err e; GF_BitStream *pleintext_bs, *cyphertext_bs, *sai_bs; char IV[17]; bin128 KID; char *buffer; u32 max_size, i, subsample_count; GF_CENCSampleAuxInfo *sai; pleintext_bs = cyphertext_bs = sai_bs = NULL; buffer = NULL; max_size = 4096; if (!priv->crypt) return GF_SERVICE_ERROR; if (!evt->is_encrypted || !evt->IV_size || !evt->saiz) return GF_OK; cyphertext_bs = gf_bs_new(evt->data, evt->data_size, GF_BITSTREAM_READ); sai_bs = gf_bs_new(evt->sai, evt->saiz, GF_BITSTREAM_READ); pleintext_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); buffer = (char*)gf_malloc(sizeof(char) * max_size); sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); if (!sai) { e = GF_IO_ERR; goto exit; } memset(sai, 0, sizeof(GF_CENCSampleAuxInfo)); sai->IV_size = evt->IV_size; /*read sample auxiliary information from bitstream*/ gf_bs_read_data(sai_bs, (char *)KID, 16); gf_bs_read_data(sai_bs, (char *)sai->IV, sai->IV_size); sai->subsample_count = gf_bs_read_u16(sai_bs); if (sai->subsample_count) { sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry)); for (i = 0; i < sai->subsample_count; i++) { sai->subsamples[i].bytes_clear_data = gf_bs_read_u16(sai_bs); sai->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(sai_bs); } } for (i = 0; i < priv->KID_count; i++) { if (!strncmp((const char *)KID, (const char *)priv->KIDs[i], 16)) { memmove(priv->key, priv->keys[i], 16); break; } } if (priv->first_crypted_samp) { memmove(IV, sai->IV, sai->IV_size); if (sai->IV_size == 8) memset(IV+8, 0, sizeof(char)*8); e = gf_crypt_init(priv->crypt, priv->key, 16, IV); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) ); e = GF_IO_ERR; goto exit; } priv->first_crypted_samp = GF_FALSE; } else { if (priv->is_cenc) { GF_BitStream *bs; bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE); gf_bs_write_u8(bs, 0); /*begin of counter*/ gf_bs_write_data(bs,(char *)sai->IV, sai->IV_size); if (sai->IV_size == 8) gf_bs_write_u64(bs, 0); /*0-padded if IV_size == 8*/ gf_bs_del(bs); gf_crypt_set_state(priv->crypt, IV, 17); } e = gf_crypt_set_key(priv->crypt, priv->key, 16, IV); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) ); e = GF_IO_ERR; goto exit; } } //sub-sample encryption if (sai->subsample_count) { subsample_count = 0; while (gf_bs_available(cyphertext_bs)) { if (subsample_count >= sai->subsample_count) break; /*read clear data and write it to pleintext bitstream*/ if (max_size < sai->subsamples[subsample_count].bytes_clear_data) { buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_clear_data); max_size = sai->subsamples[subsample_count].bytes_clear_data; } gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data); gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data); /*now read encrypted data, decrypted it and write to pleintext bitstream*/ if (max_size < sai->subsamples[subsample_count].bytes_encrypted_data) { buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_encrypted_data); max_size = sai->subsamples[subsample_count].bytes_encrypted_data; } gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data); gf_crypt_decrypt(priv->crypt, buffer, sai->subsamples[subsample_count].bytes_encrypted_data); gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data); subsample_count++; } if (buffer) gf_free(buffer); gf_bs_get_content(pleintext_bs, &buffer, &evt->data_size); } //full sample encryption else { if (max_size < evt->data_size) { buffer = (char*)gf_realloc(buffer, sizeof(char)*evt->data_size); } gf_bs_read_data(cyphertext_bs, buffer, evt->data_size); gf_crypt_decrypt(priv->crypt, buffer, evt->data_size); } memmove(evt->data, buffer, evt->data_size); exit: if (pleintext_bs) gf_bs_del(pleintext_bs); if (sai_bs) gf_bs_del(sai_bs); if (cyphertext_bs) gf_bs_del(cyphertext_bs); if (buffer) gf_free(buffer); if (sai && sai->subsamples) gf_free(sai->subsamples); if (sai) gf_free(sai); return e; }