# Encryption and Decryption with an AES Symmetric Key (CCM Mode) (C/C++)
For details, see [AES](crypto-sym-encrypt-decrypt-spec.md#aes).
## Adding the Dynamic Library in the CMake Script
```txt
target_link_libraries(entry PUBLIC libohcrypto.so)
```
## How to Develop
**Creating an Object**
Call [OH_CryptoSymKeyGenerator_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-key-h.md#oh_cryptosymkeygenerator_create) and [OH_CryptoSymKeyGenerator_Generate](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-key-h.md#oh_cryptosymkeygenerator_generate) to generate a symmetric key (**OH_CryptoSymKey**) with the key algorithm being AES and the key length being 128 bits.
In addition to the example in this topic, [AES](crypto-sym-key-generation-conversion-spec.md#aes) and [Randomly Generating a Symmetric Key](crypto-generate-sym-key-randomly-ndk.md) may help you better understand how to generate an AES symmetric key. Note that the input parameters in the reference documents may be different from those in the example below.
**Encrypting a Message**
1. Call [OH_CryptoSymCipher_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_create) with the string parameter **'AES128|CCM'** to create a **Cipher** instance for encryption. The key type is AES128, and the block cipher mode is CCM.
2. Call [OH_CryptoSymCipherParams_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipherparams_create) to create a parameter object and call [OH_CryptoSymCipherParams_SetParam](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipherparams_setparam) to set encryption parameters.
3. Call [OH_CryptoSymCipher_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_init) to initialize the **Cipher** instance. Specifically, set **mode** to **CRYPTO_ENCRYPT_MODE**, and specify the key for encryption (**OH_CryptoSymKey**) and the encryption parameter instance (**OH_CryptoSymCipherParams**) corresponding to the CCM mode.
4. Call [OH_CryptoSymCipher_Update](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_update) to update data (in plaintext).
Currently, the amount of data to be passed in by a single **update()** call is not limited. You can determine how to pass in data based on the data size.
> **NOTE**
> The CCM mode does not support segment-based encryption and decryption.
5. Call [OH_CryptoSymCipher_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_final) to obtain the encrypted data.
- If data has been passed in by **update()**, pass in **null** in the **data** parameter.
- Since **final()** might return **null**, always check its output before accessing any data.
> **NOTE**
> If CCM mode is used, **authTag** is set in **final()** as the authentication information initialized during decryption and needs to be saved.
6. Call [OH_CryptoSymCipherParams_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipherparams_create) to create a **Params** instance, and call [OH_CryptoSymCipherParams_SetParam](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipherparams_setparam) to set **authTag** as the authentication information for decryption.
In CCM mode, the algorithm library supports only 12-byte **authTag**, which is used for initialization authentication during decryption. In the following example, **authTag** is of 12 bytes.
**Decrypting a Message**
1. Call [OH_CryptoSymCipher_Create](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_create) with the parameter **'AES128|CCM'** to create a **Cipher** instance for decryption. The key type is AES128, and the block cipher mode is CCM.
2. Before decryption, call [OH_CryptoSymCipherParams_SetParam](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipherparams_setparam) to set **authTag** as the authentication information for initialization.
3. Call [OH_CryptoSymCipher_Init](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_init) to initialize the **Cipher** instance. Specifically, set **mode** to decryption mode, and specify the decryption key and the decryption parameter of the CCM mode.
4. Call [OH_CryptoSymCipher_Update](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_update) to update data (in ciphertext).
Currently, the amount of data to be passed in by a single **update()** call is not limited. You can determine how to pass in data based on the ciphertext size.
> **NOTE**
> The CCM mode does not support segment-based encryption and decryption.
5. Call [OH_CryptoSymCipher_Final](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_final) to obtain the decrypted data.
- If data has been passed in by **update()**, pass in **null** in the **data** parameter.
- Before accessing the **final()** output data, check whether the result is **null** to avoid exceptions.
**Destroying Objects**
Call [OH_CryptoSymKeyGenerator_Destroy](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-key-h.md#oh_cryptosymkeygenerator_destroy), [OH_CryptoSymCipher_Destroy](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-cipher-h.md#oh_cryptosymcipher_destroy), [OH_CryptoSymKey_Destroy](../../reference/apis-crypto-architecture-kit/capi-crypto-sym-key-h.md#oh_cryptosymkey_destroy), and [OH_Crypto_FreeDataBlob](../../reference/apis-crypto-architecture-kit/capi-crypto-common-h.md#oh_crypto_freedatablob) to release the allocated memory and destroy the symmetric key, cipher instance, and parameters.
- **Example**
```c++
#include "CryptoArchitectureKit/crypto_common.h"
#include "CryptoArchitectureKit/crypto_sym_cipher.h"
#include
static OH_Crypto_ErrCode doTestAesCcm()
{
OH_CryptoSymKeyGenerator *genCtx = nullptr;
OH_CryptoSymCipher *encCtx = nullptr;
OH_CryptoSymCipher *decCtx = nullptr;
OH_CryptoSymKey *keyCtx = nullptr;
OH_CryptoSymCipherParams *params = nullptr;
Crypto_DataBlob encData = {.data = nullptr, .len = 0};
Crypto_DataBlob decData = {.data = nullptr, .len = 0};
uint8_t aad[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // The aad value in the sample code is for reference only.
uint8_t tag[12] = {0};
uint8_t iv[7] = {1, 2, 4, 12, 3, 4, 2}; // The iv value in the sample code is for reference only.
Crypto_DataBlob ivData = {.data = iv, .len = sizeof(iv)};
Crypto_DataBlob aadData = {.data = aad, .len = sizeof(aad)};
Crypto_DataBlob tagData = {.data = tag, .len = sizeof(tag)};
Crypto_DataBlob tagOutPut = {.data = nullptr, .len = 0};
char *plainText = const_cast("this is test!");
Crypto_DataBlob msgBlob = {.data = (uint8_t *)(plainText), .len = strlen(plainText)};
// Generate a symmetric key.
OH_Crypto_ErrCode ret;
ret = OH_CryptoSymKeyGenerator_Create("AES128", &genCtx);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymKeyGenerator_Generate(genCtx, &keyCtx);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
// Set parameters.
ret = OH_CryptoSymCipherParams_Create(¶ms);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_IV_DATABLOB, &ivData);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_AAD_DATABLOB, &aadData);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, &tagData);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
// Encrypt the message.
ret = OH_CryptoSymCipher_Create("AES128|CCM", &encCtx);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipher_Init(encCtx, CRYPTO_ENCRYPT_MODE, keyCtx, params);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipher_Update(encCtx, &msgBlob, &encData);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipher_Final(encCtx, nullptr, &tagOutPut);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
// Decrypt the message.
ret = OH_CryptoSymCipher_Create("AES128|CCM", &decCtx);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, &tagOutPut);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipher_Init(decCtx, CRYPTO_DECRYPT_MODE, keyCtx, params);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipher_Update(decCtx, &encData, &decData);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
ret = OH_CryptoSymCipher_Final(decCtx, nullptr, &decData);
if (ret != CRYPTO_SUCCESS) {
goto end;
}
end:
OH_CryptoSymCipherParams_Destroy(params);
OH_CryptoSymCipher_Destroy(encCtx);
OH_CryptoSymCipher_Destroy(decCtx);
OH_CryptoSymKeyGenerator_Destroy(genCtx);
OH_CryptoSymKey_Destroy(keyCtx);
OH_Crypto_FreeDataBlob(&encData);
OH_Crypto_FreeDataBlob(&decData);
OH_Crypto_FreeDataBlob(&tagOutPut);
return ret;
}
```