Skip to content

MPEG CENC in CBCS mode

Marcel Cornu edited this page Jun 30, 2020 · 6 revisions

Using intel-ipsec-mb for MPEG Common Encryption (ISO 23001-7) in “cbcs” mode

Introduction

The intel-ipsec-mb library can be used to accelerate MPEG Common Encryption (CENC) in “cbcs” mode by leverage SIMD instructions to process multiple buffers in parallel. Currently SSE and AVX instruction sets are supported to encrypt / decrypt either 4 or 8 buffers concurrently using the 1:9 crypt:skip pattern.

API Overview

AES-CBCS is done through the library’s asynchronous API (“job” API). The application submits multiple jobs to the library to be processed and jobs are returned in order. When the jobs are returned, depends on the underlying implementation and size of the jobs. Please refer to the Fast Multi-buffer IPsec Implementations on Intel® Architecture Processors whitepaper for more information on the job API and multi-buffer processing.

Encryption

The design of AES-CBC encryption specifies that every block to be encrypted has a dependency on the previous block. This means only single blocks can be encrypted at a time. In order to maximize throughput, multi-buffer job scheduling is used to encrypt multiple buffers in parallel. The library will wait until there are enough jobs (buffers to be processed) submitted before beginning encryption. As jobs are submitted, the multi-buffer manager (job scheduler) inserts each job into a “lane”. Until all lanes are populated, the API will return NULL. Once all lanes have been filled, jobs will start to be processed and for every new job submitted, a completed job will be returned. Jobs are returned in the same order that they were submitted. If there are no more jobs to be submitted, existing jobs can be flushed (i.e. forced to completion) from the multi-buffer manager.

Decryption

AES-CBC decryption does not have the same dependency as encryption. For this reason, decryption can be done using a single-buffer implementation to decrypt multiple blocks of a single buffer in parallel. Every job submitted is processed and returned immediately. No job scheduling is required.

API Usage

Below is a sample application to demonstrate how to use of AES-CBCS in 1:9 pattern and also to highlight the order that jobs are submitted and returned. In this example, the SSE implementation is used. This implementation supports processing 4 buffers in parallel for encryption by setting the following job (IMB_JOB structure) fields:
cipher_mode = IMB_CIPHER_CBCS_1_9
cipher_direction = IMB_DIR_ENCRYPT
chain_order = IMB_ORDER_CIPHER_HASH

For decryption, set the job fields to:
cipher_mode = IMB_CIPHER_CBCS_1_9
cipher_direction = IMB_DIR_DECRYPT
chain_order = IMB_ORDER_HASH_CIPHER

Other IMB_JOB fields of note:
hash_alg should be set to IMB_AUTH_NULL if no authentication is being performed. In this case the chain_order field does not matter.
msg_len_to_cipher_in_bytesset to the full length of the buffer to be processed.
src pointer to first block to be encrypted/decrypted.
dst pointer to output buffer (CBCS assumes in place processing (i.e. same in/out buffer)

Sample Application

#include <stdio.h>
#include <stdint.h>
#include <intel-ipsec-mb.h>

int main(int argc, char **argv)
{
    IMB_MGR *p_mgr = NULL;
    IMB_JOB *job = NULL;
    uint64_t flags = 0;
    uint32_t enc_keys[11*4] __attribute__((aligned(16))); // 16 byte keys * 11 rounds
    uint32_t dec_keys[11*4] __attribute__((aligned(16)));
    uint8_t buf[1024];
    int i, num_jobs = 10, jobs_rx = 0;
    uint8_t aes_key[16] = {0}; // 128b key
    uint8_t iv[16] = {0}; // 128b key

    /* allocate multi-buffer manager */
    p_mgr = alloc_mb_mgr(flags);
    if (p_mgr == NULL)
    {
        printf("Error allocating MB_MGR structure!\n");
        return EXIT_FAILURE;
    }

    /* initialize SSE mb_mgr */
    init_mb_mgr_sse(p_mgr);

    /* expand aes-128 key */
    IMB_AES_KEYEXP_128(p_mgr, aes_key, enc_keys, dec_keys);

    /* flush the scheduler */
    while ((job = IMB_FLUSH_JOB(p_mgr))!= NULL)
        ;

    /* submit jobs */
    printf("Submitting %d jobs...\n", num_jobs);

    for (i = 0; i < num_jobs; i++)
    {
        job = IMB_GET_NEXT_JOB(p_mgr);
        job->cipher_direction = IMB_DIR_ENCRYPT; // or IMB_DIR_DECRYPT
        job->chain_order = IMB_ORDER_CIPHER_HASH; //HASH_CIPHER for DECRYPT
        job->dst = buf;
        job->src = buf;
        job->cipher_mode = IMB_CIPHER_CBCS_1_9;
        job->enc_keys = enc_keys;
        job->dec_keys = dec_keys;
        job->key_len_in_bytes = 16;

        job->iv = iv;
        job->iv_len_in_bytes = 16;
        job->cipher_start_src_offset_in_bytes = 0;
        job->msg_len_to_cipher_in_bytes = sizeof(buf);
        job->hash_alg = IMB_AUTH_NULL;

        printf("Submitting job %i\n", i);
        job = IMB_SUBMIT_JOB(p_mgr);
        if (job == NULL) {
                printf("Recieved NULL\n");
        } else {
                jobs_rx++;
                printf("Recieved job!\n");
        }
    }

    /* flush the scheduler */
    printf("Flushing scheduler...\n");

    while ((job = IMB_FLUSH_JOB(p_mgr)) != NULL) {
            jobs_rx++;
            printf("Got flushed job\n");
    }

    printf("Received %d jobs total!\n", jobs_rx);

    free_mb_mgr(p_mgr);
}

Output

The above application outputs the following:

| ENCRYPTION             | DECRYPTION             |
|------------------------|------------------------|
| Submitting 10 jobs...  | Submitting 10 jobs...  |
| Submitting job 0       | Submitting job 0       |
| Recieved NULL          | Recieved job!          |
| Submitting job 1       | Submitting job 1       |
| Recieved NULL          | Recieved job!          |
| Submitting job 2       | Submitting job 2       |
| Recieved NULL          | Recieved job!          |
| Submitting job 3       | Submitting job 3       |
| Recieved job!          | Recieved job!          |
| Submitting job 4       | Submitting job 4       |
| Recieved job!          | Recieved job!          |
| Submitting job 5       | Submitting job 5       |
| Recieved job!          | Recieved job!          |
| Submitting job 6       | Submitting job 6       |
| Recieved job!          | Recieved job!          |
| Submitting job 7       | Submitting job 7       |
| Recieved job!          | Recieved job!          |
| Submitting job 8       | Submitting job 8       |
| Recieved job!          | Recieved job!          |
| Submitting job 9       | Submitting job 9       |
| Recieved job!          | Recieved job!          |
| Flushing scheduler...  | Flushing scheduler...  |
| Got flushed job        | Received 10 jobs total!|
| Got flushed job        |                        |
| Got flushed job        |                        |
| Received 10 jobs total!|                        |
Clone this wiki locally