Example #1
0
/**
 * \brief Mixes new input data into the chaining key.
 *
 * \param state The SymmetricState object.
 * \param input Points to the input data to mix in.
 * \param size The size of the \a input data in bytes.
 *
 * \return NOISE_ERROR_NONE on success.
 * \return NOISE_ERROR_INVALID_PARAM if \a state or \a input is NULL.
 * \return NOISE_ERROR_INVALID_STATE if the \a state has already been split.
 *
 * \sa noise_symmetricstate_mix_hash(), noise_symmetricstate_split()
 */
int noise_symmetricstate_mix_key
    (NoiseSymmetricState *state, const uint8_t *input, size_t size)
{
    uint8_t temp_k[NOISE_MAX_HASHLEN];
    size_t hash_len;
    size_t key_len;

    /* Validate the parameters */
    if (!state || !input)
        return NOISE_ERROR_INVALID_PARAM;

    /* If the state has been split, then we cannot do this */
    if (!state->cipher)
        return NOISE_ERROR_INVALID_STATE;

    /* Mix the input data in using HKDF */
    hash_len = noise_hashstate_get_hash_length(state->hash);
    key_len = noise_cipherstate_get_key_length(state->cipher);
    noise_hashstate_hkdf
        (state->hash, state->ck, hash_len, input, size,
         state->ck, hash_len, temp_k, key_len);

    /* Change the cipher key, or set it for the first time */
    noise_cipherstate_init_key(state->cipher, temp_k, key_len);
    noise_clean(temp_k, sizeof(temp_k));
    return NOISE_ERROR_NONE;
}
Example #2
0
/* Measure the performance of an AEAD primitive */
static void perf_cipher(int id)
{
    static uint8_t const key[32] = {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
        0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
        0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
        0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20
    };
    static uint8_t const ad[32] = {
        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
        0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x20,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
        0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40
    };
    NoiseCipherState *cipher;
    uint8_t data[BLOCK_SIZE + 16];
    timestamp_t start, end;
    int count;
    double elapsed;
    NoiseBuffer mbuf;

    if (noise_cipherstate_new_by_id(&cipher, id) != NOISE_ERROR_NONE)
        return;

    memset(data, 0xAA, sizeof(data));
    noise_cipherstate_init_key(cipher, key, sizeof(key));
    start = current_timestamp();
    for (count = 0; count < (MB_COUNT * BLOCKS_PER_MB); ++count) {
        noise_buffer_set_inout(mbuf, data, sizeof(data) - 16, sizeof(data));
        noise_cipherstate_encrypt_with_ad(cipher, ad, sizeof(ad), &mbuf);
    }
    end = current_timestamp();

    elapsed = elapsed_to_seconds(start, end) / (double)MB_COUNT;
    printf("%-20s%8.2f          %8.2f\n",
           noise_id_to_name(NOISE_CIPHER_CATEGORY, id),
           1.0 / elapsed, units / elapsed);

    noise_cipherstate_free(cipher);
}
Example #3
0
/**
 * \brief Splits the transport encryption CipherState objects out of
 * this SymmetricState object.
 *
 * \param state The SymmetricState object.
 * \param c1 Points to the variable where to place the pointer to the
 * first CipherState object.  This can be NULL if the application is
 * using a one-way handshake pattern.
 * \param c2 Points to the variable where to place the pointer to the
 * second CipherState object.  This can be NULL if the application is
 * using a one-way handshake pattern.
 * \param secondary_key Points to an optional "secondary symmetric key"
 * from a parallel non-DH handshake to mix into the final cipher keys.
 * This may be NULL if \a secondary_key_len is zero.
 * \param secondary_key_len Length of \a secondary_key in bytes.
 * This must be either zero or 32 to comply with the requirements from
 * the Noise protocol specification.
 *
 * \return NOISE_ERROR_NONE on success.
 * \return NOISE_ERROR_INVALID_PARAM if \a state is NULL.
 * \return NOISE_ERROR_INVALID_PARAM if both \a c1 and \a c2 are NULL.
 * \return NOISE_ERROR_INVALID_PARAM if \a secondary_key is NULL and
 * \a secondary_key_len is not zero.
 * \return NOISE_ERROR_INVALID_LENGTH if \a secondary_key_len is not zero or 32.
 * \return NOISE_ERROR_INVALID_STATE if the \a state has already been split.
 * \return NOISE_ERROR_NO_MEMORY if there is insufficient memory to create
 * the new CipherState objects.
 *
 * Once a SymmetricState has been split, it is effectively finished and
 * cannot be used for future encryption or hashing operations.
 * If those operations are invoked, the relevant functions will return
 * NOISE_ERROR_INVALID_STATE.
 *
 * The \a c1 object should be used to protect messages from the initiator to
 * the responder, and the \a c2 object should be used to protect messages
 * from the responder to the initiator.
 *
 * If the handshake pattern is one-way, then the application should call
 * noise_cipherstate_free() on the object that is not needed.  Alternatively,
 * the application can pass NULL to noise_symmetricstate_split() as the
 * \a c1 or \a c2 argument and the second CipherState will not be created
 * at all.
 */
int noise_symmetricstate_split
    (NoiseSymmetricState *state, NoiseCipherState **c1, NoiseCipherState **c2,
     const uint8_t *secondary_key, size_t secondary_key_len)
{
    uint8_t temp_k1[NOISE_MAX_HASHLEN];
    uint8_t temp_k2[NOISE_MAX_HASHLEN];
    size_t hash_len;
    size_t key_len;

    /* Validate the parameters */
    if (!state)
        return NOISE_ERROR_INVALID_PARAM;
    if (!c1 && !c2)
        return NOISE_ERROR_INVALID_PARAM;
    if (!secondary_key && secondary_key_len)
        return NOISE_ERROR_INVALID_PARAM;
    if (secondary_key_len != 0 && secondary_key_len != 32)
        return NOISE_ERROR_INVALID_LENGTH;
    if (c1)
        *c1 = 0;
    if (c2)
        *c2 = 0;

    /* If the state has already been split, then we cannot split again */
    if (!state->cipher)
        return NOISE_ERROR_INVALID_STATE;

    /* Generate the two encryption keys with HKDF */
    hash_len = noise_hashstate_get_hash_length(state->hash);
    key_len = noise_cipherstate_get_key_length(state->cipher);
    if (!secondary_key) {
        noise_hashstate_hkdf
            (state->hash, state->ck, hash_len, state->ck, 0,
             temp_k1, key_len, temp_k2, key_len);
    } else {
        noise_hashstate_hkdf
            (state->hash, state->ck, hash_len, secondary_key, secondary_key_len,
             temp_k1, key_len, temp_k2, key_len);
    }

    /* If we only need c2, then re-initialize the key in the internal
       cipher and copy it to c2 */
    if (!c1 && c2) {
        noise_cipherstate_init_key(state->cipher, temp_k2, key_len);
        *c2 = state->cipher;
        state->cipher = 0;
        noise_clean(temp_k1, sizeof(temp_k1));
        noise_clean(temp_k2, sizeof(temp_k2));
        return NOISE_ERROR_NONE;
    }

    /* Split a copy out of the cipher and give it the second key.
       We don't need to do this if the second CipherSuite is not required */
    if (c2) {
        *c2 = (*(state->cipher->create))();
        if (!(*c2)) {
            noise_clean(temp_k1, sizeof(temp_k1));
            noise_clean(temp_k2, sizeof(temp_k2));
            return NOISE_ERROR_NO_MEMORY;
        }
        noise_cipherstate_init_key(*c2, temp_k2, key_len);
    }

    /* Re-initialize the key in the internal cipher and copy it to c1 */
    noise_cipherstate_init_key(state->cipher, temp_k1, key_len);
    *c1 = state->cipher;
    state->cipher = 0;
    noise_clean(temp_k1, sizeof(temp_k1));
    noise_clean(temp_k2, sizeof(temp_k2));
    return NOISE_ERROR_NONE;
}