Пример #1
0
Файл: srtp.c Проект: AVbin/libav
static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf,
                            int outlen)
{
    int i, j, outpos;
    for (i = 0, outpos = 0; outpos < outlen; i++) {
        uint8_t keystream[16];
        AV_WB16(&iv[14], i);
        av_aes_crypt(aes, keystream, iv, 1, NULL, 0);
        for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
            outbuf[outpos] ^= keystream[j];
    }
}
Пример #2
0
static int crypto_write(URLContext *h, const unsigned char *buf, int size)
{
    CryptoContext *c = h->priv_data;
    int total_size, blocks, pad_len, out_size;
    uint8_t *out_buf;
    int ret = 0;

    total_size = size + c->pad_len;
    pad_len = total_size % BLOCKSIZE;
    out_size = total_size - pad_len;
    blocks = out_size / BLOCKSIZE;

    if (out_size) {
        out_buf = av_malloc(out_size);
        if (!out_buf)
            return AVERROR(ENOMEM);

        if (c->pad_len) {
            memcpy(&c->pad[c->pad_len], buf, BLOCKSIZE - c->pad_len);
            av_aes_crypt(c->aes_encrypt, out_buf, c->pad, 1, c->encrypt_iv, 0);
            blocks--;
        }

        av_aes_crypt(c->aes_encrypt, &out_buf[c->pad_len ? BLOCKSIZE : 0],
                             &buf[c->pad_len ? BLOCKSIZE - c->pad_len: 0],
                             blocks, c->encrypt_iv, 0);

        ret = ffurl_write(c->hd, out_buf, out_size);
        av_free(out_buf);
        if (ret < 0)
            return ret;

        memcpy(c->pad, &buf[size - pad_len], pad_len);
    } else
        memcpy(&c->pad[c->pad_len], buf, size);

    c->pad_len = pad_len;

    return size;
}
Пример #3
0
static int crypto_read(URLContext *h, uint8_t *buf, int size)
{
    CryptoContext *c = h->priv_data;
    int blocks;
retry:
    if (c->outdata > 0) {
        size = FFMIN(size, c->outdata);
        memcpy(buf, c->outptr, size);
        c->outptr  += size;
        c->outdata -= size;
        c->position = c->position + size;
        return size;
    }
    // We avoid using the last block until we've found EOF,
    // since we'll remove PKCS7 padding at the end. So make
    // sure we've got at least 2 blocks, so we can decrypt
    // at least one.
    while (c->indata - c->indata_used < 2*BLOCKSIZE) {
        int n = ffurl_read(c->hd, c->inbuffer + c->indata,
                           sizeof(c->inbuffer) - c->indata);
        if (n <= 0) {
            c->eof = 1;
            break;
        }
        c->indata += n;
    }
    blocks = (c->indata - c->indata_used) / BLOCKSIZE;
    if (!blocks)
        return AVERROR_EOF;
    if (!c->eof)
        blocks--;
    av_aes_crypt(c->aes_decrypt, c->outbuffer, c->inbuffer + c->indata_used,
                 blocks, c->decrypt_iv, 1);
    c->outdata      = BLOCKSIZE * blocks;
    c->outptr       = c->outbuffer;
    c->indata_used += BLOCKSIZE * blocks;
    if (c->indata_used >= sizeof(c->inbuffer)/2) {
        memmove(c->inbuffer, c->inbuffer + c->indata_used,
                c->indata - c->indata_used);
        c->indata     -= c->indata_used;
        c->indata_used = 0;
    }
    if (c->eof) {
        // Remove PKCS7 padding at the end
        int padding = c->outbuffer[c->outdata - 1];
        c->outdata -= padding;
    }
    goto retry;
}
Пример #4
0
static int crypto_close(URLContext *h)
{
    CryptoContext *c = h->priv_data;
    uint8_t out_buf[BLOCKSIZE];
    int ret, pad;

    if (c->aes_encrypt) {
        pad = BLOCKSIZE - c->pad_len;
        memset(&c->pad[c->pad_len], pad, pad);
        av_aes_crypt(c->aes_encrypt, out_buf, c->pad, 1, c->encrypt_iv, 0);
        if ((ret =  ffurl_write(c->hd, out_buf, BLOCKSIZE)) < 0)
            return ret;
    }

    if (c->hd)
        ffurl_close(c->hd);
    av_freep(&c->aes_decrypt);
    av_freep(&c->aes_encrypt);
    return 0;
}
Пример #5
0
static int list_read(URLContext *h, unsigned char *buf, int size)
{   
	struct list_mgt *mgt = h->priv_data;
    int len=AVERROR(EIO);
	struct list_item *item=mgt->current_item;
	int retries = 10;
	
retry:	
	if (url_interrupt_cb()){     
		av_log(NULL, AV_LOG_ERROR," url_interrupt_cb\n");	
            	return AVERROR(EINTR);

	}
	//av_log(NULL, AV_LOG_INFO, "list_read start buf=%x,size=%d\n",buf,size);
	if(!mgt->cur_uio )
	{
		if(item && item->file)
		{
			ByteIOContext *bio;
			av_log(NULL, AV_LOG_INFO, "list_read switch to new file=%s\n",item->file);
			len=url_fopen(&bio,item->file,AVIO_FLAG_READ | URL_MINI_BUFFER | URL_NO_LP_BUFFER);
			if(len!=0)
			{
				av_log(NULL, AV_LOG_ERROR, "list url_fopen failed =%d\n",len);
				return len;
			}			
			if(url_is_file_list(bio,item->file))
			{
				mgt->have_sub_list = 1;
				/*have 32 bytes space at the end..*/
				memmove(item->file+5,item->file,strlen(item->file)+1);
				memcpy(item->file,"list:",5);
				url_fclose(bio);
				len=url_fopen(&bio,item->file,mgt->flags | URL_MINI_BUFFER | URL_NO_LP_BUFFER);
				if(len!=0)
				{
					av_log(NULL, AV_LOG_INFO, "file list url_fopen failed =%d\n",len);
					return len;
				}
			}else{
				if(item->ktype == KEY_AES_128){	
					if(item->key_ctx&&!item->crypto){
						item->crypto = av_mallocz(sizeof(struct AESCryptoContext));
						if(!item->crypto){							
							len = AVERROR(ENOMEM);
							return len;
						}
						item->crypto->aes =  av_mallocz(av_aes_size);		
						if(!item->crypto->aes){
							len = AVERROR(ENOMEM);
							return len;
						}
						
						av_aes_init(item->crypto->aes,item->key_ctx->key, 128, 1);
						item->crypto->have_init = 1;
						
					}
					bio->is_encrypted_media =1;
				}				
			}
			mgt->cur_uio=bio;
		}
	}
	if(mgt->cur_uio){
		if(size>0&&mgt->cur_uio->is_encrypted_media>0&&mgt->current_item->key_ctx&&mgt->current_item->crypto){//codes from crypto.c			
			int blocks;
			struct AESCryptoContext* c = mgt->current_item->crypto;
readagain:			
			len = 0;
			if (c->outdata > 0) {
				size = FFMIN(size, c->outdata);
				memcpy(buf, c->outptr, size);
				c->outptr  += size;
				c->outdata -= size;
				len =size;				
			}
			// We avoid using the last block until we've found EOF,
			// since we'll remove PKCS7 padding at the end. So make
			// sure we've got at least 2 blocks, so we can decrypt
			// at least one.
			while (c->indata - c->indata_used < 2*BLOCKSIZE) {
				int n = get_buffer(mgt->cur_uio,c->inbuffer + c->indata,
				                   sizeof(c->inbuffer) - c->indata);
				if (n <= 0) {
				    c->eof = 1;
				    break;
				}
				c->indata += n;				
			}
			blocks = (c->indata - c->indata_used) / BLOCKSIZE;
			if (blocks!=0){
				if (!c->eof)
					blocks--;
				av_aes_crypt(c->aes, c->outbuffer, c->inbuffer + c->indata_used, blocks,mgt->current_item->key_ctx->iv, 1);
				c->outdata      = BLOCKSIZE * blocks;
				c->outptr       = c->outbuffer;
				c->indata_used += BLOCKSIZE * blocks;
				if (c->indata_used >= sizeof(c->inbuffer)/2) {
					memmove(c->inbuffer, c->inbuffer + c->indata_used,
						c->indata - c->indata_used);
					c->indata     -= c->indata_used;
					c->indata_used = 0;
				}
				if (c->eof) {
					// Remove PKCS7 padding at the end
					int padding = c->outbuffer[c->outdata - 1];
					c->outdata -= padding;
				}

				if(len==0){
					goto readagain;
				}
			}else{
				len  =0;
			}				
			
			
		}else{
			len=get_buffer(mgt->cur_uio,buf,size);
		}
		//av_log(NULL, AV_LOG_INFO, "list_read get_buffer=%d\n",len);
	}
	if(len==AVERROR(EAGAIN))
		 return AVERROR(EAGAIN);/*not end,bug need to*/
	else if((len<=0)&& mgt->current_item!=NULL)
	{/*end of the file*/
		av_log(NULL, AV_LOG_INFO, "try switchto_next_item buf=%x,size=%d,len=%d\n",buf,size,len);

		if(item && (item->flags & ENDLIST_FLAG)){
		    if(mgt->cur_uio)
			    url_fclose(mgt->cur_uio);
    			av_log(NULL, AV_LOG_INFO, "ENDLIST_FLAG, return 0\n");
			return 0;
		}

		
		
		item=switchto_next_item(mgt);
		if(!item){
			if(mgt->flags&REAL_STREAMING_FLAG){
				fresh_item_list(mgt);	
				if(retries>0){
					retries --;
					goto retry;
				}
			}

			av_log(NULL, AV_LOG_INFO, "Need more retry by player logic\n");
			return AVERROR(EAGAIN);/*not end,but need to refresh the list later*/
		}
		if(mgt->cur_uio)
			url_fclose(mgt->cur_uio);
		mgt->cur_uio=NULL;
		mgt->current_item=item;
		
		if(item->flags & ENDLIST_FLAG){
			av_log(NULL, AV_LOG_INFO, "reach list end now!,item=%x\n",item);
			return 0;/*endof file*/
		}
		else if(item->flags & DISCONTINUE_FLAG){
			av_log(NULL, AV_LOG_INFO, "Discontiue item \n");
			//1 TODO:need to notify uper level stream is changed
			goto retry;
		}
		else{	
			av_log(NULL, AV_LOG_INFO, "[%s]item->flags=%x \n", __FUNCTION__, item->flags);
			goto retry;
		}
		
	}
	#if 0
	if(mgt->flags&REAL_STREAMING_FLAG&&mgt->item_num<4){ //force refresh items
		fresh_item_list(mgt);	
	}
	#endif

	//av_log(NULL, AV_LOG_INFO, "list_read end buf=%x,size=%d return len=%x\n",buf,size,len);
    return len;
}
Пример #6
0
int main(int argc, char **argv)
{
    int i, j;
    AVAES b;
    static const uint8_t rkey[2][16] = {
        { 0 },
        { 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3,
          0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59 }
    };
    static const uint8_t rpt[2][16] = {
        { 0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad,
          0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3 },
        { 0 }
    };
    static const uint8_t rct[2][16] = {
        { 0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7,
          0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf },
        { 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0,
          0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65 }
    };
    uint8_t pt[16], temp[16];
    int err = 0;

    av_log_set_level(AV_LOG_DEBUG);

    for (i = 0; i < 2; i++) {
        av_aes_init(&b, rkey[i], 128, 1);
        av_aes_crypt(&b, temp, rct[i], 1, NULL, 1);
        for (j = 0; j < 16; j++) {
            if (rpt[i][j] != temp[j]) {
                av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n",
                       j, rpt[i][j], temp[j]);
                err = 1;
            }
        }
    }

    if (argc > 1 && !strcmp(argv[1], "-t")) {
        AVAES ae, ad;
        AVLFG prng;

        av_aes_init(&ae, "PI=3.141592654..", 128, 0);
        av_aes_init(&ad, "PI=3.141592654..", 128, 1);
        av_lfg_init(&prng, 1);

        for (i = 0; i < 10000; i++) {
            for (j = 0; j < 16; j++)
                pt[j] = av_lfg_get(&prng);
            {
                START_TIMER;
                av_aes_crypt(&ae, temp, pt, 1, NULL, 0);
                if (!(i & (i - 1)))
                    av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n",
                           temp[0], temp[5], temp[10], temp[15]);
                av_aes_crypt(&ad, temp, temp, 1, NULL, 1);
                STOP_TIMER("aes");
            }
            for (j = 0; j < 16; j++) {
                if (pt[j] != temp[j]) {
                    av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n",
                           i, j, pt[j], temp[j]);
                }
            }
        }
    }
    return err;
}