Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
labs
BIRD Internet Routing Daemon
Commits
f312a837
Commit
f312a837
authored
Nov 13, 2015
by
Pavel Tvrdík
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add SHA-384/512 and HMAC-SHA-384/512 crypto hash
parent
4035e0e7
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
689 additions
and
0 deletions
+689
-0
lib/Modules
lib/Modules
+2
-0
lib/sha512.c
lib/sha512.c
+614
-0
lib/sha512.h
lib/sha512.h
+73
-0
No files found.
lib/Modules
View file @
f312a837
sha256.c
sha256.h
sha512.c
sha512.h
sha1.c
sha1.h
birdlib.h
...
...
lib/sha512.c
0 → 100644
View file @
f312a837
/*
* BIRD Library -- SHA-512 and SHA-384 Hash Functions,
* HMAC-SHA-512 and HMAC-SHA-384 Functions
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Based on the code from libgcrypt-1.6.0, which is
* (c) 2003, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "lib/sha256.h"
#include "lib/sha512.h"
#include "lib/unaligned.h"
static
uint
sha512_transform
(
void
*
context
,
const
byte
*
data
,
size_t
nblks
);
void
sha512_init
(
struct
sha512_context
*
ctx
)
{
struct
sha512_state
*
hd
=
&
ctx
->
state
;
hd
->
h0
=
UINT64_C
(
0x6a09e667f3bcc908
);
hd
->
h1
=
UINT64_C
(
0xbb67ae8584caa73b
);
hd
->
h2
=
UINT64_C
(
0x3c6ef372fe94f82b
);
hd
->
h3
=
UINT64_C
(
0xa54ff53a5f1d36f1
);
hd
->
h4
=
UINT64_C
(
0x510e527fade682d1
);
hd
->
h5
=
UINT64_C
(
0x9b05688c2b3e6c1f
);
hd
->
h6
=
UINT64_C
(
0x1f83d9abfb41bd6b
);
hd
->
h7
=
UINT64_C
(
0x5be0cd19137e2179
);
ctx
->
bctx
.
nblocks
=
0
;
ctx
->
bctx
.
nblocks_high
=
0
;
ctx
->
bctx
.
count
=
0
;
ctx
->
bctx
.
blocksize
=
128
;
ctx
->
bctx
.
transform
=
sha512_transform
;
}
void
sha384_init
(
struct
sha384_context
*
ctx
)
{
struct
sha512_state
*
hd
=
&
ctx
->
state
;
hd
->
h0
=
UINT64_C
(
0xcbbb9d5dc1059ed8
);
hd
->
h1
=
UINT64_C
(
0x629a292a367cd507
);
hd
->
h2
=
UINT64_C
(
0x9159015a3070dd17
);
hd
->
h3
=
UINT64_C
(
0x152fecd8f70e5939
);
hd
->
h4
=
UINT64_C
(
0x67332667ffc00b31
);
hd
->
h5
=
UINT64_C
(
0x8eb44a8768581511
);
hd
->
h6
=
UINT64_C
(
0xdb0c2e0d64f98fa7
);
hd
->
h7
=
UINT64_C
(
0x47b5481dbefa4fa4
);
ctx
->
bctx
.
nblocks
=
0
;
ctx
->
bctx
.
nblocks_high
=
0
;
ctx
->
bctx
.
count
=
0
;
ctx
->
bctx
.
blocksize
=
128
;
ctx
->
bctx
.
transform
=
sha512_transform
;
}
void
sha512_update
(
struct
sha512_context
*
ctx
,
const
byte
*
in_buf
,
size_t
in_len
)
{
sha256_update
(
&
ctx
->
bctx
,
in_buf
,
in_len
);
}
static
inline
u64
ROTR
(
u64
x
,
u64
n
)
{
return
((
x
>>
n
)
|
(
x
<<
(
64
-
n
)));
}
static
inline
u64
Ch
(
u64
x
,
u64
y
,
u64
z
)
{
return
((
x
&
y
)
^
(
~
x
&
z
));
}
static
inline
u64
Maj
(
u64
x
,
u64
y
,
u64
z
)
{
return
((
x
&
y
)
^
(
x
&
z
)
^
(
y
&
z
));
}
static
inline
u64
Sum0
(
u64
x
)
{
return
(
ROTR
(
x
,
28
)
^
ROTR
(
x
,
34
)
^
ROTR
(
x
,
39
));
}
static
inline
u64
Sum1
(
u64
x
)
{
return
(
ROTR
(
x
,
14
)
^
ROTR
(
x
,
18
)
^
ROTR
(
x
,
41
));
}
static
const
u64
k
[]
=
{
UINT64_C
(
0x428a2f98d728ae22
),
UINT64_C
(
0x7137449123ef65cd
),
UINT64_C
(
0xb5c0fbcfec4d3b2f
),
UINT64_C
(
0xe9b5dba58189dbbc
),
UINT64_C
(
0x3956c25bf348b538
),
UINT64_C
(
0x59f111f1b605d019
),
UINT64_C
(
0x923f82a4af194f9b
),
UINT64_C
(
0xab1c5ed5da6d8118
),
UINT64_C
(
0xd807aa98a3030242
),
UINT64_C
(
0x12835b0145706fbe
),
UINT64_C
(
0x243185be4ee4b28c
),
UINT64_C
(
0x550c7dc3d5ffb4e2
),
UINT64_C
(
0x72be5d74f27b896f
),
UINT64_C
(
0x80deb1fe3b1696b1
),
UINT64_C
(
0x9bdc06a725c71235
),
UINT64_C
(
0xc19bf174cf692694
),
UINT64_C
(
0xe49b69c19ef14ad2
),
UINT64_C
(
0xefbe4786384f25e3
),
UINT64_C
(
0x0fc19dc68b8cd5b5
),
UINT64_C
(
0x240ca1cc77ac9c65
),
UINT64_C
(
0x2de92c6f592b0275
),
UINT64_C
(
0x4a7484aa6ea6e483
),
UINT64_C
(
0x5cb0a9dcbd41fbd4
),
UINT64_C
(
0x76f988da831153b5
),
UINT64_C
(
0x983e5152ee66dfab
),
UINT64_C
(
0xa831c66d2db43210
),
UINT64_C
(
0xb00327c898fb213f
),
UINT64_C
(
0xbf597fc7beef0ee4
),
UINT64_C
(
0xc6e00bf33da88fc2
),
UINT64_C
(
0xd5a79147930aa725
),
UINT64_C
(
0x06ca6351e003826f
),
UINT64_C
(
0x142929670a0e6e70
),
UINT64_C
(
0x27b70a8546d22ffc
),
UINT64_C
(
0x2e1b21385c26c926
),
UINT64_C
(
0x4d2c6dfc5ac42aed
),
UINT64_C
(
0x53380d139d95b3df
),
UINT64_C
(
0x650a73548baf63de
),
UINT64_C
(
0x766a0abb3c77b2a8
),
UINT64_C
(
0x81c2c92e47edaee6
),
UINT64_C
(
0x92722c851482353b
),
UINT64_C
(
0xa2bfe8a14cf10364
),
UINT64_C
(
0xa81a664bbc423001
),
UINT64_C
(
0xc24b8b70d0f89791
),
UINT64_C
(
0xc76c51a30654be30
),
UINT64_C
(
0xd192e819d6ef5218
),
UINT64_C
(
0xd69906245565a910
),
UINT64_C
(
0xf40e35855771202a
),
UINT64_C
(
0x106aa07032bbd1b8
),
UINT64_C
(
0x19a4c116b8d2d0c8
),
UINT64_C
(
0x1e376c085141ab53
),
UINT64_C
(
0x2748774cdf8eeb99
),
UINT64_C
(
0x34b0bcb5e19b48a8
),
UINT64_C
(
0x391c0cb3c5c95a63
),
UINT64_C
(
0x4ed8aa4ae3418acb
),
UINT64_C
(
0x5b9cca4f7763e373
),
UINT64_C
(
0x682e6ff3d6b2b8a3
),
UINT64_C
(
0x748f82ee5defb2fc
),
UINT64_C
(
0x78a5636f43172f60
),
UINT64_C
(
0x84c87814a1f0ab72
),
UINT64_C
(
0x8cc702081a6439ec
),
UINT64_C
(
0x90befffa23631e28
),
UINT64_C
(
0xa4506cebde82bde9
),
UINT64_C
(
0xbef9a3f7b2c67915
),
UINT64_C
(
0xc67178f2e372532b
),
UINT64_C
(
0xca273eceea26619c
),
UINT64_C
(
0xd186b8c721c0c207
),
UINT64_C
(
0xeada7dd6cde0eb1e
),
UINT64_C
(
0xf57d4f7fee6ed178
),
UINT64_C
(
0x06f067aa72176fba
),
UINT64_C
(
0x0a637dc5a2c898a6
),
UINT64_C
(
0x113f9804bef90dae
),
UINT64_C
(
0x1b710b35131c471b
),
UINT64_C
(
0x28db77f523047d84
),
UINT64_C
(
0x32caab7b40c72493
),
UINT64_C
(
0x3c9ebe0a15c9bebc
),
UINT64_C
(
0x431d67c49c100d4c
),
UINT64_C
(
0x4cc5d4becb3e42b6
),
UINT64_C
(
0x597f299cfc657e2a
),
UINT64_C
(
0x5fcb6fab3ad6faec
),
UINT64_C
(
0x6c44198c4a475817
)
};
/*
* Transform the message W which consists of 16 64-bit-words
*/
static
uint
sha512_transform_block
(
struct
sha512_state
*
hd
,
const
byte
*
data
)
{
u64
a
,
b
,
c
,
d
,
e
,
f
,
g
,
h
;
u64
w
[
16
];
int
t
;
/* get values from the chaining vars */
a
=
hd
->
h0
;
b
=
hd
->
h1
;
c
=
hd
->
h2
;
d
=
hd
->
h3
;
e
=
hd
->
h4
;
f
=
hd
->
h5
;
g
=
hd
->
h6
;
h
=
hd
->
h7
;
for
(
t
=
0
;
t
<
16
;
t
++
)
w
[
t
]
=
get_u64
(
data
+
t
*
8
);
#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
for
(
t
=
0
;
t
<
80
-
16
;
)
{
u64
t1
,
t2
;
/* Performance on a AMD Athlon(tm) Dual Core Processor 4050e
with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes
initialized to 0,1,2,3...255,0,... and 1000 iterations:
Not unrolled with macros: 440ms
Unrolled with macros: 350ms
Unrolled with inline: 330ms
*/
#if 0 /* Not unrolled. */
t1 = h + Sum1 (e) + Ch(e, f, g) + k[t] + w[t%16];
w[t%16] += S1 (w[(t - 2)%16]) + w[(t - 7)%16] + S0 (w[(t - 15)%16]);
t2 = Sum0 (a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
t++;
#else
/* Unrolled to interweave the chain variables. */
t1
=
h
+
Sum1
(
e
)
+
Ch
(
e
,
f
,
g
)
+
k
[
t
]
+
w
[
0
];
w
[
0
]
+=
S1
(
w
[
14
])
+
w
[
9
]
+
S0
(
w
[
1
]);
t2
=
Sum0
(
a
)
+
Maj
(
a
,
b
,
c
);
d
+=
t1
;
h
=
t1
+
t2
;
t1
=
g
+
Sum1
(
d
)
+
Ch
(
d
,
e
,
f
)
+
k
[
t
+
1
]
+
w
[
1
];
w
[
1
]
+=
S1
(
w
[
15
])
+
w
[
10
]
+
S0
(
w
[
2
]);
t2
=
Sum0
(
h
)
+
Maj
(
h
,
a
,
b
);
c
+=
t1
;
g
=
t1
+
t2
;
t1
=
f
+
Sum1
(
c
)
+
Ch
(
c
,
d
,
e
)
+
k
[
t
+
2
]
+
w
[
2
];
w
[
2
]
+=
S1
(
w
[
0
])
+
w
[
11
]
+
S0
(
w
[
3
]);
t2
=
Sum0
(
g
)
+
Maj
(
g
,
h
,
a
);
b
+=
t1
;
f
=
t1
+
t2
;
t1
=
e
+
Sum1
(
b
)
+
Ch
(
b
,
c
,
d
)
+
k
[
t
+
3
]
+
w
[
3
];
w
[
3
]
+=
S1
(
w
[
1
])
+
w
[
12
]
+
S0
(
w
[
4
]);
t2
=
Sum0
(
f
)
+
Maj
(
f
,
g
,
h
);
a
+=
t1
;
e
=
t1
+
t2
;
t1
=
d
+
Sum1
(
a
)
+
Ch
(
a
,
b
,
c
)
+
k
[
t
+
4
]
+
w
[
4
];
w
[
4
]
+=
S1
(
w
[
2
])
+
w
[
13
]
+
S0
(
w
[
5
]);
t2
=
Sum0
(
e
)
+
Maj
(
e
,
f
,
g
);
h
+=
t1
;
d
=
t1
+
t2
;
t1
=
c
+
Sum1
(
h
)
+
Ch
(
h
,
a
,
b
)
+
k
[
t
+
5
]
+
w
[
5
];
w
[
5
]
+=
S1
(
w
[
3
])
+
w
[
14
]
+
S0
(
w
[
6
]);
t2
=
Sum0
(
d
)
+
Maj
(
d
,
e
,
f
);
g
+=
t1
;
c
=
t1
+
t2
;
t1
=
b
+
Sum1
(
g
)
+
Ch
(
g
,
h
,
a
)
+
k
[
t
+
6
]
+
w
[
6
];
w
[
6
]
+=
S1
(
w
[
4
])
+
w
[
15
]
+
S0
(
w
[
7
]);
t2
=
Sum0
(
c
)
+
Maj
(
c
,
d
,
e
);
f
+=
t1
;
b
=
t1
+
t2
;
t1
=
a
+
Sum1
(
f
)
+
Ch
(
f
,
g
,
h
)
+
k
[
t
+
7
]
+
w
[
7
];
w
[
7
]
+=
S1
(
w
[
5
])
+
w
[
0
]
+
S0
(
w
[
8
]);
t2
=
Sum0
(
b
)
+
Maj
(
b
,
c
,
d
);
e
+=
t1
;
a
=
t1
+
t2
;
t1
=
h
+
Sum1
(
e
)
+
Ch
(
e
,
f
,
g
)
+
k
[
t
+
8
]
+
w
[
8
];
w
[
8
]
+=
S1
(
w
[
6
])
+
w
[
1
]
+
S0
(
w
[
9
]);
t2
=
Sum0
(
a
)
+
Maj
(
a
,
b
,
c
);
d
+=
t1
;
h
=
t1
+
t2
;
t1
=
g
+
Sum1
(
d
)
+
Ch
(
d
,
e
,
f
)
+
k
[
t
+
9
]
+
w
[
9
];
w
[
9
]
+=
S1
(
w
[
7
])
+
w
[
2
]
+
S0
(
w
[
10
]);
t2
=
Sum0
(
h
)
+
Maj
(
h
,
a
,
b
);
c
+=
t1
;
g
=
t1
+
t2
;
t1
=
f
+
Sum1
(
c
)
+
Ch
(
c
,
d
,
e
)
+
k
[
t
+
10
]
+
w
[
10
];
w
[
10
]
+=
S1
(
w
[
8
])
+
w
[
3
]
+
S0
(
w
[
11
]);
t2
=
Sum0
(
g
)
+
Maj
(
g
,
h
,
a
);
b
+=
t1
;
f
=
t1
+
t2
;
t1
=
e
+
Sum1
(
b
)
+
Ch
(
b
,
c
,
d
)
+
k
[
t
+
11
]
+
w
[
11
];
w
[
11
]
+=
S1
(
w
[
9
])
+
w
[
4
]
+
S0
(
w
[
12
]);
t2
=
Sum0
(
f
)
+
Maj
(
f
,
g
,
h
);
a
+=
t1
;
e
=
t1
+
t2
;
t1
=
d
+
Sum1
(
a
)
+
Ch
(
a
,
b
,
c
)
+
k
[
t
+
12
]
+
w
[
12
];
w
[
12
]
+=
S1
(
w
[
10
])
+
w
[
5
]
+
S0
(
w
[
13
]);
t2
=
Sum0
(
e
)
+
Maj
(
e
,
f
,
g
);
h
+=
t1
;
d
=
t1
+
t2
;
t1
=
c
+
Sum1
(
h
)
+
Ch
(
h
,
a
,
b
)
+
k
[
t
+
13
]
+
w
[
13
];
w
[
13
]
+=
S1
(
w
[
11
])
+
w
[
6
]
+
S0
(
w
[
14
]);
t2
=
Sum0
(
d
)
+
Maj
(
d
,
e
,
f
);
g
+=
t1
;
c
=
t1
+
t2
;
t1
=
b
+
Sum1
(
g
)
+
Ch
(
g
,
h
,
a
)
+
k
[
t
+
14
]
+
w
[
14
];
w
[
14
]
+=
S1
(
w
[
12
])
+
w
[
7
]
+
S0
(
w
[
15
]);
t2
=
Sum0
(
c
)
+
Maj
(
c
,
d
,
e
);
f
+=
t1
;
b
=
t1
+
t2
;
t1
=
a
+
Sum1
(
f
)
+
Ch
(
f
,
g
,
h
)
+
k
[
t
+
15
]
+
w
[
15
];
w
[
15
]
+=
S1
(
w
[
13
])
+
w
[
8
]
+
S0
(
w
[
0
]);
t2
=
Sum0
(
b
)
+
Maj
(
b
,
c
,
d
);
e
+=
t1
;
a
=
t1
+
t2
;
t
+=
16
;
#endif
}
for
(;
t
<
80
;
)
{
u64
t1
,
t2
;
#if 0 /* Not unrolled. */
t1 = h + Sum1 (e) + Ch(e, f, g) + k[t] + w[t%16];
t2 = Sum0 (a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
t++;
#else
/* Unrolled to interweave the chain variables. */
t1
=
h
+
Sum1
(
e
)
+
Ch
(
e
,
f
,
g
)
+
k
[
t
]
+
w
[
0
];
t2
=
Sum0
(
a
)
+
Maj
(
a
,
b
,
c
);
d
+=
t1
;
h
=
t1
+
t2
;
t1
=
g
+
Sum1
(
d
)
+
Ch
(
d
,
e
,
f
)
+
k
[
t
+
1
]
+
w
[
1
];
t2
=
Sum0
(
h
)
+
Maj
(
h
,
a
,
b
);
c
+=
t1
;
g
=
t1
+
t2
;
t1
=
f
+
Sum1
(
c
)
+
Ch
(
c
,
d
,
e
)
+
k
[
t
+
2
]
+
w
[
2
];
t2
=
Sum0
(
g
)
+
Maj
(
g
,
h
,
a
);
b
+=
t1
;
f
=
t1
+
t2
;
t1
=
e
+
Sum1
(
b
)
+
Ch
(
b
,
c
,
d
)
+
k
[
t
+
3
]
+
w
[
3
];
t2
=
Sum0
(
f
)
+
Maj
(
f
,
g
,
h
);
a
+=
t1
;
e
=
t1
+
t2
;
t1
=
d
+
Sum1
(
a
)
+
Ch
(
a
,
b
,
c
)
+
k
[
t
+
4
]
+
w
[
4
];
t2
=
Sum0
(
e
)
+
Maj
(
e
,
f
,
g
);
h
+=
t1
;
d
=
t1
+
t2
;
t1
=
c
+
Sum1
(
h
)
+
Ch
(
h
,
a
,
b
)
+
k
[
t
+
5
]
+
w
[
5
];
t2
=
Sum0
(
d
)
+
Maj
(
d
,
e
,
f
);
g
+=
t1
;
c
=
t1
+
t2
;
t1
=
b
+
Sum1
(
g
)
+
Ch
(
g
,
h
,
a
)
+
k
[
t
+
6
]
+
w
[
6
];
t2
=
Sum0
(
c
)
+
Maj
(
c
,
d
,
e
);
f
+=
t1
;
b
=
t1
+
t2
;
t1
=
a
+
Sum1
(
f
)
+
Ch
(
f
,
g
,
h
)
+
k
[
t
+
7
]
+
w
[
7
];
t2
=
Sum0
(
b
)
+
Maj
(
b
,
c
,
d
);
e
+=
t1
;
a
=
t1
+
t2
;
t1
=
h
+
Sum1
(
e
)
+
Ch
(
e
,
f
,
g
)
+
k
[
t
+
8
]
+
w
[
8
];
t2
=
Sum0
(
a
)
+
Maj
(
a
,
b
,
c
);
d
+=
t1
;
h
=
t1
+
t2
;
t1
=
g
+
Sum1
(
d
)
+
Ch
(
d
,
e
,
f
)
+
k
[
t
+
9
]
+
w
[
9
];
t2
=
Sum0
(
h
)
+
Maj
(
h
,
a
,
b
);
c
+=
t1
;
g
=
t1
+
t2
;
t1
=
f
+
Sum1
(
c
)
+
Ch
(
c
,
d
,
e
)
+
k
[
t
+
10
]
+
w
[
10
];
t2
=
Sum0
(
g
)
+
Maj
(
g
,
h
,
a
);
b
+=
t1
;
f
=
t1
+
t2
;
t1
=
e
+
Sum1
(
b
)
+
Ch
(
b
,
c
,
d
)
+
k
[
t
+
11
]
+
w
[
11
];
t2
=
Sum0
(
f
)
+
Maj
(
f
,
g
,
h
);
a
+=
t1
;
e
=
t1
+
t2
;
t1
=
d
+
Sum1
(
a
)
+
Ch
(
a
,
b
,
c
)
+
k
[
t
+
12
]
+
w
[
12
];
t2
=
Sum0
(
e
)
+
Maj
(
e
,
f
,
g
);
h
+=
t1
;
d
=
t1
+
t2
;
t1
=
c
+
Sum1
(
h
)
+
Ch
(
h
,
a
,
b
)
+
k
[
t
+
13
]
+
w
[
13
];
t2
=
Sum0
(
d
)
+
Maj
(
d
,
e
,
f
);
g
+=
t1
;
c
=
t1
+
t2
;
t1
=
b
+
Sum1
(
g
)
+
Ch
(
g
,
h
,
a
)
+
k
[
t
+
14
]
+
w
[
14
];
t2
=
Sum0
(
c
)
+
Maj
(
c
,
d
,
e
);
f
+=
t1
;
b
=
t1
+
t2
;
t1
=
a
+
Sum1
(
f
)
+
Ch
(
f
,
g
,
h
)
+
k
[
t
+
15
]
+
w
[
15
];
t2
=
Sum0
(
b
)
+
Maj
(
b
,
c
,
d
);
e
+=
t1
;
a
=
t1
+
t2
;
t
+=
16
;
#endif
}
/* Update chaining vars. */
hd
->
h0
+=
a
;
hd
->
h1
+=
b
;
hd
->
h2
+=
c
;
hd
->
h3
+=
d
;
hd
->
h4
+=
e
;
hd
->
h5
+=
f
;
hd
->
h6
+=
g
;
hd
->
h7
+=
h
;
return
/* burn_stack */
(
8
+
16
)
*
sizeof
(
u64
)
+
sizeof
(
u32
)
+
3
*
sizeof
(
void
*
);
}
static
uint
sha512_transform
(
void
*
context
,
const
byte
*
data
,
size_t
nblks
)
{
struct
sha512_context
*
ctx
=
context
;
uint
burn
;
do
{
burn
=
sha512_transform_block
(
&
ctx
->
state
,
data
)
+
3
*
sizeof
(
void
*
);
data
+=
128
;
}
while
(
--
nblks
);
return
burn
;
}
/* The routine final terminates the computation and
* returns the digest.
* The handle is prepared for a new cycle, but adding bytes to the
* handle will the destroy the returned buffer.
* Returns: 64 bytes representing the digest. When used for sha384,
* we take the leftmost 48 of those bytes.
*/
byte
*
sha512_final
(
struct
sha512_context
*
ctx
)
{
u64
t
,
th
,
msb
,
lsb
;
byte
*
p
;
sha256_update
(
&
ctx
->
bctx
,
NULL
,
0
);
/* flush */
;
t
=
ctx
->
bctx
.
nblocks
;
/* if (sizeof t == sizeof ctx->bctx.nblocks) */
th
=
ctx
->
bctx
.
nblocks_high
;
/* else */
/* th = ctx->bctx.nblocks >> 64; In case we ever use u128 */
/* multiply by 128 to make a byte count */
lsb
=
t
<<
7
;
msb
=
(
th
<<
7
)
|
(
t
>>
57
);
/* add the count */
t
=
lsb
;
if
((
lsb
+=
ctx
->
bctx
.
count
)
<
t
)
msb
++
;
/* multiply by 8 to make a bit count */
t
=
lsb
;
lsb
<<=
3
;
msb
<<=
3
;
msb
|=
t
>>
61
;
if
(
ctx
->
bctx
.
count
<
112
)
{
/* enough room */
ctx
->
bctx
.
buf
[
ctx
->
bctx
.
count
++
]
=
0x80
;
/* pad */
while
(
ctx
->
bctx
.
count
<
112
)
ctx
->
bctx
.
buf
[
ctx
->
bctx
.
count
++
]
=
0
;
/* pad */
}
else
{
/* need one extra block */
ctx
->
bctx
.
buf
[
ctx
->
bctx
.
count
++
]
=
0x80
;
/* pad character */
while
(
ctx
->
bctx
.
count
<
128
)
ctx
->
bctx
.
buf
[
ctx
->
bctx
.
count
++
]
=
0
;
sha256_update
(
&
ctx
->
bctx
,
NULL
,
0
);
/* flush */
;
memset
(
ctx
->
bctx
.
buf
,
0
,
112
);
/* fill next block with zeroes */
}
/* append the 128 bit count */
put_u64
(
ctx
->
bctx
.
buf
+
112
,
msb
);
put_u64
(
ctx
->
bctx
.
buf
+
120
,
lsb
);
sha512_transform
(
ctx
,
ctx
->
bctx
.
buf
,
1
);
p
=
ctx
->
bctx
.
buf
;
#define X(a) do { put_u64(p, ctx->state.h##a); p += 8; } while(0)
X
(
0
);
X
(
1
);
X
(
2
);
X
(
3
);
X
(
4
);
X
(
5
);
/* Note that these last two chunks are included even for SHA384.
We just ignore them. */
X
(
6
);
X
(
7
);
#undef X
return
ctx
->
bctx
.
buf
;
}
/*
* SHA512-HMAC
*/
static
void
sha512_hash_buffer
(
byte
*
outbuf
,
const
byte
*
buffer
,
size_t
length
)
{
struct
sha512_context
hd_tmp
;
sha512_init
(
&
hd_tmp
);
sha512_update
(
&
hd_tmp
,
buffer
,
length
);
memcpy
(
outbuf
,
sha512_final
(
&
hd_tmp
),
SHA512_SIZE
);
}
void
sha512_hmac_init
(
struct
sha512_hmac_context
*
ctx
,
const
byte
*
key
,
size_t
keylen
)
{
byte
keybuf
[
SHA512_BLOCK_SIZE
],
buf
[
SHA512_BLOCK_SIZE
];
/* Hash the key if necessary */
if
(
keylen
<=
SHA512_BLOCK_SIZE
)
{
memcpy
(
keybuf
,
key
,
keylen
);
bzero
(
keybuf
+
keylen
,
SHA512_BLOCK_SIZE
-
keylen
);
}
else
{
sha512_hash_buffer
(
keybuf
,
key
,
keylen
);
bzero
(
keybuf
+
SHA512_SIZE
,
SHA512_BLOCK_SIZE
-
SHA512_SIZE
);
}
/* Initialize the inner digest */
sha512_init
(
&
ctx
->
ictx
);
int
i
;
for
(
i
=
0
;
i
<
SHA512_BLOCK_SIZE
;
i
++
)
buf
[
i
]
=
keybuf
[
i
]
^
0x36
;
sha512_update
(
&
ctx
->
ictx
,
buf
,
SHA512_BLOCK_SIZE
);
/* Initialize the outer digest */
sha512_init
(
&
ctx
->
octx
);
for
(
i
=
0
;
i
<
SHA512_BLOCK_SIZE
;
i
++
)
buf
[
i
]
=
keybuf
[
i
]
^
0x5c
;
sha512_update
(
&
ctx
->
octx
,
buf
,
SHA512_BLOCK_SIZE
);
}
void
sha512_hmac_update
(
struct
sha512_hmac_context
*
ctx
,
const
byte
*
buf
,
size_t
buflen
)
{
/* Just update the inner digest */
sha512_update
(
&
ctx
->
ictx
,
buf
,
buflen
);
}
byte
*
sha512_hmac_final
(
struct
sha512_hmac_context
*
ctx
)
{
/* Finish the inner digest */
byte
*
isha
=
sha512_final
(
&
ctx
->
ictx
);
/* Finish the outer digest */
sha512_update
(
&
ctx
->
octx
,
isha
,
SHA512_SIZE
);
return
sha512_final
(
&
ctx
->
octx
);
}
/*
* SHA384-HMAC
*/
static
void
sha384_hash_buffer
(
byte
*
outbuf
,
const
byte
*
buffer
,
size_t
length
)
{
struct
sha384_context
hd_tmp
;
sha384_init
(
&
hd_tmp
);
sha384_update
(
&
hd_tmp
,
buffer
,
length
);
memcpy
(
outbuf
,
sha384_final
(
&
hd_tmp
),
SHA384_SIZE
);
}
void
sha384_hmac_init
(
struct
sha384_hmac_context
*
ctx
,
const
byte
*
key
,
size_t
keylen
)
{
byte
keybuf
[
SHA384_BLOCK_SIZE
],
buf
[
SHA384_BLOCK_SIZE
];
/* Hash the key if necessary */
if
(
keylen
<=
SHA384_BLOCK_SIZE
)
{
memcpy
(
keybuf
,
key
,
keylen
);
bzero
(
keybuf
+
keylen
,
SHA384_BLOCK_SIZE
-
keylen
);
}
else
{
sha384_hash_buffer
(
keybuf
,
key
,
keylen
);
bzero
(
keybuf
+
SHA384_SIZE
,
SHA384_BLOCK_SIZE
-
SHA384_SIZE
);
}
/* Initialize the inner digest */
sha384_init
(
&
ctx
->
ictx
);
int
i
;
for
(
i
=
0
;
i
<
SHA384_BLOCK_SIZE
;
i
++
)
buf
[
i
]
=
keybuf
[
i
]
^
0x36
;
sha384_update
(
&
ctx
->
ictx
,
buf
,
SHA384_BLOCK_SIZE
);
/* Initialize the outer digest */
sha384_init
(
&
ctx
->
octx
);
for
(
i
=
0
;
i
<
SHA384_BLOCK_SIZE
;
i
++
)
buf
[
i
]
=
keybuf
[
i
]
^
0x5c
;
sha384_update
(
&
ctx
->
octx
,
buf
,
SHA384_BLOCK_SIZE
);
}
void
sha384_hmac_update
(
struct
sha384_hmac_context
*
ctx
,
const
byte
*
buf
,
size_t
buflen
)
{
/* Just update the inner digest */