-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
gost3411-2012.c
142 lines (114 loc) · 3.19 KB
/
gost3411-2012.c
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
137
138
139
140
141
142
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_CPUID_H
# include <cpuid.h>
#endif
#include "gost3411-2012.h"
#include "gost3411-2012-ref.h"
#if (__x86_64__ || __i386__)
# include "gost3411-2012-mmx.h"
# include "gost3411-2012-sse2.h"
#endif
#if __x86_64__
# include "gost3411-2012-sse41.h"
#endif
#ifndef __GNUC_PREREQ__
# ifdef __GNUC__
# define __GNUC_PREREQ__(x, y) ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || (__GNUC__ > (x)))
# else
# define __GNUC_PREREQ__(x, y) 0
# endif
#endif
#include "tables.h"
void GOST34112012Init(void* ctx, const unsigned int digest_size)
{
GOST34112012Context* CTX = (GOST34112012Context*)ctx;
memset(CTX, 0, sizeof(GOST34112012Context));
CTX->digest_size = digest_size;
if (256 == digest_size) {
CTX->h.QWORD[0] = 0x0101010101010101ULL;
CTX->h.QWORD[1] = 0x0101010101010101ULL;
CTX->h.QWORD[2] = 0x0101010101010101ULL;
CTX->h.QWORD[3] = 0x0101010101010101ULL;
CTX->h.QWORD[4] = 0x0101010101010101ULL;
CTX->h.QWORD[5] = 0x0101010101010101ULL;
CTX->h.QWORD[6] = 0x0101010101010101ULL;
CTX->h.QWORD[7] = 0x0101010101010101ULL;
}
}
#if defined(HAVE_CPUID_H) && (__x86_64__ || __i386__) && (defined(__GNUC__) && __GNUC_PREREQ__(4, 6) || defined(__clang_major__) && __clang_major__ >= 4)
typedef void (*func_t)(void);
#ifndef bit_MMX
# define bit_MMX (1 << 23)
#endif
#ifndef bit_SSE2
# define bit_SSE2 (1 << 26)
#endif
#ifndef bit_SSE4_1
# define bit_SSE4_1 (1 << 19)
#endif
static void (*resolve_GOST34112012Update(void))(void* restrict, const unsigned char* restrict, size_t)
{
uint32_t eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
#if __x86_64__
if (ecx & bit_SSE4_1) {
return GOST34112012Update_sse41;
}
#endif
if (edx & bit_SSE2) {
return GOST34112012Update_sse2;
}
if (edx & bit_MMX) {
return GOST34112012Update_mmx;
}
}
return GOST34112012Update_ref;
}
static void (*resolve_GOST34112012Final(void))(void* restrict, unsigned char* restrict)
{
uint32_t eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
#if __x86_64__
if (ecx & bit_SSE4_1) {
return GOST34112012Final_sse41;
}
#endif
if (edx & bit_SSE2) {
return GOST34112012Final_sse2;
}
if (edx & bit_MMX) {
return GOST34112012Final_mmx;
}
}
return GOST34112012Final_ref;
}
extern void GOST34112012Update(void* restrict ctx, const unsigned char* restrict data, size_t len) __attribute__((ifunc("resolve_GOST34112012Update")));
extern void GOST34112012Final(void* restrict ctx, unsigned char* restrict digest) __attribute__((ifunc("resolve_GOST34112012Final")));
#else
void GOST34112012Update(void* restrict ctx, const unsigned char* restrict data, size_t len)
{
#if __SSE4_1__
GOST34112012Update_sse41(ctx, data, len);
#elif __SSE2__
GOST34112012Update_sse2(ctx, data, len);
#elif __MMX__
GOST34112012Update_mmx(ctx, data, len);
#else
GOST34112012Update_ref(ctx, data, len);
#endif
}
extern void GOST34112012Final(void* restrict ctx, unsigned char* restrict digest)
{
#if __SSE4_1__
GOST34112012Final_sse41(ctx, digest);
#elif __SSE2__
GOST34112012Final_sse2(ctx, digest);
#elif __MMX__
GOST34112012Final_mmx(ctx, digest);
#else
GOST34112012Final_ref(ctx, digest);
#endif
}
#endif /* defined(__GNUC__) */