CK_RV aes_gcm_sample()

in src/derivation/ecdh.c [126:280]


CK_RV aes_gcm_sample(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR aes_key) {
    CK_RV rv;
    CK_BYTE_PTR plaintext = "plaintext payload to encrypt";
    CK_ULONG plaintext_length = (CK_ULONG) strlen(plaintext);
    CK_ULONG ciphertext_length = 0;
    CK_BYTE_PTR aad = "plaintext aad";
    CK_ULONG aad_length = (CK_ULONG) strlen(aad);
    CK_BYTE_PTR decrypted_ciphertext = NULL;
    CK_BYTE_PTR ciphertext = NULL;

    printf("Plaintext: %s\n", plaintext);
    printf("Plaintext length: %lu\n", plaintext_length);

    printf("AAD: %s\n", aad);
    printf("AAD length: %lu\n", aad_length);

    // Prepare the mechanism
    CK_MECHANISM mech;
    CK_GCM_PARAMS params;

    // Allocate memory to hold the HSM generated IV.
    CK_BYTE_PTR iv = malloc(AES_GCM_IV_SIZE);
    rv = 1;
    if (NULL == iv) {
        fprintf(stderr, "Failed to allocate IV memory\n");
        goto done;
    }
    memset(iv, 0, AES_GCM_IV_SIZE);

    // Setup the mechanism with the IV location and AAD information.
    params.pIv = iv;
    params.ulIvLen = AES_GCM_IV_SIZE;
    params.ulIvBits = 0;
    params.pAAD = aad;
    params.ulAADLen = aad_length;
    params.ulTagBits = AES_GCM_TAG_SIZE * 8;

    mech.mechanism = CKM_AES_GCM;
    mech.ulParameterLen = sizeof(params);
    mech.pParameter = &params;

    //**********************************************************************************************
    // Encrypt
    //**********************************************************************************************

    rv = funcs->C_EncryptInit(session, &mech, *aes_key);
    if (CKR_OK != rv) {
        fprintf(stderr, "Encryption Init failed: %lu\n", rv);
        goto done;
    }

    // Determine how much memory is required to store the ciphertext.
    rv = funcs->C_Encrypt(session, plaintext, plaintext_length, NULL, &ciphertext_length);

    // The ciphertext will be prepended with the HSM generated IV
    // so the length must include the IV
    ciphertext_length += AES_GCM_IV_SIZE;
    if (CKR_OK != rv) {
        fprintf(stderr, "Failed to find GCM ciphertext length\n");
        goto done;
    }

    // Allocate memory to store the ciphertext.
    ciphertext = malloc(ciphertext_length);
    if (NULL == ciphertext) {
        rv = 1;
        fprintf(stderr, "Failed to allocate ciphertext memory\n");
        goto done;
    }
    memset(ciphertext, 0, ciphertext_length);

    // Encrypt the data.
    rv = funcs->C_Encrypt(session, plaintext, plaintext_length, ciphertext + AES_GCM_IV_SIZE, &ciphertext_length);

    // Prepend HSM generated IV to ciphertext buffer
    memcpy(ciphertext, iv, AES_GCM_IV_SIZE);
    ciphertext_length += AES_GCM_IV_SIZE;
    if (CKR_OK != rv) {
        fprintf(stderr, "Encryption failed: %lu\n", rv);
        goto done;
    }

    // Ciphertext buffer = IV || ciphertext || TAG
    // Print the HSM generated IV
    printf("IV: ");
    print_bytes_as_hex(ciphertext, AES_GCM_IV_SIZE);
    printf("IV length: %d\n", AES_GCM_IV_SIZE);

    // Print just the ciphertext in hex format
    printf("Ciphertext: ");
    print_bytes_as_hex(ciphertext + AES_GCM_IV_SIZE, ciphertext_length - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE);
    printf("Ciphertext length: %lu\n", ciphertext_length - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE);

    // Print TAG in hex format
    printf("Tag: ");
    print_bytes_as_hex(ciphertext + AES_GCM_IV_SIZE + plaintext_length, ciphertext_length - AES_GCM_IV_SIZE - plaintext_length);
    printf("Tag length: %lu\n", ciphertext_length - AES_GCM_IV_SIZE - plaintext_length);

    //**********************************************************************************************
    // Decrypt
    //**********************************************************************************************

    // Use the IV that was prepended -- The first AES_GCM_IV_SIZE bytes of the ciphertext.
    params.pIv = ciphertext;
    mech.ulParameterLen = sizeof(params);
    mech.pParameter = &params;

    rv = funcs->C_DecryptInit(session, &mech, *aes_key);
    if (CKR_OK != rv) {
        fprintf(stderr, "Decryption Init failed: %lu\n", rv);
        goto done;
    }

    // Determine the length of decrypted ciphertext.
    CK_ULONG decrypted_ciphertext_length = 0;
    rv = funcs->C_Decrypt(session, ciphertext + AES_GCM_IV_SIZE, ciphertext_length - AES_GCM_IV_SIZE,
                          NULL, &decrypted_ciphertext_length);

    if (CKR_OK != rv) {
        fprintf(stderr, "Decryption failed: %lu\n", rv);
        goto done;
    }

    // Allocate memory for the decrypted cipher text.
    decrypted_ciphertext = malloc(decrypted_ciphertext_length);
    if (NULL == decrypted_ciphertext) {
        rv = 1;
        fprintf(stderr, "Could not allocate memory for decrypted ciphertext\n");
        goto done;
    }

    // Decrypt the ciphertext.
    rv = funcs->C_Decrypt(session, ciphertext + AES_GCM_IV_SIZE, ciphertext_length - AES_GCM_IV_SIZE,
                          decrypted_ciphertext, &decrypted_ciphertext_length);
    if (CKR_OK != rv) {
        fprintf(stderr, "Decryption failed: %lu\n", rv);
        goto done;
    }
    printf("Decrypted ciphertext: %.*s\n", (int)decrypted_ciphertext_length, decrypted_ciphertext);
    printf("Decrypted ciphertext length: %lu\n", decrypted_ciphertext_length);

done:
    if (NULL != iv) {
        free(iv);
    }

    if (NULL != ciphertext) {
        free(ciphertext);
    }

    if (NULL != decrypted_ciphertext) {
        free(decrypted_ciphertext);
    }
    return rv;
}