Beispiel #1
0
static void afl_pkt_from_stdin(fko_srv_options_t *opts)
{
    FILE                *fp = NULL;
    fko_ctx_t           decode_ctx = NULL;
    unsigned char       spa_pkt[AFL_MAX_PKT_SIZE] = {0};
    int                 res = 0, es = EXIT_SUCCESS;
    char                dump_buf[AFL_DUMP_CTX_SIZE];

    fp = fdopen(STDIN_FILENO, "r");
    if(fp != NULL)
    {
        if(fgets((char *)spa_pkt, AFL_MAX_PKT_SIZE, fp) == NULL)
        {
            fclose(fp);
            clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
        }

        fclose(fp);

        fko_new(&decode_ctx);

        res = fko_set_encoded_data(decode_ctx, (char *) spa_pkt,
                strlen((char *)spa_pkt), 0, FKO_DIGEST_SHA256);

        if(res == FKO_SUCCESS)
            res = fko_set_spa_data(decode_ctx, (const char *) spa_pkt);
        if(res == FKO_SUCCESS)
            res = fko_decode_spa_data(decode_ctx);
        if(res == FKO_SUCCESS)
            res = dump_ctx_to_buffer(decode_ctx, dump_buf, sizeof(dump_buf));
        if(res == FKO_SUCCESS)
            log_msg(LOG_INFO, "%s", dump_buf);

        fko_destroy(decode_ctx);

        if(res == FKO_SUCCESS)
        {
            log_msg(LOG_INFO, "SPA packet decode: %s", fko_errstr(res));
            es = EXIT_SUCCESS;
        }
        else
        {
            log_msg(LOG_ERR, "Could not decode SPA packet: %s", fko_errstr(res));
            es = EXIT_FAILURE;
        }
    }
    else
        log_msg(LOG_ERR, "Could not acquire SPA packet from stdin.");

    clean_exit(opts, NO_FW_CLEANUP, es);
}
Beispiel #2
0
/* decode_spa_data
*/
static PyObject *
decode_spa_data(PyObject *self, PyObject *args)
{
    fko_ctx_t ctx;
    int res;

    if(!PyArg_ParseTuple(args, "k", &ctx))
        return NULL;

    res = fko_decode_spa_data(ctx);

    if(res != FKO_SUCCESS)
    {
        PyErr_SetString(FKOError, fko_errstr(res));
        return NULL;
    }

    return Py_BuildValue("", NULL);
}
Beispiel #3
0
/* Decode, decrypt, and parse SPA data into the context.
*/
static int
_rijndael_decrypt(fko_ctx_t ctx, const char *dec_key)
{
    char           *tbuf;
    unsigned char  *ndx;
    unsigned char  *cipher;
    int             cipher_len, pt_len, i, err = 0;

    int             b64_len = strlen(ctx->encrypted_msg);

    /* Now see if we need to add the "Salted__" string to the front of the
     * encrypted data.
    */
    if(strncmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT)))
    {
        /* We need to realloc space for the salt.
        */
        tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
        if(tbuf == NULL)
            return(FKO_ERROR_MEMORY_ALLOCATION);

        memmove(tbuf+strlen(B64_RIJNDAEL_SALT), tbuf, b64_len);

        ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));

        /* Adjust b64_len for added SALT value and Make sure we are still
         * a properly NULL-terminated string (Ubuntu was one system for
         * which this was an issue).
        */
        b64_len += strlen(B64_RIJNDAEL_SALT);
        tbuf[b64_len] = '\0';
    }

    /* Create a bucket for the (base64) decoded encrypted data and get the
     * raw cipher data.
    */
    cipher = malloc(strlen(ctx->encrypted_msg));
    if(cipher == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    if((cipher_len = b64_decode(ctx->encrypted_msg, cipher)) < 0)
        return(FKO_ERROR_INVALID_DATA);

    /* Create a bucket for the plaintext data and decrypt the message
     * data into it.
    */
    ctx->encoded_msg = malloc(cipher_len);
    if(ctx->encoded_msg == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    pt_len = rij_decrypt(cipher, cipher_len, dec_key, (unsigned char*)ctx->encoded_msg);

    /* Done with cipher...
    */
    free(cipher);

    /* The length of the decrypted data should be within 32 bytes of the
     * length of the encrypted version.
    */
    if(pt_len < (cipher_len - 32))
        return(FKO_ERROR_DECRYPTION_SIZE);

    /* At this point we can check the data to see if we have a good
     * decryption by ensuring the first field (16-digit random decimal
     * value) is valid and is followed by a colon.  Additional checks
     * are made in fko_decode_spa_data().
    */
    ndx = (unsigned char *)ctx->encoded_msg;
    for(i=0; i<FKO_RAND_VAL_SIZE; i++)
        if(!isdigit(*(ndx++)))
            err++;

    if(err > 0 || *ndx != ':')
        return(FKO_ERROR_DECRYPTION_FAILURE);

    /* Call fko_decode and return the results.
    */
    return(fko_decode_spa_data(ctx));
}
Beispiel #4
0
/* Prep and decrypt using gpgme
*/
static int
gpg_decrypt(fko_ctx_t ctx, const char *dec_key)
{
    char           *tbuf;
    unsigned char  *cipher;
    size_t          cipher_len;
    int             res;

    int             b64_len = strlen(ctx->encrypted_msg);

    /* Now see if we need to add the "hQ" string to the front of the
     * base64-encoded-GPG-encrypted data.
    */
    if(strncmp(ctx->encrypted_msg, B64_GPG_PREFIX, strlen(B64_GPG_PREFIX)))
    {
        /* We need to realloc space for the GPG prefix of hQ.
        */
        tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
        if(tbuf == NULL)
            return(FKO_ERROR_MEMORY_ALLOCATION);

        memmove(tbuf+strlen(B64_GPG_PREFIX), tbuf, b64_len);

        ctx->encrypted_msg = memcpy(tbuf, B64_GPG_PREFIX, strlen(B64_GPG_PREFIX));

        /* Adjust b64_len for added SALT value and Make sure we are still
         * a properly NULL-terminated string (Ubuntu was one system for
         * which this was an issue).
        */
        b64_len += strlen(B64_GPG_PREFIX);
        tbuf[b64_len] = '\0';
    }

    /* Create a bucket for the (base64) decoded encrypted data and get the
     * raw cipher data.
    */
    cipher = malloc(strlen(ctx->encrypted_msg));
    if(cipher == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    if((cipher_len = b64_decode(ctx->encrypted_msg, cipher)) < 0)
        return(FKO_ERROR_INVALID_DATA);

    /* Create a bucket for the plaintext data and decrypt the message
     * data into it.
    */
    /* --DSS Actually, the needed memory will be malloced in the gpgme_decrypt
    //       function. Just leaving this here for reference (for now).
    //ctx->encoded_msg = malloc(cipher_len);
    //if(ctx->encoded_msg == NULL)
    //    return(FKO_ERROR_MEMORY_ALLOCATION);
    */

    res = gpgme_decrypt(ctx, cipher, cipher_len,
        dec_key,  (unsigned char**)&ctx->encoded_msg, &cipher_len
    );

    /* Done with cipher...
    */
    free(cipher);

    if(res != FKO_SUCCESS)
        return(res);

    /* XXX: We could put some kind of sanity check  of the decrypted
     *      data here
    */

    /* Call fko_decode and return the results.
    */
    return(fko_decode_spa_data(ctx));
}
Beispiel #5
0
/* Prep and decrypt using gpgme
*/
static int
gpg_decrypt(fko_ctx_t ctx, const char *dec_key)
{
    unsigned char  *cipher;
    size_t          cipher_len;
    int             res, pt_len, b64_decode_len;

    /* Now see if we need to add the "hQ" string to the front of the
     * base64-encoded-GPG-encrypted data.
    */
    if(! ctx->added_gpg_prefix)
        add_gpg_prefix(ctx);

    /* Create a bucket for the (base64) decoded encrypted data and get the
     * raw cipher data.
    */
    cipher = malloc(ctx->encrypted_msg_len);
    if(cipher == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    if((b64_decode_len = b64_decode(ctx->encrypted_msg, cipher)) < 0)
    {
        if(zero_free((char *) cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
            return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_CIPHER_DECODEFAIL);
        else
            return(FKO_ERROR_ZERO_OUT_DATA);

    }

    cipher_len = b64_decode_len;

    /* Create a bucket for the plaintext data and decrypt the message
     * data into it.
    */
    /* --DSS Actually, the needed memory will be malloced in the gpgme_decrypt
    //       function. Just leaving this here for reference (for now).
    //ctx->encoded_msg = malloc(cipher_len);
    //if(ctx->encoded_msg == NULL)
    //    return(FKO_ERROR_MEMORY_ALLOCATION);
    */

    res = gpgme_decrypt(ctx, cipher, cipher_len,
        dec_key, (unsigned char**)&ctx->encoded_msg, &cipher_len
    );

    /* Done with cipher...
    */
    if(res != FKO_SUCCESS)
    {
        if(zero_free((char *) cipher, ctx->encrypted_msg_len) != FKO_SUCCESS)
            return(FKO_ERROR_ZERO_OUT_DATA);
        else
            return(res);
    }

    pt_len = strnlen(ctx->encoded_msg, MAX_SPA_ENCODED_MSG_SIZE);

    if(ctx->encoded_msg == NULL)
        return(FKO_ERROR_INVALID_DATA_ENCRYPT_DECRYPTED_MESSAGE_MISSING);

    if(! is_valid_encoded_msg_len(pt_len))
        return(FKO_ERROR_INVALID_DATA_ENCRYPT_DECRYPTED_MSGLEN_VALIDFAIL);

    ctx->encoded_msg_len = pt_len;

    /* Call fko_decode and return the results.
    */
    return(fko_decode_spa_data(ctx));
}
Beispiel #6
0
/* Decode, decrypt, and parse SPA data into the context.
*/
static int
_rijndael_decrypt(fko_ctx_t ctx,
    const char *dec_key, const int key_len, int encryption_mode)
{
    unsigned char  *ndx;
    unsigned char  *cipher;
    int             cipher_len, pt_len, i, err = 0, res = FKO_SUCCESS;
    int             zero_free_rv = FKO_SUCCESS;

    if(key_len > RIJNDAEL_MAX_KEYSIZE)
        return(FKO_ERROR_INVALID_KEY_LEN);

    /* Now see if we need to add the "Salted__" string to the front of the
     * encrypted data.
    */
    if(! ctx->added_salted_str)
    {
        res = add_salted_str(ctx);
        if(res != FKO_SUCCESS)
            return res;
    }

    /* Create a bucket for the (base64) decoded encrypted data and get the
     * raw cipher data.
    */
    cipher = malloc(ctx->encrypted_msg_len);
    if(cipher == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    if((cipher_len = b64_decode(ctx->encrypted_msg, cipher)) < 0)
    {
        if(zero_free((char *)cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
            return(FKO_ERROR_INVALID_DATA_ENCRYPT_CIPHERLEN_DECODEFAIL);
        else
            return(FKO_ERROR_ZERO_OUT_DATA);
    }

    /* Since we're using AES, make sure the incoming data is a multiple of
     * the blocksize
    */
    if((cipher_len % RIJNDAEL_BLOCKSIZE) != 0)
    {
        if(zero_free((char *)cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
            return(FKO_ERROR_INVALID_DATA_ENCRYPT_CIPHERLEN_VALIDFAIL);
        else
            return(FKO_ERROR_ZERO_OUT_DATA);
    }

    if(ctx->encoded_msg != NULL)
        zero_free_rv = zero_free(ctx->encoded_msg,
                strnlen(ctx->encoded_msg, MAX_SPA_ENCODED_MSG_SIZE));

    /* Create a bucket for the plaintext data and decrypt the message
     * data into it.
    */
    ctx->encoded_msg = malloc(cipher_len);
    if(ctx->encoded_msg == NULL)
    {
        if(zero_free((char *)cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
            return(FKO_ERROR_MEMORY_ALLOCATION);
        else
            return(FKO_ERROR_ZERO_OUT_DATA);
    }

    pt_len = rij_decrypt(cipher, cipher_len, dec_key, key_len,
                (unsigned char*)ctx->encoded_msg, encryption_mode);

    /* Done with cipher...
    */
    if(zero_free((char *)cipher, ctx->encrypted_msg_len) != FKO_SUCCESS)
        zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;

    /* The length of the decrypted data should be within 32 bytes of the
     * length of the encrypted version.
    */
    if(pt_len < (cipher_len - 32) || pt_len <= 0)
        return(FKO_ERROR_DECRYPTION_SIZE);

    if(ctx->encoded_msg == NULL)
        return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_ENCODEDMSG_NULL);

    if(! is_valid_encoded_msg_len(pt_len))
        return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_ENCODEDMSGLEN_VALIDFAIL);

    if(zero_free_rv != FKO_SUCCESS)
        return(zero_free_rv);

    ctx->encoded_msg_len = pt_len;

    /* At this point we can check the data to see if we have a good
     * decryption by ensuring the first field (16-digit random decimal
     * value) is valid and is followed by a colon.  Additional checks
     * are made in fko_decode_spa_data().
    */
    ndx = (unsigned char *)ctx->encoded_msg;
    for(i=0; i<FKO_RAND_VAL_SIZE; i++)
        if(!isdigit(*(ndx++)))
            err++;

    if(err > 0 || *ndx != ':')
        return(FKO_ERROR_DECRYPTION_FAILURE);

    /* Call fko_decode and return the results.
    */
    return(fko_decode_spa_data(ctx));
}
Beispiel #7
0
static void
spa_encoded_msg_fuzzing(void)
{
    fko_ctx_t      decode_ctx = NULL;
    int            res = 0, pkt_id, require_success, require_digest, digest_type, msg_len;
    int            line_ctr = 0, spa_payload_ctr = 0;
    FILE          *fz  = NULL;
    char           line[MAX_LINE_LEN] = {0};
    char           b64_encoded_msg[MAX_LINE_LEN] = {0};
    unsigned char  b64_decoded_msg[MAX_LINE_LEN] = {0};

    /* fuzzing file contents (or from stdin) are formatted like this:
     *
     * <pkt_ID> <status: success|fail> <digest: yes|no> <digest type> <base64_SPA_payload>
    */

    if ((fz = fopen("fuzz_spa_payloads", "r")) == NULL)
        return;

    while ((fgets(line, MAX_LINE_LEN, fz)) != NULL)
    {
        line_ctr++;
        line[MAX_LINE_LEN-1] = '\0';

        if (line[strlen(line)-1] == '\n')
            line[strlen(line)-1] = '\0';

        if(IS_EMPTY_LINE(line[0]))
            continue;

        if(sscanf(line, "%d %d %d %d %s", &pkt_id, &require_success,
                    &require_digest, &digest_type, b64_encoded_msg) != 5)
        {
            printf("[+] fuzzing parsing error at line: %d\n", line_ctr);
            continue;
        }

        msg_len = fko_base64_decode(b64_encoded_msg, b64_decoded_msg);

        spa_payload_ctr++;

        fko_new(&decode_ctx);

        if ((res = fko_set_encoded_data(decode_ctx, (char *) b64_decoded_msg,
                        msg_len, require_digest, digest_type)) != FKO_SUCCESS) {
            printf("[-] pkt_id: %d, fko_set_encoded_data(): %s\n", pkt_id, fko_errstr(res));
        }

        res = fko_decode_spa_data(decode_ctx);
        if (require_success) {
            if (res != FKO_SUCCESS) {
                printf("[-] pkt_id: %d, expected decode success but: fko_decode_spa_data(): %s\n",
                        pkt_id, fko_errstr(res));
            }
        } else {
            if (res == FKO_SUCCESS) {
                printf("[-] pkt_id: %d, expected decode failure but: fko_decode_spa_data(): %s\n",
                        pkt_id, fko_errstr(res));
            }
        }

        fko_destroy(decode_ctx);

        memset(line, 0x0, MAX_LINE_LEN);
        memset(b64_encoded_msg, 0x0, MAX_LINE_LEN);
    }

    fclose(fz);

    printf("[+] Sent %d SPA payloads through libfko encode/decode cycle...\n",
            spa_payload_ctr);
    return;
}