![github@pureftpd.org](/assets/img/avatar_default.png)
22 changed files with 521 additions and 546 deletions
@ -0,0 +1,140 @@ |
|||
|
|||
/*-
|
|||
* Copyright 2005,2007,2009 Colin Percival |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
|||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
|||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|||
* SUCH DAMAGE. |
|||
* |
|||
*/ |
|||
|
|||
#include "api.h" |
|||
#include "crypto_auth_hmacsha512256.h" |
|||
#include "crypto_hash_sha512.h" |
|||
#include "utils.h" |
|||
|
|||
#include <sys/types.h> |
|||
|
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
|
|||
int |
|||
crypto_auth_hmacsha512_init(crypto_auth_hmacsha512_state *state, |
|||
const unsigned char *key, |
|||
size_t keylen) |
|||
{ |
|||
unsigned char pad[128]; |
|||
unsigned char khash[64]; |
|||
size_t i; |
|||
|
|||
if (keylen > 128) { |
|||
crypto_hash_sha512_init(&state->ictx); |
|||
crypto_hash_sha512_update(&state->ictx, key, keylen); |
|||
crypto_hash_sha512_final(&state->ictx, khash); |
|||
key = khash; |
|||
keylen = 64; |
|||
} |
|||
crypto_hash_sha512_init(&state->ictx); |
|||
memset(pad, 0x36, 128); |
|||
for (i = 0; i < keylen; i++) { |
|||
pad[i] ^= key[i]; |
|||
} |
|||
crypto_hash_sha512_update(&state->ictx, pad, 128); |
|||
|
|||
crypto_hash_sha512_init(&state->octx); |
|||
memset(pad, 0x5c, 128); |
|||
for (i = 0; i < keylen; i++) { |
|||
pad[i] ^= key[i]; |
|||
} |
|||
crypto_hash_sha512_update(&state->octx, pad, 128); |
|||
|
|||
sodium_memzero((void *) khash, 64); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_auth_hmacsha512_update(crypto_auth_hmacsha512_state *state, |
|||
const unsigned char *in, |
|||
unsigned long long inlen) |
|||
{ |
|||
crypto_hash_sha512_update(&state->ictx, in, inlen); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_auth_hmacsha512_final(crypto_auth_hmacsha512_state *state, |
|||
unsigned char *out) |
|||
{ |
|||
unsigned char ihash[64]; |
|||
|
|||
crypto_hash_sha512_final(&state->ictx, ihash); |
|||
crypto_hash_sha512_update(&state->octx, ihash, 64); |
|||
crypto_hash_sha512_final(&state->octx, out); |
|||
|
|||
sodium_memzero((void *) ihash, 64); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_auth_hmacsha512256_init(crypto_auth_hmacsha512256_state *state, |
|||
const unsigned char *key, |
|||
size_t keylen) |
|||
{ |
|||
return crypto_auth_hmacsha512_init((crypto_auth_hmacsha512_state *) state, |
|||
key, keylen); |
|||
} |
|||
|
|||
int |
|||
crypto_auth_hmacsha512256_update(crypto_auth_hmacsha512256_state *state, |
|||
const unsigned char *in, |
|||
unsigned long long inlen) |
|||
{ |
|||
return crypto_auth_hmacsha512_update((crypto_auth_hmacsha512_state *) state, |
|||
in, inlen); |
|||
} |
|||
|
|||
int |
|||
crypto_auth_hmacsha512256_final(crypto_auth_hmacsha512256_state *state, |
|||
unsigned char *out) |
|||
{ |
|||
unsigned char out0[64]; |
|||
|
|||
crypto_auth_hmacsha512_final((crypto_auth_hmacsha512_state *) state, out0); |
|||
memcpy(out, out0, 32); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_auth(unsigned char *out, const unsigned char *in, |
|||
unsigned long long inlen, const unsigned char *k) |
|||
{ |
|||
crypto_auth_hmacsha512256_state state; |
|||
|
|||
crypto_auth_hmacsha512256_init(&state, k, crypto_auth_KEYBYTES); |
|||
crypto_auth_hmacsha512256_update(&state, in, inlen); |
|||
crypto_auth_hmacsha512256_final(&state, out); |
|||
|
|||
return 0; |
|||
} |
@ -1,86 +0,0 @@ |
|||
/*
|
|||
* 20080913 |
|||
* D. J. Bernstein |
|||
* Public domain. |
|||
* */ |
|||
|
|||
#include "api.h" |
|||
#include "_crypto_hashblocks_sha512.h" |
|||
|
|||
#define blocks crypto_hashblocks_sha512 |
|||
|
|||
typedef unsigned long long uint64; |
|||
|
|||
static const unsigned char iv[64] = { |
|||
0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, |
|||
0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, |
|||
0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, |
|||
0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, |
|||
0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, |
|||
0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, |
|||
0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, |
|||
0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 |
|||
} ; |
|||
|
|||
int crypto_auth(unsigned char *out,const unsigned char *in,unsigned long long inlen,const unsigned char *k) |
|||
{ |
|||
unsigned char h[64]; |
|||
unsigned char padded[256]; |
|||
unsigned long long i; |
|||
unsigned long long bytes = 128 + inlen; |
|||
|
|||
for (i = 0;i < 64;++i) h[i] = iv[i]; |
|||
|
|||
for (i = 0;i < 32;++i) padded[i] = k[i] ^ 0x36; |
|||
for (i = 32;i < 128;++i) padded[i] = 0x36; |
|||
|
|||
blocks(h,padded,128); |
|||
blocks(h,in,inlen); |
|||
in += inlen; |
|||
inlen &= 127; |
|||
in -= inlen; |
|||
|
|||
for (i = 0;i < inlen;++i) padded[i] = in[i]; |
|||
padded[inlen] = 0x80; |
|||
|
|||
if (inlen < 112) { |
|||
for (i = inlen + 1;i < 119;++i) padded[i] = 0; |
|||
padded[119] = bytes >> 61; |
|||
padded[120] = bytes >> 53; |
|||
padded[121] = bytes >> 45; |
|||
padded[122] = bytes >> 37; |
|||
padded[123] = bytes >> 29; |
|||
padded[124] = bytes >> 21; |
|||
padded[125] = bytes >> 13; |
|||
padded[126] = bytes >> 5; |
|||
padded[127] = bytes << 3; |
|||
blocks(h,padded,128); |
|||
} else { |
|||
for (i = inlen + 1;i < 247;++i) padded[i] = 0; |
|||
padded[247] = bytes >> 61; |
|||
padded[248] = bytes >> 53; |
|||
padded[249] = bytes >> 45; |
|||
padded[250] = bytes >> 37; |
|||
padded[251] = bytes >> 29; |
|||
padded[252] = bytes >> 21; |
|||
padded[253] = bytes >> 13; |
|||
padded[254] = bytes >> 5; |
|||
padded[255] = bytes << 3; |
|||
blocks(h,padded,256); |
|||
} |
|||
|
|||
for (i = 0;i < 32;++i) padded[i] = k[i] ^ 0x5c; |
|||
for (i = 32;i < 128;++i) padded[i] = 0x5c; |
|||
|
|||
for (i = 0;i < 64;++i) padded[128 + i] = h[i]; |
|||
for (i = 0;i < 64;++i) h[i] = iv[i]; |
|||
|
|||
for (i = 64;i < 128;++i) padded[128 + i] = 0; |
|||
padded[128 + 64] = 0x80; |
|||
padded[128 + 126] = 6; |
|||
|
|||
blocks(h,padded,256); |
|||
for (i = 0;i < 32;++i) out[i] = h[i]; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,322 @@ |
|||
|
|||
/*-
|
|||
* Copyright 2005,2007,2009 Colin Percival |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
|||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
|||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|||
* SUCH DAMAGE. |
|||
* |
|||
*/ |
|||
|
|||
#include "api.h" |
|||
#include "crypto_hash_sha512.h" |
|||
#include "utils.h" |
|||
|
|||
#include <sys/types.h> |
|||
|
|||
#include <limits.h> |
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
/* Avoid namespace collisions with BSD <sys/endian.h>. */ |
|||
#define be64dec _sha512_be64dec |
|||
#define be64enc _sha512_be64enc |
|||
|
|||
static inline uint64_t |
|||
be64dec(const void *pp) |
|||
{ |
|||
const uint8_t *p = (uint8_t const *)pp; |
|||
|
|||
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + |
|||
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + |
|||
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + |
|||
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); |
|||
} |
|||
|
|||
static inline void |
|||
be64enc(void *pp, uint64_t x) |
|||
{ |
|||
uint8_t *p = (uint8_t *)pp; |
|||
|
|||
p[7] = x & 0xff; |
|||
p[6] = (x >> 8) & 0xff; |
|||
p[5] = (x >> 16) & 0xff; |
|||
p[4] = (x >> 24) & 0xff; |
|||
p[3] = (x >> 32) & 0xff; |
|||
p[2] = (x >> 40) & 0xff; |
|||
p[1] = (x >> 48) & 0xff; |
|||
p[0] = (x >> 56) & 0xff; |
|||
} |
|||
|
|||
static void |
|||
be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len) |
|||
{ |
|||
size_t i; |
|||
|
|||
for (i = 0; i < len / 8; i++) { |
|||
be64enc(dst + i * 8, src[i]); |
|||
} |
|||
} |
|||
|
|||
static void |
|||
be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len) |
|||
{ |
|||
size_t i; |
|||
|
|||
for (i = 0; i < len / 8; i++) { |
|||
dst[i] = be64dec(src + i * 8); |
|||
} |
|||
} |
|||
|
|||
#define Ch(x, y, z) ((x & (y ^ z)) ^ z) |
|||
#define Maj(x, y, z) ((x & (y | z)) | (y & z)) |
|||
#define SHR(x, n) (x >> n) |
|||
#define ROTR(x, n) ((x >> n) | (x << (64 - n))) |
|||
#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) |
|||
#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) |
|||
#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) |
|||
#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6)) |
|||
|
|||
#define RND(a, b, c, d, e, f, g, h, k) \ |
|||
t0 = h + S1(e) + Ch(e, f, g) + k; \ |
|||
t1 = S0(a) + Maj(a, b, c); \ |
|||
d += t0; \ |
|||
h = t0 + t1; |
|||
|
|||
#define RNDr(S, W, i, k) \ |
|||
RND(S[(80 - i) % 8], S[(81 - i) % 8], \ |
|||
S[(82 - i) % 8], S[(83 - i) % 8], \ |
|||
S[(84 - i) % 8], S[(85 - i) % 8], \ |
|||
S[(86 - i) % 8], S[(87 - i) % 8], \ |
|||
W[i] + k) |
|||
|
|||
static void |
|||
SHA512_Transform(uint64_t *state, const unsigned char block[128]) |
|||
{ |
|||
uint64_t W[80]; |
|||
uint64_t S[8]; |
|||
uint64_t t0, t1; |
|||
int i; |
|||
|
|||
be64dec_vect(W, block, 128); |
|||
for (i = 16; i < 80; i++) { |
|||
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; |
|||
} |
|||
|
|||
memcpy(S, state, 64); |
|||
|
|||
RNDr(S, W, 0, 0x428a2f98d728ae22ULL); |
|||
RNDr(S, W, 1, 0x7137449123ef65cdULL); |
|||
RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL); |
|||
RNDr(S, W, 3, 0xe9b5dba58189dbbcULL); |
|||
RNDr(S, W, 4, 0x3956c25bf348b538ULL); |
|||
RNDr(S, W, 5, 0x59f111f1b605d019ULL); |
|||
RNDr(S, W, 6, 0x923f82a4af194f9bULL); |
|||
RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL); |
|||
RNDr(S, W, 8, 0xd807aa98a3030242ULL); |
|||
RNDr(S, W, 9, 0x12835b0145706fbeULL); |
|||
RNDr(S, W, 10, 0x243185be4ee4b28cULL); |
|||
RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL); |
|||
RNDr(S, W, 12, 0x72be5d74f27b896fULL); |
|||
RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL); |
|||
RNDr(S, W, 14, 0x9bdc06a725c71235ULL); |
|||
RNDr(S, W, 15, 0xc19bf174cf692694ULL); |
|||
RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL); |
|||
RNDr(S, W, 17, 0xefbe4786384f25e3ULL); |
|||
RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL); |
|||
RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL); |
|||
RNDr(S, W, 20, 0x2de92c6f592b0275ULL); |
|||
RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL); |
|||
RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL); |
|||
RNDr(S, W, 23, 0x76f988da831153b5ULL); |
|||
RNDr(S, W, 24, 0x983e5152ee66dfabULL); |
|||
RNDr(S, W, 25, 0xa831c66d2db43210ULL); |
|||
RNDr(S, W, 26, 0xb00327c898fb213fULL); |
|||
RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL); |
|||
RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL); |
|||
RNDr(S, W, 29, 0xd5a79147930aa725ULL); |
|||
RNDr(S, W, 30, 0x06ca6351e003826fULL); |
|||
RNDr(S, W, 31, 0x142929670a0e6e70ULL); |
|||
RNDr(S, W, 32, 0x27b70a8546d22ffcULL); |
|||
RNDr(S, W, 33, 0x2e1b21385c26c926ULL); |
|||
RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL); |
|||
RNDr(S, W, 35, 0x53380d139d95b3dfULL); |
|||
RNDr(S, W, 36, 0x650a73548baf63deULL); |
|||
RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL); |
|||
RNDr(S, W, 38, 0x81c2c92e47edaee6ULL); |
|||
RNDr(S, W, 39, 0x92722c851482353bULL); |
|||
RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL); |
|||
RNDr(S, W, 41, 0xa81a664bbc423001ULL); |
|||
RNDr(S, W, 42, 0xc24b8b70d0f89791ULL); |
|||
RNDr(S, W, 43, 0xc76c51a30654be30ULL); |
|||
RNDr(S, W, 44, 0xd192e819d6ef5218ULL); |
|||
RNDr(S, W, 45, 0xd69906245565a910ULL); |
|||
RNDr(S, W, 46, 0xf40e35855771202aULL); |
|||
RNDr(S, W, 47, 0x106aa07032bbd1b8ULL); |
|||
RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL); |
|||
RNDr(S, W, 49, 0x1e376c085141ab53ULL); |
|||
RNDr(S, W, 50, 0x2748774cdf8eeb99ULL); |
|||
RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL); |
|||
RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL); |
|||
RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL); |
|||
RNDr(S, W, 54, 0x5b9cca4f7763e373ULL); |
|||
RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL); |
|||
RNDr(S, W, 56, 0x748f82ee5defb2fcULL); |
|||
RNDr(S, W, 57, 0x78a5636f43172f60ULL); |
|||
RNDr(S, W, 58, 0x84c87814a1f0ab72ULL); |
|||
RNDr(S, W, 59, 0x8cc702081a6439ecULL); |
|||
RNDr(S, W, 60, 0x90befffa23631e28ULL); |
|||
RNDr(S, W, 61, 0xa4506cebde82bde9ULL); |
|||
RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL); |
|||
RNDr(S, W, 63, 0xc67178f2e372532bULL); |
|||
RNDr(S, W, 64, 0xca273eceea26619cULL); |
|||
RNDr(S, W, 65, 0xd186b8c721c0c207ULL); |
|||
RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL); |
|||
RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL); |
|||
RNDr(S, W, 68, 0x06f067aa72176fbaULL); |
|||
RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL); |
|||
RNDr(S, W, 70, 0x113f9804bef90daeULL); |
|||
RNDr(S, W, 71, 0x1b710b35131c471bULL); |
|||
RNDr(S, W, 72, 0x28db77f523047d84ULL); |
|||
RNDr(S, W, 73, 0x32caab7b40c72493ULL); |
|||
RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL); |
|||
RNDr(S, W, 75, 0x431d67c49c100d4cULL); |
|||
RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL); |
|||
RNDr(S, W, 77, 0x597f299cfc657e2aULL); |
|||
RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL); |
|||
RNDr(S, W, 79, 0x6c44198c4a475817ULL); |
|||
|
|||
for (i = 0; i < 8; i++) { |
|||
state[i] += S[i]; |
|||
} |
|||
|
|||
sodium_memzero((void *) W, sizeof W); |
|||
sodium_memzero((void *) S, sizeof S); |
|||
sodium_memzero((void *) &t0, sizeof t0); |
|||
sodium_memzero((void *) &t1, sizeof t1); |
|||
} |
|||
|
|||
static unsigned char PAD[128] = { |
|||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
|||
}; |
|||
|
|||
static void |
|||
SHA512_Pad(crypto_hash_sha512_state *state) |
|||
{ |
|||
unsigned char len[16]; |
|||
uint64_t r, plen; |
|||
|
|||
be64enc_vect(len, state->count, 16); |
|||
|
|||
r = (state->count[1] >> 3) & 0x7f; |
|||
plen = (r < 112) ? (112 - r) : (240 - r); |
|||
crypto_hash_sha512_update(state, PAD, (unsigned long long) plen); |
|||
|
|||
crypto_hash_sha512_update(state, len, 16); |
|||
} |
|||
|
|||
int |
|||
crypto_hash_sha512_init(crypto_hash_sha512_state *state) |
|||
{ |
|||
state->count[0] = state->count[1] = 0; |
|||
|
|||
state->state[0] = 0x6a09e667f3bcc908ULL; |
|||
state->state[1] = 0xbb67ae8584caa73bULL; |
|||
state->state[2] = 0x3c6ef372fe94f82bULL; |
|||
state->state[3] = 0xa54ff53a5f1d36f1ULL; |
|||
state->state[4] = 0x510e527fade682d1ULL; |
|||
state->state[5] = 0x9b05688c2b3e6c1fULL; |
|||
state->state[6] = 0x1f83d9abfb41bd6bULL; |
|||
state->state[7] = 0x5be0cd19137e2179ULL; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_hash_sha512_update(crypto_hash_sha512_state *state, |
|||
const unsigned char *in, |
|||
unsigned long long inlen) |
|||
{ |
|||
uint64_t bitlen[2]; |
|||
uint64_t r; |
|||
const unsigned char *src = in; |
|||
|
|||
r = (state->count[1] >> 3) & 0x7f; |
|||
|
|||
bitlen[1] = ((uint64_t)inlen) << 3; |
|||
bitlen[0] = ((uint64_t)inlen) >> 61; |
|||
|
|||
if ((state->count[1] += bitlen[1]) < bitlen[1]) { |
|||
state->count[0]++; |
|||
} |
|||
state->count[0] += bitlen[0]; |
|||
|
|||
if (inlen < 128 - r) { |
|||
memcpy(&state->buf[r], src, inlen); |
|||
return 0; |
|||
} |
|||
memcpy(&state->buf[r], src, 128 - r); |
|||
SHA512_Transform(state->state, state->buf); |
|||
src += 128 - r; |
|||
inlen -= 128 - r; |
|||
|
|||
while (inlen >= 128) { |
|||
SHA512_Transform(state->state, src); |
|||
src += 128; |
|||
inlen -= 128; |
|||
} |
|||
memcpy(state->buf, src, inlen); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_hash_sha512_final(crypto_hash_sha512_state *state, |
|||
unsigned char *out) |
|||
{ |
|||
SHA512_Pad(state); |
|||
be64enc_vect(out, state->state, 64); |
|||
sodium_memzero((void *) state, sizeof *state); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
crypto_hash(unsigned char *out, const unsigned char *in, |
|||
unsigned long long inlen) |
|||
{ |
|||
crypto_hash_sha512_state state; |
|||
|
|||
crypto_hash_sha512_init(&state); |
|||
crypto_hash_sha512_update(&state, in, inlen); |
|||
crypto_hash_sha512_final(&state, out); |
|||
|
|||
return 0; |
|||
} |
|||
|
@ -1,71 +0,0 @@ |
|||
/*
|
|||
20080913 |
|||
D. J. Bernstein |
|||
Public domain. |
|||
*/ |
|||
|
|||
#include "api.h" |
|||
#include "_crypto_hashblocks_sha512.h" |
|||
|
|||
#define blocks crypto_hashblocks_sha512 |
|||
|
|||
static const unsigned char iv[64] = { |
|||
0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, |
|||
0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, |
|||
0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, |
|||
0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, |
|||
0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, |
|||
0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, |
|||
0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, |
|||
0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 |
|||
} ; |
|||
|
|||
typedef unsigned long long uint64; |
|||
|
|||
int crypto_hash(unsigned char *out,const unsigned char *in,unsigned long long inlen) |
|||
{ |
|||
unsigned char h[64]; |
|||
unsigned char padded[256]; |
|||
unsigned long long i; |
|||
unsigned long long bytes = inlen; |
|||
|
|||
for (i = 0;i < 64;++i) h[i] = iv[i]; |
|||
|
|||
blocks(h,in,inlen); |
|||
in += inlen; |
|||
inlen &= 127; |
|||
in -= inlen; |
|||
|
|||
for (i = 0;i < inlen;++i) padded[i] = in[i]; |
|||
padded[inlen] = 0x80; |
|||
|
|||
if (inlen < 112) { |
|||
for (i = inlen + 1;i < 119;++i) padded[i] = 0; |
|||
padded[119] = bytes >> 61; |
|||
padded[120] = bytes >> 53; |
|||
padded[121] = bytes >> 45; |
|||
padded[122] = bytes >> 37; |
|||
padded[123] = bytes >> 29; |
|||
padded[124] = bytes >> 21; |
|||
padded[125] = bytes >> 13; |
|||
padded[126] = bytes >> 5; |
|||
padded[127] = bytes << 3; |
|||
blocks(h,padded,128); |
|||
} else { |
|||
for (i = inlen + 1;i < 247;++i) padded[i] = 0; |
|||
padded[247] = bytes >> 61; |
|||
padded[248] = bytes >> 53; |
|||
padded[249] = bytes >> 45; |
|||
padded[250] = bytes >> 37; |
|||
padded[251] = bytes >> 29; |
|||
padded[252] = bytes >> 21; |
|||
padded[253] = bytes >> 13; |
|||
padded[254] = bytes >> 5; |
|||
padded[255] = bytes << 3; |
|||
blocks(h,padded,256); |
|||
} |
|||
|
|||
for (i = 0;i < 64;++i) out[i] = h[i]; |
|||
|
|||
return 0; |
|||
} |
@ -1 +0,0 @@ |
|||
f005c91634ae549f0dd4529ddbaf07038cb75a59b818cd1d4eb4e2b4019ab6733556131f320c4a145c735a22594581d454cccb15c18bf198ffcb2da29fe39456 |
@ -1,9 +0,0 @@ |
|||
|
|||
#include "_crypto_hashblocks_sha512.h" |
|||
|
|||
#define crypto_hashblocks crypto_hashblocks_sha512 |
|||
#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES |
|||
#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES |
|||
#define crypto_hashblocks_PRIMITIVE "sha512" |
|||
#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION |
|||
#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION |
@ -1,239 +0,0 @@ |
|||
#include "api.h" |
|||
|
|||
typedef unsigned long long uint64; |
|||
|
|||
static uint64 load_bigendian(const unsigned char *x) |
|||
{ |
|||
return |
|||
(uint64) (x[7]) \ |
|||
| (((uint64) (x[6])) << 8) \ |
|||
| (((uint64) (x[5])) << 16) \ |
|||
| (((uint64) (x[4])) << 24) \ |
|||
| (((uint64) (x[3])) << 32) \ |
|||
| (((uint64) (x[2])) << 40) \ |
|||
| (((uint64) (x[1])) << 48) \ |
|||
| (((uint64) (x[0])) << 56) |
|||
; |
|||
} |
|||
|
|||
static void store_bigendian(unsigned char *x,uint64 u) |
|||
{ |
|||
x[7] = u; u >>= 8; |
|||
x[6] = u; u >>= 8; |
|||
x[5] = u; u >>= 8; |
|||
x[4] = u; u >>= 8; |
|||
x[3] = u; u >>= 8; |
|||
x[2] = u; u >>= 8; |
|||
x[1] = u; u >>= 8; |
|||
x[0] = u; |
|||
} |
|||
|
|||
#define SHR(x,c) ((x) >> (c)) |
|||
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) |
|||
|
|||
#define Ch(x,y,z) ((x & y) ^ (~x & z)) |
|||
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) |
|||
#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) |
|||
#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) |
|||
#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7)) |
|||
#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6)) |
|||
|
|||
#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0; |
|||
|
|||
#define EXPAND \ |
|||
M(w0 ,w14,w9 ,w1 ) \ |
|||
M(w1 ,w15,w10,w2 ) \ |
|||
M(w2 ,w0 ,w11,w3 ) \ |
|||
M(w3 ,w1 ,w12,w4 ) \ |
|||
M(w4 ,w2 ,w13,w5 ) \ |
|||
M(w5 ,w3 ,w14,w6 ) \ |
|||
M(w6 ,w4 ,w15,w7 ) \ |
|||
M(w7 ,w5 ,w0 ,w8 ) \ |
|||
M(w8 ,w6 ,w1 ,w9 ) \ |
|||
M(w9 ,w7 ,w2 ,w10) \ |
|||
M(w10,w8 ,w3 ,w11) \ |
|||
M(w11,w9 ,w4 ,w12) \ |
|||
M(w12,w10,w5 ,w13) \ |
|||
M(w13,w11,w6 ,w14) \ |
|||
M(w14,w12,w7 ,w15) \ |
|||
M(w15,w13,w8 ,w0 ) |
|||
|
|||
#define F(w,k) \ |
|||
T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ |
|||
T2 = Sigma0(a) + Maj(a,b,c); \ |
|||
h = g; \ |
|||
g = f; \ |
|||
f = e; \ |
|||
e = d + T1; \ |
|||
d = c; \ |
|||
c = b; \ |
|||
b = a; \ |
|||
a = T1 + T2; |
|||
|
|||
int crypto_hashblocks(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) |
|||
{ |
|||
uint64 state[8]; |
|||
uint64 a; |
|||
uint64 b; |
|||
uint64 c; |
|||
uint64 d; |
|||
uint64 e; |
|||
uint64 f; |
|||
uint64 g; |
|||
uint64 h; |
|||
uint64 T1; |
|||
uint64 T2; |
|||
|
|||
a = load_bigendian(statebytes + 0); state[0] = a; |
|||
b = load_bigendian(statebytes + 8); state[1] = b; |
|||
c = load_bigendian(statebytes + 16); state[2] = c; |
|||
d = load_bigendian(statebytes + 24); state[3] = d; |
|||
e = load_bigendian(statebytes + 32); state[4] = e; |
|||
f = load_bigendian(statebytes + 40); state[5] = f; |
|||
g = load_bigendian(statebytes + 48); state[6] = g; |
|||
h = load_bigendian(statebytes + 56); state[7] = h; |
|||
|
|||
while (inlen >= 128) { |
|||
uint64 w0 = load_bigendian(in + 0); |
|||
uint64 w1 = load_bigendian(in + 8); |
|||
uint64 w2 = load_bigendian(in + 16); |
|||
uint64 w3 = load_bigendian(in + 24); |
|||
uint64 w4 = load_bigendian(in + 32); |
|||
uint64 w5 = load_bigendian(in + 40); |
|||
uint64 w6 = load_bigendian(in + 48); |
|||
uint64 w7 = load_bigendian(in + 56); |
|||
uint64 w8 = load_bigendian(in + 64); |
|||
uint64 w9 = load_bigendian(in + 72); |
|||
uint64 w10 = load_bigendian(in + 80); |
|||
uint64 w11 = load_bigendian(in + 88); |
|||
uint64 w12 = load_bigendian(in + 96); |
|||
uint64 w13 = load_bigendian(in + 104); |
|||
uint64 w14 = load_bigendian(in + 112); |
|||
uint64 w15 = load_bigendian(in + 120); |
|||
|
|||
F(w0 ,0x428a2f98d728ae22ULL) |
|||
F(w1 ,0x7137449123ef65cdULL) |
|||
F(w2 ,0xb5c0fbcfec4d3b2fULL) |
|||
F(w3 ,0xe9b5dba58189dbbcULL) |
|||
F(w4 ,0x3956c25bf348b538ULL) |
|||
F(w5 ,0x59f111f1b605d019ULL) |
|||
F(w6 ,0x923f82a4af194f9bULL) |
|||
F(w7 ,0xab1c5ed5da6d8118ULL) |
|||
F(w8 ,0xd807aa98a3030242ULL) |
|||
F(w9 ,0x12835b0145706fbeULL) |
|||
F(w10,0x243185be4ee4b28cULL) |
|||
F(w11,0x550c7dc3d5ffb4e2ULL) |
|||
F(w12,0x72be5d74f27b896fULL) |
|||
F(w13,0x80deb1fe3b1696b1ULL) |
|||
F(w14,0x9bdc06a725c71235ULL) |
|||
F(w15,0xc19bf174cf692694ULL) |
|||
|
|||
EXPAND |
|||
|
|||
F(w0 ,0xe49b69c19ef14ad2ULL) |
|||
F(w1 ,0xefbe4786384f25e3ULL) |
|||
F(w2 ,0x0fc19dc68b8cd5b5ULL) |
|||
F(w3 ,0x240ca1cc77ac9c65ULL) |
|||
F(w4 ,0x2de92c6f592b0275ULL) |
|||
F(w5 ,0x4a7484aa6ea6e483ULL) |
|||
F(w6 ,0x5cb0a9dcbd41fbd4ULL) |
|||
F(w7 ,0x76f988da831153b5ULL) |
|||
F(w8 ,0x983e5152ee66dfabULL) |
|||
F(w9 ,0xa831c66d2db43210ULL) |
|||
F(w10,0xb00327c898fb213fULL) |
|||
F(w11,0xbf597fc7beef0ee4ULL) |
|||
F(w12,0xc6e00bf33da88fc2ULL) |
|||
F(w13,0xd5a79147930aa725ULL) |
|||
F(w14,0x06ca6351e003826fULL) |
|||
F(w15,0x142929670a0e6e70ULL) |
|||
|
|||
EXPAND |
|||
|
|||
F(w0 ,0x27b70a8546d22ffcULL) |
|||
F(w1 ,0x2e1b21385c26c926ULL) |
|||
F(w2 ,0x4d2c6dfc5ac42aedULL) |
|||
F(w3 ,0x53380d139d95b3dfULL) |
|||
F(w4 ,0x650a73548baf63deULL) |
|||
F(w5 ,0x766a0abb3c77b2a8ULL) |
|||
F(w6 ,0x81c2c92e47edaee6ULL) |
|||
F(w7 ,0x92722c851482353bULL) |
|||
F(w8 ,0xa2bfe8a14cf10364ULL) |
|||
F(w9 ,0xa81a664bbc423001ULL) |
|||
F(w10,0xc24b8b70d0f89791ULL) |
|||
F(w11,0xc76c51a30654be30ULL) |
|||
F(w12,0xd192e819d6ef5218ULL) |
|||
F(w13,0xd69906245565a910ULL) |
|||
F(w14,0xf40e35855771202aULL) |
|||
F(w15,0x106aa07032bbd1b8ULL) |
|||
|
|||
EXPAND |
|||
|
|||
F(w0 ,0x19a4c116b8d2d0c8ULL) |
|||
F(w1 ,0x1e376c085141ab53ULL) |
|||
F(w2 ,0x2748774cdf8eeb99ULL) |
|||
F(w3 ,0x34b0bcb5e19b48a8ULL) |
|||
F(w4 ,0x391c0cb3c5c95a63ULL) |
|||
F(w5 ,0x4ed8aa4ae3418acbULL) |
|||
F(w6 ,0x5b9cca4f7763e373ULL) |
|||
F(w7 ,0x682e6ff3d6b2b8a3ULL) |
|||
F(w8 ,0x748f82ee5defb2fcULL) |
|||
F(w9 ,0x78a5636f43172f60ULL) |
|||
F(w10,0x84c87814a1f0ab72ULL) |
|||
F(w11,0x8cc702081a6439ecULL) |
|||
F(w12,0x90befffa23631e28ULL) |
|||
F(w13,0xa4506cebde82bde9ULL) |
|||
F(w14,0xbef9a3f7b2c67915ULL) |
|||
F(w15,0xc67178f2e372532bULL) |
|||
|
|||
EXPAND |
|||
|
|||
F(w0 ,0xca273eceea26619cULL) |
|||
F(w1 ,0xd186b8c721c0c207ULL) |
|||
F(w2 ,0xeada7dd6cde0eb1eULL) |
|||
F(w3 ,0xf57d4f7fee6ed178ULL) |
|||
F(w4 ,0x06f067aa72176fbaULL) |
|||
F(w5 ,0x0a637dc5a2c898a6ULL) |
|||
F(w6 ,0x113f9804bef90daeULL) |
|||
F(w7 ,0x1b710b35131c471bULL) |
|||
F(w8 ,0x28db77f523047d84ULL) |
|||
F(w9 ,0x32caab7b40c72493ULL) |
|||
F(w10,0x3c9ebe0a15c9bebcULL) |
|||
F(w11,0x431d67c49c100d4cULL) |
|||
F(w12,0x4cc5d4becb3e42b6ULL) |
|||
F(w13,0x597f299cfc657e2aULL) |
|||
F(w14,0x5fcb6fab3ad6faecULL) |
|||
F(w15,0x6c44198c4a475817ULL) |
|||
|
|||
a += state[0]; |
|||
b += state[1]; |
|||
c += state[2]; |
|||
d += state[3]; |
|||
e += state[4]; |
|||
f += state[5]; |
|||
g += state[6]; |
|||
h += state[7]; |
|||
|
|||
state[0] = a; |
|||
state[1] = b; |
|||
state[2] = c; |
|||
state[3] = d; |
|||
state[4] = e; |
|||
state[5] = f; |
|||
state[6] = g; |
|||
state[7] = h; |
|||
|
|||
in += 128; |
|||
inlen -= 128; |
|||
} |
|||
|
|||
store_bigendian(statebytes + 0,state[0]); |
|||
store_bigendian(statebytes + 8,state[1]); |
|||
store_bigendian(statebytes + 16,state[2]); |
|||
store_bigendian(statebytes + 24,state[3]); |
|||
store_bigendian(statebytes + 32,state[4]); |
|||
store_bigendian(statebytes + 40,state[5]); |
|||
store_bigendian(statebytes + 48,state[6]); |
|||
store_bigendian(statebytes + 56,state[7]); |
|||
|
|||
return 0; |
|||
} |
@ -1,78 +0,0 @@ |
|||
/*
|
|||
* crypto_hashblocks/try.c version 20090118 |
|||
* D. J. Bernstein |
|||
* Public domain. |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include "crypto_hashblocks.h" |
|||
#include "utils.h" |
|||
#include "windows/windows-quirks.h" |
|||
|
|||
extern unsigned char *alignedcalloc(unsigned long long); |
|||
|
|||
const char *primitiveimplementation = crypto_hashblocks_IMPLEMENTATION; |
|||
|
|||
#define MAXTEST_BYTES (10000 + crypto_hashblocks_STATEBYTES) |
|||
#define CHECKSUM_BYTES 4096 |
|||
#define TUNE_BYTES 1536 |
|||
|
|||
static unsigned char *h; |
|||
static unsigned char *h2; |
|||
static unsigned char *m; |
|||
static unsigned char *m2; |
|||
|
|||
void preallocate(void) |
|||
{ |
|||
} |
|||
|
|||
void allocate(void) |
|||
{ |
|||
h = alignedcalloc(crypto_hashblocks_STATEBYTES); |
|||
h2 = alignedcalloc(crypto_hashblocks_STATEBYTES); |
|||
m = alignedcalloc(MAXTEST_BYTES); |
|||
m2 = alignedcalloc(MAXTEST_BYTES); |
|||
} |
|||
|
|||
void predoit(void) |
|||
{ |
|||
} |
|||
|
|||
void doit(void) |
|||
{ |
|||
crypto_hashblocks(h,m,TUNE_BYTES); |
|||
} |
|||
|
|||
char checksum[crypto_hashblocks_STATEBYTES * 2 + 1]; |
|||
|
|||
const char *checksum_compute(void) |
|||
{ |
|||
long long i; |
|||
long long j; |
|||
|
|||
for (i = 0;i < CHECKSUM_BYTES;++i) { |
|||
long long hlen = crypto_hashblocks_STATEBYTES; |
|||
long long mlen = i; |
|||
for (j = -16;j < 0;++j) h[j] = rand(); |
|||
for (j = hlen;j < hlen + 16;++j) h[j] = rand(); |
|||
for (j = -16;j < hlen + 16;++j) h2[j] = h[j]; |
|||
for (j = -16;j < 0;++j) m[j] = rand(); |
|||
for (j = mlen;j < mlen + 16;++j) m[j] = rand(); |
|||
for (j = -16;j < mlen + 16;++j) m2[j] = m[j]; |
|||
if (crypto_hashblocks(h,m,mlen) != 0) return "crypto_hashblocks returns nonzero"; |
|||
for (j = -16;j < mlen + 16;++j) if (m2[j] != m[j]) return "crypto_hashblocks writes to input"; |
|||
for (j = -16;j < 0;++j) if (h2[j] != h[j]) return "crypto_hashblocks writes before output"; |
|||
for (j = hlen;j < hlen + 16;++j) if (h2[j] != h[j]) return "crypto_hashblocks writes after output"; |
|||
for (j = 0;j < hlen;++j) m2[j] = h2[j]; |
|||
if (crypto_hashblocks(h2,m2,mlen) != 0) return "crypto_hashblocks returns nonzero"; |
|||
if (crypto_hashblocks(m2,m2,mlen) != 0) return "crypto_hashblocks returns nonzero"; |
|||
for (j = 0;j < hlen;++j) if (m2[j] != h2[j]) return "crypto_hashblocks does not handle overlap"; |
|||
for (j = 0;j < mlen;++j) m[j] ^= h[j % hlen]; |
|||
m[mlen] = h[0]; |
|||
} |
|||
if (crypto_hashblocks(h,m,CHECKSUM_BYTES) != 0) return "crypto_hashblocks returns nonzero"; |
|||
|
|||
sodium_bin2hex(checksum, sizeof checksum, h, crypto_hashblocks_STATEBYTES); |
|||
|
|||
return 0; |
|||
} |
@ -1,24 +0,0 @@ |
|||
#ifndef _crypto_hashblocks_sha512_H |
|||
#define _crypto_hashblocks_sha512_H |
|||
|
|||
#include <stddef.h> |
|||
#include "export.h" |
|||
|
|||
#define crypto_hashblocks_sha512_STATEBYTES 64U |
|||
#define crypto_hashblocks_sha512_BLOCKBYTES 128U |
|||
|
|||
#ifdef __cplusplus |
|||
# if __GNUC__ |
|||
# pragma GCC diagnostic ignored "-Wlong-long" |
|||
# endif |
|||
extern "C" { |
|||
#endif |
|||
|
|||
/* This function is only used internally */ |
|||
int crypto_hashblocks_sha512(unsigned char *,const unsigned char *,unsigned long long); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
Loading…
Reference in new issue