Add ccm_init/free()
diff --git a/include/polarssl/ccm.h b/include/polarssl/ccm.h
index b794cd8..24405e4 100644
--- a/include/polarssl/ccm.h
+++ b/include/polarssl/ccm.h
@@ -36,6 +36,34 @@
 extern "C" {
 #endif
 
+/**
+ * \brief          CCM context structure
+ */
+typedef struct {
+    cipher_context_t cipher_ctx;    /*!< cipher context used */
+}
+ccm_context;
+
+/**
+ * \brief           CCM initialization (encryption and decryption)
+ *
+ * \param ctx       CCM context to be initialized
+ * \param cipher    cipher to use (a 128-bit block cipher)
+ * \param key       encryption key
+ * \param keysize   key size in bits (must be acceptable by the cipher)
+ *
+ * \return          0 if successful, or a cipher specific error code
+ */
+int ccm_init( ccm_context *ctx, cipher_id_t cipher,
+              const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief           Free a CCM context and underlying cipher sub-context
+ *
+ * \param ctx       CCM context to free
+ */
+void ccm_free( ccm_context *ctx );
+
 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
 /**
  * \brief          Checkup routine
diff --git a/library/ccm.c b/library/ccm.c
index b4ba3d5..453edfb 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -42,6 +42,45 @@
 
 #include "polarssl/ccm.h"
 
+/*
+ * Initialize context
+ */
+int ccm_init( ccm_context *ctx, cipher_id_t cipher,
+              const unsigned char *key, unsigned int keysize )
+{
+    int ret;
+    const cipher_info_t *cipher_info;
+
+    memset( ctx, 0, sizeof( ccm_context ) );
+
+    cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( cipher_info->block_size != 16 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
+                               POLARSSL_ENCRYPT ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Free context
+ */
+void ccm_free( ccm_context *ctx )
+{
+    (void) cipher_free_ctx( &ctx->cipher_ctx );
+    memset( ctx, 0, sizeof( ccm_context ) );
+}
+
 
 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
 
diff --git a/tests/suites/test_suite_ccm.data b/tests/suites/test_suite_ccm.data
index 223e28a..61ae831 100644
--- a/tests/suites/test_suite_ccm.data
+++ b/tests/suites/test_suite_ccm.data
@@ -1,2 +1,18 @@
 CCM self test
 ccm_self_test:
+
+CCM init #1 AES-128: OK
+depends_on:POLARSSL_AES_C
+ccm_init:POLARSSL_CIPHER_ID_AES:128:0
+
+CCM init #2 CAMELLIA-256: OK
+depends_on:POLARSSL_CAMELLIA_C
+ccm_init:POLARSSL_CIPHER_ID_CAMELLIA:256:0
+
+CCM init #3 AES-224: bad key size
+depends_on:POLARSSL_AES_C
+ccm_init:POLARSSL_CIPHER_ID_AES:224:POLARSSL_ERR_CCM_BAD_INPUT
+
+CCM init #4 BLOWFISH-128: bad block size
+depends_on:POLARSSL_BLOWFISH_C
+ccm_init:POLARSSL_CIPHER_ID_BLOWFISH:128:POLARSSL_ERR_CCM_BAD_INPUT
diff --git a/tests/suites/test_suite_ccm.function b/tests/suites/test_suite_ccm.function
index 487d1c5..7137a60 100644
--- a/tests/suites/test_suite_ccm.function
+++ b/tests/suites/test_suite_ccm.function
@@ -13,3 +13,20 @@
     TEST_ASSERT( ccm_self_test( 0 ) == 0 );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void ccm_init( int cipher_id, int key_size, int result )
+{
+    ccm_context ctx;
+    unsigned char key[32];
+    int ret;
+
+    memset( key, 0x2A, sizeof( key ) );
+    TEST_ASSERT( (unsigned) key_size <= 8 * sizeof( key ) );
+
+    ret = ccm_init( &ctx, cipher_id, key, key_size );
+    TEST_ASSERT( ret == result );
+
+    ccm_free( &ctx );
+}
+/* END_CASE */