### 3.1 Creating Contexts ¶

Before doing anything with libfko, you need to create a context. A context is created for one of two reasons. One is for the purpose of building a new fko SPA message from scratch (typically to be packaged and sent to an fwknop server somewhere). The other would be a context for taking an existing SPA message for decoding, parsing, and data extraction.

For building a new fko SPA message, you will use the `fko_new` function:

Function: `int` fko_new `(fko_ctx_t *ctx)` ¶

  The function `fko_new` sets up and initializes a new `fko_ctx_t` object, pre-populates default values and returns a handle for it in ctx. The function returns the error code `FKO_SUCCESS` if the context was successfully created. Otherwise an another error code will be returned (see Error Handling for details on the various error codes and their meanings).

    fko_ctx_t   ctx;
    int         rc;

    rc = fko_new(&ctx);

    if(rc != FKO_SUCCESS)
    {
        fprintf(stderr, "Error %i from fko_new: %s\n",
            rc, fko_errstr(rc));
        exit(1);
    }

For a context that will be used for receiving and parsing an existing SPA message, you will use the `fko_new_with_data` function:

Function: `int` fko_new_with_data `(fko_ctx_t *ctx, const char *data, const char *key, const int key_len, int encryption_mode, const char hmac_key, const int hmac_key_len, const int hmac_type)` ¶

  The function `fko_new_with_data` sets up and initializes a new `fko_ctx_t` context, but instead of initializing default values, it stores the encrypted message data and makes it ready for parsing. This can be done in one of two ways. One is to pass `NULL` for the third argument. The context will be created and the data will be stored, but no decryption or decoding takes place. In this case, you will need to call `fko_decrypt_spa_data` at a later time. The other way to do it is to supply the key value (decryption passphrase) and assocated length. In this case, the context is created, the SPA data is decrypted, decoded, parsed, and stored in the context ready for retrieval. If an HMAC is also desired or required, then the hmac_key and associated length can be passed in. This will cause libfko to authenticate the SPA data before decryption is attempted; this is strongly recommended.

  The `fko_new_with_data` function returns the error code `FKO_SUCCESS` if the context was successfully created. If any of the intermediate steps in parsing the data, validating the SPA message digest, or any other internal action fails, then the appropriate error code is returned.

The most common (simple) case...

    fko_ctx_t   ctx;
    char       *spa_data;
    char       *key;
    int         key_len;
    char       *hmac_key;
    int         hmac_key_len;
    int         hmac_type = FKO_HMAC_SHA256;
    int         enc_mode  = FKO_ENC_MODE_CBC;
    int rc;

    /* Assume we called code that retrieves the data and key
    */

    rc = fko_new_with_data(&ctx, spa_data, key, key_len, \\
        enc_mode, hmac_key, hmac_key_len, hmac_type);

    if(rc != FKO_SUCCESS)
    {
        fprintf(stderr, "Error %i from fko_new_with_data: %s\n",
            rc, fkoerrstr(rc));
        exit(1);
    }

Or, perhaps you need to defer decryption and parsing to a later point in the program. We could use fko_new_with_data(), passing NULL for the decryption key and HMAC keys, or we could use fko_new() to create an empty context, then use fko_set_spa_data() to add the encypted data (see comments in the code samples).

    fko_ctx_t   ctx;
    char       *spa_data;
    char       *key;
    int rc;

    /* Assume we called code that retrieves the data and key
    */

    rc = fko_new_with_data(&ctx, spa_data, NULL, 0,
            FKO_ENC_MODE_CBC, NULL, 0, FKO_HMAC_SHA256);

    if(rc != FKO_SUCCESS)
    {
        fprintf(stderr, "Error from fko_new_with_data: %s\n",
            fko_errstr(rc));
        exit(1);
    }

    /* We could also just create and empty context and add the
     * encrypted data as follows:
     *
     * rc = fko_new(&ctx);
     * ... check rc ...
     * rc = fko_set_spa_data(ctx, spa_data);
     * ...
    */

    /* Assume we called other code and functions...  */

    /* Verify HMAC
    */
    rc = fko_verify_hmac(ctx, hmac_key, hmac_key_len);
    if(rc != FKO_SUCCESS)
    {
        fprintf(stderr, "Error from fko_verify_hmac: %s\n",
            fko_errstr(rc));
        exit(1);
    }

    /* Decrypt and decode...
    */
    rc = fko_decrypt_spa_data(ctx, key, key_len);

    if(rc != FKO_SUCCESS)
    {
        fprintf(stderr, "Error from fko_decrypt_spa_data: %s\n",
            fko_errstr(rc));
        exit(1);
    }