AES harness¶
Test encryption¶
To test a function that encrypts with AES, the harness function must:
- follow the naming convention; 
- conform to the function signature. 
Naming convention¶
CC_AES_<mode>_encrypt
Where mode is one of: ECB, CBC, CBCPKCS7, CTR, CFB8, CFB128.
This tests all key lengths. A specific one can be indicated:
CC_AES_<mode>_<length>_encrypt
Where length is one of 128, 192, or 256.
Function signature¶
- int AES_encrypt(
- uint8_t *ciphertext,
- size_t ciphertext_size,
- const uint8_t *plaintext,
- size_t plaintext_size,
- const uint8_t *key,
- size_t key_size,
- const uint8_t *iv,
- size_t iv_size,
- Encrypts a plaintext with AES. - Parameters:
- ciphertext – [Out] An allocated buffer to return the resulting ciphertext. 
- ciphertext_size – [In] The size of - ciphertextin bytes.
- plaintext – [In] The plaintext to encrypt. 
- plaintext_size – [In] The size of - plaintextin bytes.
- key – [In] The symmetric key to use. 
- key_size – [In] The size of - keyin bytes. Passed even when specifying the key size.
- iv – [In] The IV to use. Not used for ECB mode. 
- iv_size – [In] The size of - ivin bytes. 0 if the IV is not used.
 
- Returns:
- A status value. 
- Return values:
- 1 – Operation successful. 
- 0 – An error occurred. 
 
 
Example¶
#include <openssl/evp.h>
// Define a generic function to use for all modes.
int encrypt(const EVP_CIPHER *cipher, uint8_t *ciphertext,
            size_t ciphertext_size, const uint8_t *plaintext,
            size_t plaintext_size, const uint8_t *key, size_t key_size,
            const uint8_t *iv, size_t iv_size);
int CC_AES_ECB_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size) {
  return encrypt(EVP_aes_256_ecb(), ciphertext, ciphertext_size, plaintext,
                 plaintext_size, key, key_size, iv, iv_size);
}
int CC_AES_CBC_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size) {
  return encrypt(EVP_aes_256_cbc(), ciphertext, ciphertext_size, plaintext,
                 plaintext_size, key, key_size, iv, iv_size);
}
int CC_AES_CTR_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size) {
  return encrypt(EVP_aes_256_ctr(), ciphertext, ciphertext_size, plaintext,
                 plaintext_size, key, key_size, iv, iv_size);
}
int CC_AES_CFB8_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                            const uint8_t *plaintext, size_t plaintext_size,
                            const uint8_t *key, size_t key_size,
                            const uint8_t *iv, size_t iv_size) {
  return encrypt(EVP_aes_256_cfb8(), ciphertext, ciphertext_size, plaintext,
                 plaintext_size, key, key_size, iv, iv_size);
}
int CC_AES_CFB128_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                              const uint8_t *plaintext, size_t plaintext_size,
                              const uint8_t *key, size_t key_size,
                              const uint8_t *iv, size_t iv_size) {
  return encrypt(EVP_aes_256_cfb128(), ciphertext, ciphertext_size, plaintext,
                 plaintext_size, key, key_size, iv, iv_size);
}
// CBC-PKCS7 uses padding, unlike the other modes.
int CC_AES_CBCPKCS7_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                                const uint8_t *plaintext, size_t plaintext_size,
                                const uint8_t *key, size_t key_size,
                                const uint8_t *iv, size_t iv_size) {
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  int len = 0;
  if (!ctx)
    goto error;
  if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    goto error;
  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_size))
    goto error;
  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
    goto error;
  EVP_CIPHER_CTX_free(ctx);
  return 1;
error:
  EVP_CIPHER_CTX_free(ctx);
  return 0;
}
int encrypt(const EVP_CIPHER *cipher, uint8_t *ciphertext,
            size_t ciphertext_size, const uint8_t *plaintext,
            size_t plaintext_size, const uint8_t *key, size_t key_size,
            const uint8_t *iv, size_t iv_size) {
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  int len = 0;
  if (!ctx)
    goto error;
  // Disable padding, as the test vectors are without it.
  EVP_CIPHER_CTX_set_padding(ctx, 0);
  if (1 != EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
    goto error;
  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_size))
    goto error;
  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
    goto error;
  EVP_CIPHER_CTX_free(ctx);
  return 1;
error:
  EVP_CIPHER_CTX_free(ctx);
  return 0;
}
Compile with:
gcc -fPIC -shared -o AES_openssl_encrypt.so AES_openssl_encrypt.c -lssl -lcrypto
Then test with:
crypto-condor-cli test harness AES_openssl_encrypt.so
Test authenticated encryption¶
To test a function that encrypts with an AEAD mode, the harness function must:
- follow the naming convention; 
- conform to the function signature. 
Naming convention¶
CC_AES_<mode>_encrypt
Where mode is one of: CCM, GCM.
This tests all key lengths. A specific one can be indicated:
CC_AES_<mode>_<length>_encrypt
Where length is one of 128, 192, or 256.
Function signature¶
- int AES_encrypt_aead(
- uint8_t *ciphertext,
- size_t ciphertext_size,
- uint8_t *mac,
- size_t mac_size,
- const uint8_t *plaintext,
- size_t plaintext_size,
- const uint8_t *key,
- size_t key_size,
- const uint8_t *iv,
- size_t iv_size,
- const uint8_t *aad,
- size_t aad_size,
- Encrypts a plaintext with AES and an AEAD mode of operation. - Parameters:
- ciphertext – [Out] An allocated buffer to return the resulting ciphertext. 
- ciphertext_size – [In] The size of - ciphertextin bytes.
- mac – [Out] An allocated buffer to return the resulting MAC tag. 
- mac_size – [In] The size of - macin bytes.
- plaintext – [In] The plaintext to encrypt. 
- plaintext_size – [In] The size of - plaintextin bytes.
- key – [In] The symmetric key to use. 
- key_size – [In] The size of - keyin bytes. Passed even when specifying the key size.
- iv – [In] The IV to use. Not used for ECB mode. 
- iv_size – [In] The size of - ivin bytes. 0 if the IV is not used.
 
- Returns:
- A status value. 
- Return values:
- 1 – Operation successful. 
- 0 – An error occurred. 
 
 
Example¶
#include <openssl/evp.h>
int CC_AES_GCM_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                           uint8_t *mac, size_t mac_size,
                           const uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *nonce, size_t nonce_size,
                           const uint8_t *aad, size_t aad_size) {
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  int len;
  if (!ctx)
    goto error;
  if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
    goto error;
  if (1 !=
      EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce_size, NULL)) {
    fprintf(stderr, "Failed to set IV len\n");
    goto error;
  }
  if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce))
    goto error;
  if (1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_size))
    goto error;
  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_size))
    goto error;
  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
    goto error;
  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, mac_size, mac))
    goto error;
  EVP_CIPHER_CTX_free(ctx);
  return 1;
error:
  EVP_CIPHER_CTX_free(ctx);
  return 0;
}
int CC_AES_CCM_256_encrypt(uint8_t *ciphertext, size_t ciphertext_size,
                           uint8_t *mac, size_t mac_size,
                           const uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *nonce, size_t nonce_size,
                           const uint8_t *aad, size_t aad_size) {
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  int len;
  if (!ctx)
    goto error;
  if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))
    goto error;
  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, nonce_size, NULL))
    goto error;
  EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, mac_size, NULL);
  if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce))
    goto error;
  // Provide total plaintext length.
  if (1 != EVP_EncryptUpdate(ctx, NULL, &len, NULL, plaintext_size))
    goto error;
  // Provide any AAD data.
  if (aad_size > 0) {
    if (1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_size))
      goto error;
  }
  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_size))
    goto error;
  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
    goto error;
  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, mac_size, mac))
    goto error;
  EVP_CIPHER_CTX_free(ctx);
  return 1;
error:
  EVP_CIPHER_CTX_free(ctx);
  return 0;
}
Compile with:
gcc -fPIC -shared -o AES_openssl_encrypt_aead.so AES_openssl_encrypt_aead.c -lssl -lcrypto
Then test with:
crypto-condor-cli test harness AES_openssl_encrypt_aead.so
Test decryption¶
To test a function that decrypts with AES, the harness function must:
- follow the naming convention; 
- conform to the function signature. 
Naming convention¶
CC_AES_<mode>_decrypt
Where mode is one of: CCM, GCM.
This tests all key lengths. A specific one can be indicated:
CC_AES_<mode>_<length>_decrypt
Where length is one of 128, 192, or 256.
Function signature¶
- int AES_decrypt(
- uint8_t *plaintext,
- size_t plaintext_size,
- const uint8_t *ciphertext,
- size_t ciphertext_size,
- const uint8_t *key,
- size_t key_size,
- const uint8_t *iv,
- size_t iv_size,
- Decrypts a ciphertext with AES. - Parameters:
- plaintext – [Out] An allocated buffer to return the resulting plaintext. 
- plaintext_size – [In] The size of - plaintextin bytes.
- ciphertext – [In] The ciphertext to decrypt. 
- ciphertext_size – [In] The size of - ciphertextin bytes.
- key – [In] The symmetric key to use. 
- key_size – [In] The size of - keyin bytes. Passed even when specifying the key size.
- iv – [In] The IV to use. Not used for ECB mode. 
- iv_size – [In] The size of - ivin bytes. 0 if the IV is not used.
 
- Returns:
- The actual size of the (unpadded) plaintext, or -1 if an error occurred. 
 
Example¶
#include <openssl/evp.h>
int decrypt(const EVP_CIPHER *cipher, uint8_t *plaintext, size_t plaintext_size,
            const uint8_t *ciphertext, size_t ciphertext_size,
            const uint8_t *key, size_t key_size, const uint8_t *iv,
            size_t iv_size);
int CC_AES_ECB_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size) {
  return decrypt(EVP_aes_256_ecb(), plaintext, plaintext_size, ciphertext,
                 ciphertext_size, key, key_size, iv, iv_size);
}
int CC_AES_CBC_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size) {
  return decrypt(EVP_aes_256_cbc(), plaintext, plaintext_size, ciphertext,
                 ciphertext_size, key, key_size, iv, iv_size);
}
int CC_AES_CTR_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size) {
  return decrypt(EVP_aes_256_ctr(), plaintext, plaintext_size, ciphertext,
                 ciphertext_size, key, key_size, iv, iv_size);
}
int CC_AES_CFB8_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                            const uint8_t *ciphertext, size_t ciphertext_size,
                            const uint8_t *key, size_t key_size,
                            const uint8_t *iv, size_t iv_size) {
  return decrypt(EVP_aes_256_cfb8(), plaintext, plaintext_size, ciphertext,
                 ciphertext_size, key, key_size, iv, iv_size);
}
int CC_AES_CFB128_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                              const uint8_t *ciphertext, size_t ciphertext_size,
                              const uint8_t *key, size_t key_size,
                              const uint8_t *iv, size_t iv_size) {
  return decrypt(EVP_aes_256_cfb128(), plaintext, plaintext_size, ciphertext,
                 ciphertext_size, key, key_size, iv, iv_size);
}
int CC_AES_CBCPKCS7_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                              const uint8_t *ciphertext, size_t ciphertext_size,
                              const uint8_t *key, size_t key_size,
                              const uint8_t *iv, size_t iv_size) {
  int pt_len = 0, len = 0;
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  if (!ctx)
    goto error;
  if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    goto error;
  if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_size))
    goto error;
  pt_len += len;
  if (!EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
    goto error;
  pt_len += len;
  EVP_CIPHER_CTX_free(ctx);
  return pt_len;
error:
  EVP_CIPHER_CTX_free(ctx);
  return -1;
}
int decrypt(const EVP_CIPHER *cipher, uint8_t *plaintext, size_t plaintext_size,
            const uint8_t *ciphertext, size_t ciphertext_size,
            const uint8_t *key, size_t key_size, const uint8_t *iv,
            size_t iv_size) {
  int len = 0, pt_len = 0;
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  if (!ctx)
    goto error;
  if (1 != EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv))
    goto error;
  EVP_CIPHER_CTX_set_padding(ctx, 0);
  if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_size))
    goto error;
  pt_len += len;
  if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
    goto error;
  pt_len += len;
  EVP_CIPHER_CTX_free(ctx);
  return pt_len;
error:
  EVP_CIPHER_CTX_free(ctx);
  return -1;
}
Compile with:
gcc -fPIC -shared -o AES_openssl_decrypt.so AES_openssl_decrypt.c -lssl -lcrypto
Then test with:
crypto-condor-cli test harness AES_openssl_decrypt.so
Test authenticated decryption¶
To test a function that decrypts with an AEAD mode, the harness function must:
- follow the naming convention; 
- conform to the function signature. 
Naming convention¶
CC_AES_<mode>_decrypt
Where mode is one of: CCM, GCM.
This tests all key lengths. A specific one can be indicated:
CC_AES_<mode>_<length>_decrypt
Where length is one of 128, 192, or 256.
Function signature¶
- int AES_decrypt_aead(
- uint8_t *plaintext,
- size_t plaintext_size,
- const uint8_t *ciphertext,
- size_t ciphertext_size,
- const uint8_t *mac,
- size_t mac_size,
- const uint8_t *key,
- size_t key_size,
- const uint8_t *iv,
- size_t iv_size,
- const uint8_t *aad,
- size_t aad_size,
- Decrypts a ciphertext with AES and an AEAD mode of operation. - Parameters:
- plaintext – [Out] An allocated buffer to return the resulting plaintext. 
- plaintext_size – [In] The size of - plaintextin bytes.
- ciphertext – [In] The ciphertext to decrypt. 
- ciphertext_size – [In] The size of - ciphertextin bytes.
- mac – [In] The MAC tag to verify. 
- mac_size – [In] The size of - macin bytes.
- key – [In] The symmetric key to use. 
- key_size – [In] The size of - keyin bytes. Passed even when specifying the key size.
- iv – [In] The IV to use. Not used for ECB mode. 
- iv_size – [In] The size of - ivin bytes. 0 if the IV is not used.
 
- Returns:
- A status value. 
- Return values:
- 1 – Operation successful. 
- 0 – An error occurred. 
- -1 – The MAC tag is invalid. 
 
 
Example¶
#include <openssl/evp.h>
int CC_AES_GCM_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *mac, size_t mac_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size,
                           const uint8_t *aad, size_t aad_size) {
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  int len = 0;
  if (!ctx)
    goto error;
  if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
    goto error;
  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_size, NULL))
    goto error;
  if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
    goto error;
  if (aad_size > 0)
    if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_size))
      goto error;
  if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_size))
    goto error;
  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, mac_size, (void *)mac))
    goto error;
  if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
    EVP_CIPHER_CTX_free(ctx);
    return -1;
  }
  EVP_CIPHER_CTX_free(ctx);
  return 1;
error:
  EVP_CIPHER_CTX_free(ctx);
  return 0;
}
int CC_AES_CCM_256_decrypt(uint8_t *plaintext, size_t plaintext_size,
                           const uint8_t *ciphertext, size_t ciphertext_size,
                           const uint8_t *mac, size_t mac_size,
                           const uint8_t *key, size_t key_size,
                           const uint8_t *iv, size_t iv_size,
                           const uint8_t *aad, size_t aad_size) {
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  int len = 0;
  if (!ctx)
    goto error;
  if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))
    goto error;
  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_size, NULL))
    goto error;
  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, mac_size, (void *)mac))
    goto error;
  if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
    goto error;
  // Provide total ciphertext length.
  if (!EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_size))
    goto error;
  if (aad_size > 0)
    if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_size))
      goto error;
  if (1 !=
      EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_size)) {
    EVP_CIPHER_CTX_free(ctx);
    return -1;
  }
  EVP_CIPHER_CTX_free(ctx);
  return 1;
error:
  EVP_CIPHER_CTX_free(ctx);
  return 0;
}
Compile with:
gcc -fPIC -shared -o AES_openssl_decrypt_aead.so AES_openssl_decrypt_aead.c -lssl -lcrypto
Then test with:
crypto-condor-cli test harness AES_openssl_decrypt_aead.so