aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/include/aesni/data.h
blob: 381a32ac1bf3460c866fec8b857c6d8fcec05ed4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
 * \file
 * \author Egor Tensin <Egor.Tensin@gmail.com>
 * \date 2015
 * \copyright This file is licensed under the terms of the MIT License.
 *            See LICENSE.txt for details.
 *
 * \brief Declares necessary data structures (for blocks, keys, etc.) and
 * auxiliary I/O functions.
 */

#pragma once

#include "error.h"

/**
 * \defgroup aesni_data Data
 * \brief Data structures and I/O functions
 * \ingroup aesni
 * \{
 */

#include <emmintrin.h>
#include <tmmintrin.h>

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * \brief Represents a 128-bit block.
 */
typedef __m128i AesNI_Block128;

/**
 * \brief Loads a 128-bit block from a memory location.
 *
 * \param[in] src The pointer to a memory location. Must not be `NULL`.
 *
 * \return The loaded 128-bit block.
 */
static __inline AesNI_Block128 aesni_load_block128(const void* src)
{
    return _mm_loadu_si128((AesNI_Block128*) src);
}

/**
 * \brief Loads a 128-bit block from a 16-byte aligned memory location.
 *
 * \param[in] src The pointer to a 16-byte aligned memory location. Must not be `NULL`.
 *
 * \return The loaded 128-bit block.
 */
static __inline AesNI_Block128 aesni_load_block128_aligned(const void* src)
{
    return _mm_load_si128((AesNI_Block128*) src);
}

/**
 * \brief Stores a 128-bit block in a memory location.
 *
 * \param[out] dest The pointer to a memory location. Must not be `NULL`.
 *
 * \param[in] block The block to be stored.
 */
static __inline void __fastcall aesni_store_block128(
    void* dest,
    AesNI_Block128 block)
{
    _mm_storeu_si128((AesNI_Block128*) dest, block);
}

/**
 * \brief Stores a 128-bit block in a 16-byte aligned memory location.
 *
 * \param[out] dest The pointer to a 16-byte aligned memory location. Must not be `NULL`.
 *
 * \param[in] block The block to be stored.
 */
static __inline void __fastcall aesni_store_block128_aligned(
    void* dest,
    AesNI_Block128 block)
{
    _mm_store_si128((AesNI_Block128*) dest, block);
}

/**
 * \brief XORs two 128-bit blocks.
 *
 * \param[in] a The first XOR operand.
 * \param[in] b The second XOR operand.
 *
 * \return `a^b`.
 */
static __inline AesNI_Block128 __fastcall aesni_xor_block128(
    AesNI_Block128 a,
    AesNI_Block128 b)
{
    return _mm_xor_si128(a, b);
}

/**
 * \brief Builds a 128-bit block from four 4-byte values.
 *
 * Builds a 128-bit block like this:
 *
 * * dest[127:96] = hi3
 * * dest[95:64] = hi2
 * * dest[63:32] = lo1
 * * dest[31:0] = lo0
 *
 * \param[in] hi3 The most significant 4-byte value.
 * \param[in] hi2 The more significant 4-byte value.
 * \param[in] lo1 The less significant 4-byte value.
 * \param[in] lo0 The least significant 4-byte value.
 * \return The built 128-bit block.
 */
static __inline AesNI_Block128 __fastcall aesni_make_block128(
    int hi3, int hi2, int lo1, int lo0)
{
    return _mm_set_epi32(hi3, hi2, lo1, lo0);
}

static __inline AesNI_Block128 __fastcall aesni_reverse_bytes_block128(AesNI_Block128 block)
{
    return _mm_shuffle_epi8(block, aesni_make_block128(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f));
}

#ifdef __cplusplus
}
#endif

/**
 * \}
 */