- Upgrade to 1.0
This commit is contained in:
1 parent
4e66c377fd
commit
0c2b3f1c25
452 files changed
+33888
-16806
No files matched your search
Generated
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* ISC License
|
||||
*
|
||||
* Copyright (c) 2013-2016
|
||||
* Frank Denis <j at pureftpd dot org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Generated
+46
@@ -0,0 +1,46 @@
|
||||
[](https://travis-ci.org/jedisct1/libsodium?branch=master)
|
||||
[](https://ci.appveyor.com/project/jedisct1/libsodium)
|
||||
[](https://scan.coverity.com/projects/2397)
|
||||
|
||||

|
||||
============
|
||||
|
||||
Sodium is a new, easy-to-use software library for encryption,
|
||||
decryption, signatures, password hashing and more.
|
||||
|
||||
It is a portable, cross-compilable, installable, packageable
|
||||
fork of [NaCl](http://nacl.cr.yp.to/), with a compatible API, and an
|
||||
extended API to improve usability even further.
|
||||
|
||||
Its goal is to provide all of the core operations needed to build
|
||||
higher-level cryptographic tools.
|
||||
|
||||
Sodium supports a variety of compilers and operating systems,
|
||||
including Windows (with MingW or Visual Studio, x86 and x64), iOS and Android.
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation is a work-in-progress, and is being written using
|
||||
Gitbook:
|
||||
|
||||
* [libsodium documentation](https://download.libsodium.org/doc/) -
|
||||
online, requires Javascript.
|
||||
* [offline documentation](https://www.gitbook.com/book/jedisct1/libsodium/details)
|
||||
in PDF, MOBI and ePUB formats.
|
||||
|
||||
## Integrity Checking
|
||||
|
||||
The integrity checking instructions (including the signing key for libsodium)
|
||||
are available in the [installation](https://download.libsodium.org/doc/installation/index.html#integrity-checking)
|
||||
section of the documentation.
|
||||
|
||||
## Community
|
||||
|
||||
A mailing-list is available to discuss libsodium.
|
||||
|
||||
In order to join, just send a random mail to `sodium-subscribe` {at}
|
||||
`pureftpd` {dot} `org`.
|
||||
|
||||
## License
|
||||
|
||||
[ISC license](https://en.wikipedia.org/wiki/ISC_license).
|
||||
+1045
File diff suppressed because it is too large.
Load diff
Generated
+365
@@ -0,0 +1,365 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_aead_chacha20poly1305.h"
|
||||
#include "crypto_onetimeauth_poly1305.h"
|
||||
#include "crypto_stream_chacha20.h"
|
||||
#include "crypto_verify_16.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "private/common.h"
|
||||
|
||||
static const unsigned char _pad0[16] = { 0 };
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c,
|
||||
unsigned char *mac,
|
||||
unsigned long long *maclen_p,
|
||||
const unsigned char *m,
|
||||
unsigned long long mlen,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *nsec,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
crypto_onetimeauth_poly1305_state state;
|
||||
unsigned char block0[64U];
|
||||
unsigned char slen[8U];
|
||||
|
||||
(void) nsec;
|
||||
crypto_stream_chacha20(block0, sizeof block0, npub, k);
|
||||
crypto_onetimeauth_poly1305_init(&state, block0);
|
||||
sodium_memzero(block0, sizeof block0);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&state, ad, adlen);
|
||||
STORE64_LE(slen, (uint64_t) adlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&state, c, mlen);
|
||||
STORE64_LE(slen, (uint64_t) mlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
crypto_onetimeauth_poly1305_final(&state, mac);
|
||||
sodium_memzero(&state, sizeof state);
|
||||
|
||||
if (maclen_p != NULL) {
|
||||
*maclen_p = crypto_aead_chacha20poly1305_ABYTES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
|
||||
unsigned long long *clen_p,
|
||||
const unsigned char *m,
|
||||
unsigned long long mlen,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *nsec,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned long long clen = 0ULL;
|
||||
int ret;
|
||||
|
||||
if (mlen > UINT64_MAX - crypto_aead_chacha20poly1305_ABYTES) {
|
||||
abort(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
ret = crypto_aead_chacha20poly1305_encrypt_detached(c,
|
||||
c + mlen, NULL,
|
||||
m, mlen,
|
||||
ad, adlen,
|
||||
nsec, npub, k);
|
||||
if (clen_p != NULL) {
|
||||
if (ret == 0) {
|
||||
clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
|
||||
}
|
||||
*clen_p = clen;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c,
|
||||
unsigned char *mac,
|
||||
unsigned long long *maclen_p,
|
||||
const unsigned char *m,
|
||||
unsigned long long mlen,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *nsec,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
crypto_onetimeauth_poly1305_state state;
|
||||
unsigned char block0[64U];
|
||||
unsigned char slen[8U];
|
||||
|
||||
(void) nsec;
|
||||
crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
|
||||
crypto_onetimeauth_poly1305_init(&state, block0);
|
||||
sodium_memzero(block0, sizeof block0);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&state, ad, adlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
|
||||
|
||||
crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&state, c, mlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
|
||||
|
||||
STORE64_LE(slen, (uint64_t) adlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
STORE64_LE(slen, (uint64_t) mlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
crypto_onetimeauth_poly1305_final(&state, mac);
|
||||
sodium_memzero(&state, sizeof state);
|
||||
|
||||
if (maclen_p != NULL) {
|
||||
*maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c,
|
||||
unsigned long long *clen_p,
|
||||
const unsigned char *m,
|
||||
unsigned long long mlen,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *nsec,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned long long clen = 0ULL;
|
||||
int ret;
|
||||
|
||||
if (mlen > UINT64_MAX - crypto_aead_chacha20poly1305_ietf_ABYTES) {
|
||||
abort(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c,
|
||||
c + mlen, NULL,
|
||||
m, mlen,
|
||||
ad, adlen,
|
||||
nsec, npub, k);
|
||||
if (clen_p != NULL) {
|
||||
if (ret == 0) {
|
||||
clen = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES;
|
||||
}
|
||||
*clen_p = clen;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m,
|
||||
unsigned char *nsec,
|
||||
const unsigned char *c,
|
||||
unsigned long long clen,
|
||||
const unsigned char *mac,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
crypto_onetimeauth_poly1305_state state;
|
||||
unsigned char block0[64U];
|
||||
unsigned char slen[8U];
|
||||
unsigned char computed_mac[crypto_aead_chacha20poly1305_ABYTES];
|
||||
unsigned long long mlen;
|
||||
int ret;
|
||||
|
||||
(void) nsec;
|
||||
crypto_stream_chacha20(block0, sizeof block0, npub, k);
|
||||
crypto_onetimeauth_poly1305_init(&state, block0);
|
||||
sodium_memzero(block0, sizeof block0);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&state, ad, adlen);
|
||||
STORE64_LE(slen, (uint64_t) adlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
mlen = clen;
|
||||
crypto_onetimeauth_poly1305_update(&state, c, mlen);
|
||||
STORE64_LE(slen, (uint64_t) mlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
crypto_onetimeauth_poly1305_final(&state, computed_mac);
|
||||
sodium_memzero(&state, sizeof state);
|
||||
|
||||
(void) sizeof(int[sizeof computed_mac == 16U ? 1 : -1]);
|
||||
ret = crypto_verify_16(computed_mac, mac);
|
||||
sodium_memzero(computed_mac, sizeof computed_mac);
|
||||
if (m == NULL) {
|
||||
return ret;
|
||||
}
|
||||
if (ret != 0) {
|
||||
memset(m, 0, mlen);
|
||||
return -1;
|
||||
}
|
||||
crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
|
||||
unsigned long long *mlen_p,
|
||||
unsigned char *nsec,
|
||||
const unsigned char *c,
|
||||
unsigned long long clen,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned long long mlen = 0ULL;
|
||||
int ret = -1;
|
||||
|
||||
if (clen >= crypto_aead_chacha20poly1305_ABYTES) {
|
||||
ret = crypto_aead_chacha20poly1305_decrypt_detached
|
||||
(m, nsec,
|
||||
c, clen - crypto_aead_chacha20poly1305_ABYTES,
|
||||
c + clen - crypto_aead_chacha20poly1305_ABYTES,
|
||||
ad, adlen, npub, k);
|
||||
}
|
||||
if (mlen_p != NULL) {
|
||||
if (ret == 0) {
|
||||
mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
|
||||
}
|
||||
*mlen_p = mlen;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m,
|
||||
unsigned char *nsec,
|
||||
const unsigned char *c,
|
||||
unsigned long long clen,
|
||||
const unsigned char *mac,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
crypto_onetimeauth_poly1305_state state;
|
||||
unsigned char block0[64U];
|
||||
unsigned char slen[8U];
|
||||
unsigned char computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
|
||||
unsigned long long mlen;
|
||||
int ret;
|
||||
|
||||
(void) nsec;
|
||||
crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
|
||||
crypto_onetimeauth_poly1305_init(&state, block0);
|
||||
sodium_memzero(block0, sizeof block0);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&state, ad, adlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
|
||||
|
||||
mlen = clen;
|
||||
crypto_onetimeauth_poly1305_update(&state, c, mlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
|
||||
|
||||
STORE64_LE(slen, (uint64_t) adlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
STORE64_LE(slen, (uint64_t) mlen);
|
||||
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
|
||||
|
||||
crypto_onetimeauth_poly1305_final(&state, computed_mac);
|
||||
sodium_memzero(&state, sizeof state);
|
||||
|
||||
(void) sizeof(int[sizeof computed_mac == 16U ? 1 : -1]);
|
||||
ret = crypto_verify_16(computed_mac, mac);
|
||||
sodium_memzero(computed_mac, sizeof computed_mac);
|
||||
if (m == NULL) {
|
||||
return ret;
|
||||
}
|
||||
if (ret != 0) {
|
||||
memset(m, 0, mlen);
|
||||
return -1;
|
||||
}
|
||||
crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m,
|
||||
unsigned long long *mlen_p,
|
||||
unsigned char *nsec,
|
||||
const unsigned char *c,
|
||||
unsigned long long clen,
|
||||
const unsigned char *ad,
|
||||
unsigned long long adlen,
|
||||
const unsigned char *npub,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned long long mlen = 0ULL;
|
||||
int ret = -1;
|
||||
|
||||
if (clen >= crypto_aead_chacha20poly1305_ietf_ABYTES) {
|
||||
ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
|
||||
(m, nsec,
|
||||
c, clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||
c + clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||
ad, adlen, npub, k);
|
||||
}
|
||||
if (mlen_p != NULL) {
|
||||
if (ret == 0) {
|
||||
mlen = clen - crypto_aead_chacha20poly1305_ietf_ABYTES;
|
||||
}
|
||||
*mlen_p = mlen;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_ietf_keybytes(void) {
|
||||
return crypto_aead_chacha20poly1305_ietf_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_ietf_npubbytes(void) {
|
||||
return crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_ietf_nsecbytes(void) {
|
||||
return crypto_aead_chacha20poly1305_ietf_NSECBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_ietf_abytes(void) {
|
||||
return crypto_aead_chacha20poly1305_ietf_ABYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_keybytes(void) {
|
||||
return crypto_aead_chacha20poly1305_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_npubbytes(void) {
|
||||
return crypto_aead_chacha20poly1305_NPUBBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_nsecbytes(void) {
|
||||
return crypto_aead_chacha20poly1305_NSECBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_aead_chacha20poly1305_abytes(void) {
|
||||
return crypto_aead_chacha20poly1305_ABYTES;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
#include "crypto_auth.h"
|
||||
|
||||
size_t
|
||||
crypto_auth_bytes(void)
|
||||
{
|
||||
return crypto_auth_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_keybytes(void)
|
||||
{
|
||||
return crypto_auth_KEYBYTES;
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_auth_primitive(void)
|
||||
{
|
||||
return crypto_auth_PRIMITIVE;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_auth(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
return crypto_auth_hmacsha512256(out, in, inlen, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_auth_verify(const unsigned char *h, const unsigned char *in,
|
||||
unsigned long long inlen,const unsigned char *k)
|
||||
{
|
||||
return crypto_auth_hmacsha512256_verify(h, in, inlen, k);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#include "crypto_auth_hmacsha256.h"
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha256_bytes(void) {
|
||||
return crypto_auth_hmacsha256_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha256_keybytes(void) {
|
||||
return crypto_auth_hmacsha256_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha256_statebytes(void) {
|
||||
return sizeof(crypto_auth_hmacsha256_state);
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
|
||||
/*-
|
||||
* 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 "crypto_auth_hmacsha256.h"
|
||||
#include "crypto_hash_sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
crypto_auth_hmacsha256_init(crypto_auth_hmacsha256_state *state,
|
||||
const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
unsigned char pad[64];
|
||||
unsigned char khash[32];
|
||||
size_t i;
|
||||
|
||||
if (keylen > 64) {
|
||||
crypto_hash_sha256_init(&state->ictx);
|
||||
crypto_hash_sha256_update(&state->ictx, key, keylen);
|
||||
crypto_hash_sha256_final(&state->ictx, khash);
|
||||
key = khash;
|
||||
keylen = 32;
|
||||
}
|
||||
crypto_hash_sha256_init(&state->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < keylen; i++) {
|
||||
pad[i] ^= key[i];
|
||||
}
|
||||
crypto_hash_sha256_update(&state->ictx, pad, 64);
|
||||
|
||||
crypto_hash_sha256_init(&state->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < keylen; i++) {
|
||||
pad[i] ^= key[i];
|
||||
}
|
||||
crypto_hash_sha256_update(&state->octx, pad, 64);
|
||||
|
||||
sodium_memzero((void *) pad, sizeof pad);
|
||||
sodium_memzero((void *) khash, sizeof khash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_auth_hmacsha256_update(crypto_auth_hmacsha256_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
crypto_hash_sha256_update(&state->ictx, in, inlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_auth_hmacsha256_final(crypto_auth_hmacsha256_state *state,
|
||||
unsigned char *out)
|
||||
{
|
||||
unsigned char ihash[32];
|
||||
|
||||
crypto_hash_sha256_final(&state->ictx, ihash);
|
||||
crypto_hash_sha256_update(&state->octx, ihash, 32);
|
||||
crypto_hash_sha256_final(&state->octx, out);
|
||||
|
||||
sodium_memzero((void *) ihash, sizeof ihash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_auth_hmacsha256(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
crypto_auth_hmacsha256_state state;
|
||||
|
||||
crypto_auth_hmacsha256_init(&state, k, crypto_auth_hmacsha256_KEYBYTES);
|
||||
crypto_auth_hmacsha256_update(&state, in, inlen);
|
||||
crypto_auth_hmacsha256_final(&state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
#include "crypto_auth_hmacsha256.h"
|
||||
#include "crypto_verify_32.h"
|
||||
#include "utils.h"
|
||||
|
||||
int crypto_auth_hmacsha256_verify(const unsigned char *h,const unsigned char *in,unsigned long long inlen,const unsigned char *k)
|
||||
{
|
||||
unsigned char correct[32];
|
||||
crypto_auth_hmacsha256(correct,in,inlen,k);
|
||||
return crypto_verify_32(h,correct) | (-(h == correct)) |
|
||||
sodium_memcmp(correct,h,32);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#include "crypto_auth_hmacsha512.h"
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha512_bytes(void) {
|
||||
return crypto_auth_hmacsha512_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha512_keybytes(void) {
|
||||
return crypto_auth_hmacsha512_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha512_statebytes(void) {
|
||||
return sizeof(crypto_auth_hmacsha512_state);
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
|
||||
/*-
|
||||
* 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 "crypto_auth_hmacsha512.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 *) pad, sizeof pad);
|
||||
sodium_memzero((void *) khash, sizeof khash);
|
||||
|
||||
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, sizeof ihash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_auth_hmacsha512(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
crypto_auth_hmacsha512_state state;
|
||||
|
||||
crypto_auth_hmacsha512_init(&state, k, crypto_auth_hmacsha512_KEYBYTES);
|
||||
crypto_auth_hmacsha512_update(&state, in, inlen);
|
||||
crypto_auth_hmacsha512_final(&state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#include "crypto_auth_hmacsha512.h"
|
||||
#include "crypto_verify_64.h"
|
||||
#include "utils.h"
|
||||
|
||||
int crypto_auth_hmacsha512_verify(const unsigned char *h, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
unsigned char correct[64];
|
||||
crypto_auth_hmacsha512(correct,in,inlen,k);
|
||||
return crypto_verify_64(h,correct) | (-(h == correct)) |
|
||||
sodium_memcmp(correct,h,64);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#include "crypto_auth_hmacsha512256.h"
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha512256_bytes(void) {
|
||||
return crypto_auth_hmacsha512256_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha512256_keybytes(void) {
|
||||
return crypto_auth_hmacsha512256_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_auth_hmacsha512256_statebytes(void) {
|
||||
return sizeof(crypto_auth_hmacsha512256_state);
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
|
||||
#include "crypto_auth_hmacsha512256.h"
|
||||
#include "crypto_auth_hmacsha512.h"
|
||||
#include "crypto_hash_sha512.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
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_hmacsha512256(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_hmacsha512256_KEYBYTES);
|
||||
crypto_auth_hmacsha512256_update(&state, in, inlen);
|
||||
crypto_auth_hmacsha512256_final(&state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#include "crypto_auth_hmacsha512256.h"
|
||||
#include "crypto_verify_32.h"
|
||||
#include "utils.h"
|
||||
|
||||
int crypto_auth_hmacsha512256_verify(const unsigned char *h,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned char correct[32];
|
||||
crypto_auth_hmacsha512256(correct,in,inlen,k);
|
||||
return crypto_verify_32(h,correct) | (-(h == correct)) |
|
||||
sodium_memcmp(correct,h,32);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
|
||||
#include "crypto_box.h"
|
||||
|
||||
size_t
|
||||
crypto_box_seedbytes(void)
|
||||
{
|
||||
return crypto_box_SEEDBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_publickeybytes(void)
|
||||
{
|
||||
return crypto_box_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_secretkeybytes(void)
|
||||
{
|
||||
return crypto_box_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_beforenmbytes(void)
|
||||
{
|
||||
return crypto_box_BEFORENMBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_noncebytes(void)
|
||||
{
|
||||
return crypto_box_NONCEBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_zerobytes(void)
|
||||
{
|
||||
return crypto_box_ZEROBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_boxzerobytes(void)
|
||||
{
|
||||
return crypto_box_BOXZEROBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_macbytes(void)
|
||||
{
|
||||
return crypto_box_MACBYTES;
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_box_primitive(void)
|
||||
{
|
||||
return crypto_box_PRIMITIVE;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_seed_keypair(unsigned char *pk, unsigned char *sk,
|
||||
const unsigned char *seed)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305_seed_keypair(pk, sk, seed);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_keypair(unsigned char *pk, unsigned char *sk)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_beforenm(unsigned char *k, const unsigned char *pk,
|
||||
const unsigned char *sk)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_afternm(unsigned char *c, const unsigned char *m,
|
||||
unsigned long long mlen, const unsigned char *n,
|
||||
const unsigned char *k)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305_afternm(c, m, mlen, n, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_open_afternm(unsigned char *m, const unsigned char *c,
|
||||
unsigned long long clen, const unsigned char *n,
|
||||
const unsigned char *k)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box(unsigned char *c, const unsigned char *m,
|
||||
unsigned long long mlen, const unsigned char *n,
|
||||
const unsigned char *pk, const unsigned char *sk)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305(c, m, mlen, n, pk, sk);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_open(unsigned char *m, const unsigned char *c,
|
||||
unsigned long long clen, const unsigned char *n,
|
||||
const unsigned char *pk, const unsigned char *sk)
|
||||
{
|
||||
return crypto_box_curve25519xsalsa20poly1305_open(m, c, clen, n, pk, sk);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_box.h"
|
||||
#include "crypto_secretbox.h"
|
||||
#include "utils.h"
|
||||
|
||||
int
|
||||
crypto_box_detached_afternm(unsigned char *c, unsigned char *mac,
|
||||
const unsigned char *m, unsigned long long mlen,
|
||||
const unsigned char *n, const unsigned char *k)
|
||||
{
|
||||
return crypto_secretbox_detached(c, mac, m, mlen, n, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_detached(unsigned char *c, unsigned char *mac,
|
||||
const unsigned char *m, unsigned long long mlen,
|
||||
const unsigned char *n, const unsigned char *pk,
|
||||
const unsigned char *sk)
|
||||
{
|
||||
unsigned char k[crypto_box_BEFORENMBYTES];
|
||||
int ret;
|
||||
|
||||
(void) sizeof(int[crypto_box_BEFORENMBYTES >=
|
||||
crypto_secretbox_KEYBYTES ? 1 : -1]);
|
||||
if (crypto_box_beforenm(k, pk, sk) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = crypto_box_detached_afternm(c, mac, m, mlen, n, k);
|
||||
sodium_memzero(k, sizeof k);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_easy_afternm(unsigned char *c, const unsigned char *m,
|
||||
unsigned long long mlen, const unsigned char *n,
|
||||
const unsigned char *k)
|
||||
{
|
||||
if (mlen > SIZE_MAX - crypto_box_MACBYTES) {
|
||||
return -1;
|
||||
}
|
||||
return crypto_box_detached_afternm(c + crypto_box_MACBYTES, c, m, mlen, n,
|
||||
k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_easy(unsigned char *c, const unsigned char *m,
|
||||
unsigned long long mlen, const unsigned char *n,
|
||||
const unsigned char *pk, const unsigned char *sk)
|
||||
{
|
||||
if (mlen > SIZE_MAX - crypto_box_MACBYTES) {
|
||||
return -1;
|
||||
}
|
||||
return crypto_box_detached(c + crypto_box_MACBYTES, c, m, mlen, n,
|
||||
pk, sk);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_open_detached_afternm(unsigned char *m, const unsigned char *c,
|
||||
const unsigned char *mac,
|
||||
unsigned long long clen, const unsigned char *n,
|
||||
const unsigned char *k)
|
||||
{
|
||||
return crypto_secretbox_open_detached(m, c, mac, clen, n, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_open_detached(unsigned char *m, const unsigned char *c,
|
||||
const unsigned char *mac,
|
||||
unsigned long long clen, const unsigned char *n,
|
||||
const unsigned char *pk, const unsigned char *sk)
|
||||
{
|
||||
unsigned char k[crypto_box_BEFORENMBYTES];
|
||||
int ret;
|
||||
|
||||
if (crypto_box_beforenm(k, pk, sk) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = crypto_box_open_detached_afternm(m, c, mac, clen, n, k);
|
||||
sodium_memzero(k, sizeof k);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_open_easy_afternm(unsigned char *m, const unsigned char *c,
|
||||
unsigned long long clen, const unsigned char *n,
|
||||
const unsigned char *k)
|
||||
{
|
||||
if (clen < crypto_box_MACBYTES) {
|
||||
return -1;
|
||||
}
|
||||
return crypto_box_open_detached_afternm(m, c + crypto_box_MACBYTES, c,
|
||||
clen - crypto_box_MACBYTES,
|
||||
n, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_open_easy(unsigned char *m, const unsigned char *c,
|
||||
unsigned long long clen, const unsigned char *n,
|
||||
const unsigned char *pk, const unsigned char *sk)
|
||||
{
|
||||
if (clen < crypto_box_MACBYTES) {
|
||||
return -1;
|
||||
}
|
||||
return crypto_box_open_detached(m, c + crypto_box_MACBYTES, c,
|
||||
clen - crypto_box_MACBYTES,
|
||||
n, pk, sk);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_box.h"
|
||||
#include "crypto_generichash.h"
|
||||
#include "utils.h"
|
||||
|
||||
static int
|
||||
_crypto_box_seal_nonce(unsigned char *nonce,
|
||||
const unsigned char *pk1, const unsigned char *pk2)
|
||||
{
|
||||
crypto_generichash_state st;
|
||||
|
||||
crypto_generichash_init(&st, NULL, 0U, crypto_box_NONCEBYTES);
|
||||
crypto_generichash_update(&st, pk1, crypto_box_PUBLICKEYBYTES);
|
||||
crypto_generichash_update(&st, pk2, crypto_box_PUBLICKEYBYTES);
|
||||
crypto_generichash_final(&st, nonce, crypto_box_NONCEBYTES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_seal(unsigned char *c, const unsigned char *m,
|
||||
unsigned long long mlen, const unsigned char *pk)
|
||||
{
|
||||
unsigned char nonce[crypto_box_NONCEBYTES];
|
||||
unsigned char epk[crypto_box_PUBLICKEYBYTES];
|
||||
unsigned char esk[crypto_box_SECRETKEYBYTES];
|
||||
int ret;
|
||||
|
||||
if (crypto_box_keypair(epk, esk) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
memcpy(c, epk, crypto_box_PUBLICKEYBYTES);
|
||||
_crypto_box_seal_nonce(nonce, epk, pk);
|
||||
ret = crypto_box_easy(c + crypto_box_PUBLICKEYBYTES, m, mlen,
|
||||
nonce, pk, esk);
|
||||
sodium_memzero(esk, sizeof esk);
|
||||
sodium_memzero(epk, sizeof epk);
|
||||
sodium_memzero(nonce, sizeof nonce);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_box_seal_open(unsigned char *m, const unsigned char *c,
|
||||
unsigned long long clen,
|
||||
const unsigned char *pk, const unsigned char *sk)
|
||||
{
|
||||
unsigned char nonce[crypto_box_NONCEBYTES];
|
||||
|
||||
if (clen < crypto_box_SEALBYTES) {
|
||||
return -1;
|
||||
}
|
||||
_crypto_box_seal_nonce(nonce, c, pk);
|
||||
|
||||
(void) sizeof(int[crypto_box_PUBLICKEYBYTES < crypto_box_SEALBYTES ? 1 : -1]);
|
||||
return crypto_box_open_easy(m, c + crypto_box_PUBLICKEYBYTES,
|
||||
clen - crypto_box_PUBLICKEYBYTES,
|
||||
nonce, c, sk);
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_sealbytes(void)
|
||||
{
|
||||
return crypto_box_SEALBYTES;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
#include "crypto_box_curve25519xsalsa20poly1305.h"
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_seedbytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_SEEDBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_publickeybytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_secretkeybytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_beforenmbytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_noncebytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_NONCEBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_zerobytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_ZEROBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_boxzerobytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_box_curve25519xsalsa20poly1305_macbytes(void) {
|
||||
return crypto_box_curve25519xsalsa20poly1305_MACBYTES;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#include "crypto_box_curve25519xsalsa20poly1305.h"
|
||||
#include "crypto_secretbox_xsalsa20poly1305.h"
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305_afternm(
|
||||
unsigned char *c,
|
||||
const unsigned char *m,unsigned long long mlen,
|
||||
const unsigned char *n,
|
||||
const unsigned char *k
|
||||
)
|
||||
{
|
||||
return crypto_secretbox_xsalsa20poly1305(c,m,mlen,n,k);
|
||||
}
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305_open_afternm(
|
||||
unsigned char *m,
|
||||
const unsigned char *c,unsigned long long clen,
|
||||
const unsigned char *n,
|
||||
const unsigned char *k
|
||||
)
|
||||
{
|
||||
return crypto_secretbox_xsalsa20poly1305_open(m,c,clen,n,k);
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#include "crypto_box_curve25519xsalsa20poly1305.h"
|
||||
#include "crypto_core_hsalsa20.h"
|
||||
#include "crypto_scalarmult_curve25519.h"
|
||||
|
||||
static const unsigned char n[16] = {0};
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305_beforenm(
|
||||
unsigned char *k,
|
||||
const unsigned char *pk,
|
||||
const unsigned char *sk
|
||||
)
|
||||
{
|
||||
unsigned char s[32];
|
||||
if (crypto_scalarmult_curve25519(s,sk,pk) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return crypto_core_hsalsa20(k,n,s,NULL);
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#include "crypto_box_curve25519xsalsa20poly1305.h"
|
||||
#include "utils.h"
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305(
|
||||
unsigned char *c,
|
||||
const unsigned char *m,unsigned long long mlen,
|
||||
const unsigned char *n,
|
||||
const unsigned char *pk,
|
||||
const unsigned char *sk
|
||||
)
|
||||
{
|
||||
unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
|
||||
int ret;
|
||||
|
||||
if (crypto_box_curve25519xsalsa20poly1305_beforenm(k,pk,sk) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = crypto_box_curve25519xsalsa20poly1305_afternm(c,m,mlen,n,k);
|
||||
sodium_memzero(k, sizeof k);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305_open(
|
||||
unsigned char *m,
|
||||
const unsigned char *c,unsigned long long clen,
|
||||
const unsigned char *n,
|
||||
const unsigned char *pk,
|
||||
const unsigned char *sk
|
||||
)
|
||||
{
|
||||
unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
|
||||
int ret;
|
||||
|
||||
if (crypto_box_curve25519xsalsa20poly1305_beforenm(k,pk,sk) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = crypto_box_curve25519xsalsa20poly1305_open_afternm(m,c,clen,n,k);
|
||||
sodium_memzero(k, sizeof k);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_box_curve25519xsalsa20poly1305.h"
|
||||
#include "crypto_hash_sha512.h"
|
||||
#include "crypto_scalarmult_curve25519.h"
|
||||
#include "randombytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305_seed_keypair(
|
||||
unsigned char *pk,
|
||||
unsigned char *sk,
|
||||
const unsigned char *seed
|
||||
)
|
||||
{
|
||||
unsigned char hash[64];
|
||||
crypto_hash_sha512(hash,seed,32);
|
||||
memmove(sk,hash,32);
|
||||
sodium_memzero(hash, sizeof hash);
|
||||
return crypto_scalarmult_curve25519_base(pk,sk);
|
||||
}
|
||||
|
||||
int crypto_box_curve25519xsalsa20poly1305_keypair(
|
||||
unsigned char *pk,
|
||||
unsigned char *sk
|
||||
)
|
||||
{
|
||||
randombytes_buf(sk,32);
|
||||
return crypto_scalarmult_curve25519_base(pk,sk);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,40 @@
|
||||
{
|
||||
{ 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
|
||||
{ -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
|
||||
{ -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
|
||||
},
|
||||
{
|
||||
{ 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
|
||||
{ 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
|
||||
{ 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
|
||||
},
|
||||
{
|
||||
{ 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
|
||||
{ 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
|
||||
{ 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
|
||||
},
|
||||
{
|
||||
{ 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
|
||||
{ -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
|
||||
{ 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
|
||||
},
|
||||
{
|
||||
{ -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 },
|
||||
{ -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 },
|
||||
{ 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 },
|
||||
},
|
||||
{
|
||||
{ -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 },
|
||||
{ 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 },
|
||||
{ 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 },
|
||||
},
|
||||
{
|
||||
{ -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 },
|
||||
{ -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 },
|
||||
{ -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 },
|
||||
},
|
||||
{
|
||||
{ -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 },
|
||||
{ -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 },
|
||||
{ -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 },
|
||||
},
|
||||
+2242
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,86 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core_hchacha20.h"
|
||||
#include "crypto_core_hchacha20.h"
|
||||
#include "private/common.h"
|
||||
|
||||
int
|
||||
crypto_core_hchacha20(unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *k, const unsigned char *c)
|
||||
{
|
||||
int i;
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
|
||||
if (c == NULL) {
|
||||
x0 = U32C(0x61707865);
|
||||
x1 = U32C(0x3320646e);
|
||||
x2 = U32C(0x79622d32);
|
||||
x3 = U32C(0x6b206574);
|
||||
} else {
|
||||
x0 = LOAD32_LE(c + 0);
|
||||
x1 = LOAD32_LE(c + 4);
|
||||
x2 = LOAD32_LE(c + 8);
|
||||
x3 = LOAD32_LE(c + 12);
|
||||
}
|
||||
x4 = LOAD32_LE(k + 0);
|
||||
x5 = LOAD32_LE(k + 4);
|
||||
x6 = LOAD32_LE(k + 8);
|
||||
x7 = LOAD32_LE(k + 12);
|
||||
x8 = LOAD32_LE(k + 16);
|
||||
x9 = LOAD32_LE(k + 20);
|
||||
x10 = LOAD32_LE(k + 24);
|
||||
x11 = LOAD32_LE(k + 28);
|
||||
x12 = LOAD32_LE(in + 0);
|
||||
x13 = LOAD32_LE(in + 4);
|
||||
x14 = LOAD32_LE(in + 8);
|
||||
x15 = LOAD32_LE(in + 12);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
QUARTERROUND(x0, x4, x8, x12);
|
||||
QUARTERROUND(x1, x5, x9, x13);
|
||||
QUARTERROUND(x2, x6, x10, x14);
|
||||
QUARTERROUND(x3, x7, x11, x15);
|
||||
QUARTERROUND(x0, x5, x10, x15);
|
||||
QUARTERROUND(x1, x6, x11, x12);
|
||||
QUARTERROUND(x2, x7, x8, x13);
|
||||
QUARTERROUND(x3, x4, x9, x14);
|
||||
}
|
||||
|
||||
STORE32_LE(out + 0, x0);
|
||||
STORE32_LE(out + 4, x1);
|
||||
STORE32_LE(out + 8, x2);
|
||||
STORE32_LE(out + 12, x3);
|
||||
STORE32_LE(out + 16, x12);
|
||||
STORE32_LE(out + 20, x13);
|
||||
STORE32_LE(out + 24, x14);
|
||||
STORE32_LE(out + 28, x15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hchacha20_outputbytes(void)
|
||||
{
|
||||
return crypto_core_hchacha20_OUTPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hchacha20_inputbytes(void)
|
||||
{
|
||||
return crypto_core_hchacha20_INPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hchacha20_keybytes(void)
|
||||
{
|
||||
return crypto_core_hchacha20_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hchacha20_constbytes(void)
|
||||
{
|
||||
return crypto_core_hchacha20_CONSTBYTES;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef core_hchacha20_H
|
||||
#define core_hchacha20_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define U8C(v) (v##U)
|
||||
#define U32C(v) (v##U)
|
||||
|
||||
#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
|
||||
#define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
|
||||
|
||||
#define ROTL32(v, n) (U32V((v) << (n)) | ((v) >> (32 - (n))))
|
||||
|
||||
#define ROTATE(v, c) (ROTL32(v, c))
|
||||
#define XOR(v, w) ((v) ^ (w))
|
||||
#define PLUS(v, w) (U32V((v) + (w)))
|
||||
|
||||
#define QUARTERROUND(a, b, c, d) \
|
||||
do { \
|
||||
a = PLUS(a, b); d = ROTATE(XOR(d, a), 16); \
|
||||
c = PLUS(c, d); b = ROTATE(XOR(b, c), 12); \
|
||||
a = PLUS(a, b); d = ROTATE(XOR(d, a), 8); \
|
||||
c = PLUS(c, d); b = ROTATE(XOR(b, c), 7); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
#include "crypto_core_hsalsa20.h"
|
||||
|
||||
size_t
|
||||
crypto_core_hsalsa20_outputbytes(void) {
|
||||
return crypto_core_hsalsa20_OUTPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hsalsa20_inputbytes(void) {
|
||||
return crypto_core_hsalsa20_INPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hsalsa20_keybytes(void) {
|
||||
return crypto_core_hsalsa20_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_hsalsa20_constbytes(void) {
|
||||
return crypto_core_hsalsa20_CONSTBYTES;
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
version 20080912
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_core_hsalsa20.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#define ROUNDS 20
|
||||
#define U32C(v) (v##U)
|
||||
|
||||
static uint32_t rotate(uint32_t u,int c)
|
||||
{
|
||||
return (u << c) | (u >> (32 - c));
|
||||
}
|
||||
|
||||
int crypto_core_hsalsa20(
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
const unsigned char *k,
|
||||
const unsigned char *c
|
||||
)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
int i;
|
||||
|
||||
if (c == NULL) {
|
||||
x0 = U32C(0x61707865);
|
||||
x5 = U32C(0x3320646e);
|
||||
x10 = U32C(0x79622d32);
|
||||
x15 = U32C(0x6b206574);
|
||||
} else {
|
||||
x0 = LOAD32_LE(c + 0);
|
||||
x5 = LOAD32_LE(c + 4);
|
||||
x10 = LOAD32_LE(c + 8);
|
||||
x15 = LOAD32_LE(c + 12);
|
||||
}
|
||||
x1 = LOAD32_LE(k + 0);
|
||||
x2 = LOAD32_LE(k + 4);
|
||||
x3 = LOAD32_LE(k + 8);
|
||||
x4 = LOAD32_LE(k + 12);
|
||||
x11 = LOAD32_LE(k + 16);
|
||||
x12 = LOAD32_LE(k + 20);
|
||||
x13 = LOAD32_LE(k + 24);
|
||||
x14 = LOAD32_LE(k + 28);
|
||||
x6 = LOAD32_LE(in + 0);
|
||||
x7 = LOAD32_LE(in + 4);
|
||||
x8 = LOAD32_LE(in + 8);
|
||||
x9 = LOAD32_LE(in + 12);
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
x4 ^= rotate( x0+x12, 7);
|
||||
x8 ^= rotate( x4+ x0, 9);
|
||||
x12 ^= rotate( x8+ x4,13);
|
||||
x0 ^= rotate(x12+ x8,18);
|
||||
x9 ^= rotate( x5+ x1, 7);
|
||||
x13 ^= rotate( x9+ x5, 9);
|
||||
x1 ^= rotate(x13+ x9,13);
|
||||
x5 ^= rotate( x1+x13,18);
|
||||
x14 ^= rotate(x10+ x6, 7);
|
||||
x2 ^= rotate(x14+x10, 9);
|
||||
x6 ^= rotate( x2+x14,13);
|
||||
x10 ^= rotate( x6+ x2,18);
|
||||
x3 ^= rotate(x15+x11, 7);
|
||||
x7 ^= rotate( x3+x15, 9);
|
||||
x11 ^= rotate( x7+ x3,13);
|
||||
x15 ^= rotate(x11+ x7,18);
|
||||
x1 ^= rotate( x0+ x3, 7);
|
||||
x2 ^= rotate( x1+ x0, 9);
|
||||
x3 ^= rotate( x2+ x1,13);
|
||||
x0 ^= rotate( x3+ x2,18);
|
||||
x6 ^= rotate( x5+ x4, 7);
|
||||
x7 ^= rotate( x6+ x5, 9);
|
||||
x4 ^= rotate( x7+ x6,13);
|
||||
x5 ^= rotate( x4+ x7,18);
|
||||
x11 ^= rotate(x10+ x9, 7);
|
||||
x8 ^= rotate(x11+x10, 9);
|
||||
x9 ^= rotate( x8+x11,13);
|
||||
x10 ^= rotate( x9+ x8,18);
|
||||
x12 ^= rotate(x15+x14, 7);
|
||||
x13 ^= rotate(x12+x15, 9);
|
||||
x14 ^= rotate(x13+x12,13);
|
||||
x15 ^= rotate(x14+x13,18);
|
||||
}
|
||||
|
||||
STORE32_LE(out + 0,x0);
|
||||
STORE32_LE(out + 4,x5);
|
||||
STORE32_LE(out + 8,x10);
|
||||
STORE32_LE(out + 12,x15);
|
||||
STORE32_LE(out + 16,x6);
|
||||
STORE32_LE(out + 20,x7);
|
||||
STORE32_LE(out + 24,x8);
|
||||
STORE32_LE(out + 28,x9);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "crypto_core_salsa20.h"
|
||||
|
||||
size_t
|
||||
crypto_core_salsa20_outputbytes(void) {
|
||||
return crypto_core_salsa20_OUTPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa20_inputbytes(void) {
|
||||
return crypto_core_salsa20_INPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa20_keybytes(void) {
|
||||
return crypto_core_salsa20_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa20_constbytes(void) {
|
||||
return crypto_core_salsa20_CONSTBYTES;
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
version 20080912
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_core_salsa20.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#define ROUNDS 20
|
||||
#define U32C(v) (v##U)
|
||||
|
||||
static uint32_t rotate(uint32_t u,int c)
|
||||
{
|
||||
return (u << c) | (u >> (32 - c));
|
||||
}
|
||||
|
||||
int crypto_core_salsa20(
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
const unsigned char *k,
|
||||
const unsigned char *c
|
||||
)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
|
||||
int i;
|
||||
|
||||
if (c == NULL) {
|
||||
j0 = x0 = U32C(0x61707865);
|
||||
j5 = x5 = U32C(0x3320646e);
|
||||
j10 = x10 = U32C(0x79622d32);
|
||||
j15 = x15 = U32C(0x6b206574);
|
||||
} else {
|
||||
j0 = x0 = LOAD32_LE(c + 0);
|
||||
j5 = x5 = LOAD32_LE(c + 4);
|
||||
j10 = x10 = LOAD32_LE(c + 8);
|
||||
j15 = x15 = LOAD32_LE(c + 12);
|
||||
}
|
||||
j1 = x1 = LOAD32_LE(k + 0);
|
||||
j2 = x2 = LOAD32_LE(k + 4);
|
||||
j3 = x3 = LOAD32_LE(k + 8);
|
||||
j4 = x4 = LOAD32_LE(k + 12);
|
||||
j6 = x6 = LOAD32_LE(in + 0);
|
||||
j7 = x7 = LOAD32_LE(in + 4);
|
||||
j8 = x8 = LOAD32_LE(in + 8);
|
||||
j9 = x9 = LOAD32_LE(in + 12);
|
||||
j11 = x11 = LOAD32_LE(k + 16);
|
||||
j12 = x12 = LOAD32_LE(k + 20);
|
||||
j13 = x13 = LOAD32_LE(k + 24);
|
||||
j14 = x14 = LOAD32_LE(k + 28);
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
x4 ^= rotate( x0+x12, 7);
|
||||
x8 ^= rotate( x4+ x0, 9);
|
||||
x12 ^= rotate( x8+ x4,13);
|
||||
x0 ^= rotate(x12+ x8,18);
|
||||
x9 ^= rotate( x5+ x1, 7);
|
||||
x13 ^= rotate( x9+ x5, 9);
|
||||
x1 ^= rotate(x13+ x9,13);
|
||||
x5 ^= rotate( x1+x13,18);
|
||||
x14 ^= rotate(x10+ x6, 7);
|
||||
x2 ^= rotate(x14+x10, 9);
|
||||
x6 ^= rotate( x2+x14,13);
|
||||
x10 ^= rotate( x6+ x2,18);
|
||||
x3 ^= rotate(x15+x11, 7);
|
||||
x7 ^= rotate( x3+x15, 9);
|
||||
x11 ^= rotate( x7+ x3,13);
|
||||
x15 ^= rotate(x11+ x7,18);
|
||||
x1 ^= rotate( x0+ x3, 7);
|
||||
x2 ^= rotate( x1+ x0, 9);
|
||||
x3 ^= rotate( x2+ x1,13);
|
||||
x0 ^= rotate( x3+ x2,18);
|
||||
x6 ^= rotate( x5+ x4, 7);
|
||||
x7 ^= rotate( x6+ x5, 9);
|
||||
x4 ^= rotate( x7+ x6,13);
|
||||
x5 ^= rotate( x4+ x7,18);
|
||||
x11 ^= rotate(x10+ x9, 7);
|
||||
x8 ^= rotate(x11+x10, 9);
|
||||
x9 ^= rotate( x8+x11,13);
|
||||
x10 ^= rotate( x9+ x8,18);
|
||||
x12 ^= rotate(x15+x14, 7);
|
||||
x13 ^= rotate(x12+x15, 9);
|
||||
x14 ^= rotate(x13+x12,13);
|
||||
x15 ^= rotate(x14+x13,18);
|
||||
}
|
||||
|
||||
x0 += j0;
|
||||
x1 += j1;
|
||||
x2 += j2;
|
||||
x3 += j3;
|
||||
x4 += j4;
|
||||
x5 += j5;
|
||||
x6 += j6;
|
||||
x7 += j7;
|
||||
x8 += j8;
|
||||
x9 += j9;
|
||||
x10 += j10;
|
||||
x11 += j11;
|
||||
x12 += j12;
|
||||
x13 += j13;
|
||||
x14 += j14;
|
||||
x15 += j15;
|
||||
|
||||
STORE32_LE(out + 0,x0);
|
||||
STORE32_LE(out + 4,x1);
|
||||
STORE32_LE(out + 8,x2);
|
||||
STORE32_LE(out + 12,x3);
|
||||
STORE32_LE(out + 16,x4);
|
||||
STORE32_LE(out + 20,x5);
|
||||
STORE32_LE(out + 24,x6);
|
||||
STORE32_LE(out + 28,x7);
|
||||
STORE32_LE(out + 32,x8);
|
||||
STORE32_LE(out + 36,x9);
|
||||
STORE32_LE(out + 40,x10);
|
||||
STORE32_LE(out + 44,x11);
|
||||
STORE32_LE(out + 48,x12);
|
||||
STORE32_LE(out + 52,x13);
|
||||
STORE32_LE(out + 56,x14);
|
||||
STORE32_LE(out + 60,x15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
#include "crypto_core_salsa2012.h"
|
||||
|
||||
size_t
|
||||
crypto_core_salsa2012_outputbytes(void) {
|
||||
return crypto_core_salsa2012_OUTPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa2012_inputbytes(void) {
|
||||
return crypto_core_salsa2012_INPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa2012_keybytes(void) {
|
||||
return crypto_core_salsa2012_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa2012_constbytes(void) {
|
||||
return crypto_core_salsa2012_CONSTBYTES;
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
version 20080913
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_core_salsa2012.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#define ROUNDS 12
|
||||
#define U32C(v) (v##U)
|
||||
|
||||
static uint32_t rotate(uint32_t u,int c)
|
||||
{
|
||||
return (u << c) | (u >> (32 - c));
|
||||
}
|
||||
|
||||
int crypto_core_salsa2012(
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
const unsigned char *k,
|
||||
const unsigned char *c
|
||||
)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
|
||||
int i;
|
||||
|
||||
if (c == NULL) {
|
||||
j0 = x0 = U32C(0x61707865);
|
||||
j5 = x5 = U32C(0x3320646e);
|
||||
j10 = x10 = U32C(0x79622d32);
|
||||
j15 = x15 = U32C(0x6b206574);
|
||||
} else {
|
||||
j0 = x0 = LOAD32_LE(c + 0);
|
||||
j5 = x5 = LOAD32_LE(c + 4);
|
||||
j10 = x10 = LOAD32_LE(c + 8);
|
||||
j15 = x15 = LOAD32_LE(c + 12);
|
||||
}
|
||||
j1 = x1 = LOAD32_LE(k + 0);
|
||||
j2 = x2 = LOAD32_LE(k + 4);
|
||||
j3 = x3 = LOAD32_LE(k + 8);
|
||||
j4 = x4 = LOAD32_LE(k + 12);
|
||||
j6 = x6 = LOAD32_LE(in + 0);
|
||||
j7 = x7 = LOAD32_LE(in + 4);
|
||||
j8 = x8 = LOAD32_LE(in + 8);
|
||||
j9 = x9 = LOAD32_LE(in + 12);
|
||||
j11 = x11 = LOAD32_LE(k + 16);
|
||||
j12 = x12 = LOAD32_LE(k + 20);
|
||||
j13 = x13 = LOAD32_LE(k + 24);
|
||||
j14 = x14 = LOAD32_LE(k + 28);
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
x4 ^= rotate( x0+x12, 7);
|
||||
x8 ^= rotate( x4+ x0, 9);
|
||||
x12 ^= rotate( x8+ x4,13);
|
||||
x0 ^= rotate(x12+ x8,18);
|
||||
x9 ^= rotate( x5+ x1, 7);
|
||||
x13 ^= rotate( x9+ x5, 9);
|
||||
x1 ^= rotate(x13+ x9,13);
|
||||
x5 ^= rotate( x1+x13,18);
|
||||
x14 ^= rotate(x10+ x6, 7);
|
||||
x2 ^= rotate(x14+x10, 9);
|
||||
x6 ^= rotate( x2+x14,13);
|
||||
x10 ^= rotate( x6+ x2,18);
|
||||
x3 ^= rotate(x15+x11, 7);
|
||||
x7 ^= rotate( x3+x15, 9);
|
||||
x11 ^= rotate( x7+ x3,13);
|
||||
x15 ^= rotate(x11+ x7,18);
|
||||
x1 ^= rotate( x0+ x3, 7);
|
||||
x2 ^= rotate( x1+ x0, 9);
|
||||
x3 ^= rotate( x2+ x1,13);
|
||||
x0 ^= rotate( x3+ x2,18);
|
||||
x6 ^= rotate( x5+ x4, 7);
|
||||
x7 ^= rotate( x6+ x5, 9);
|
||||
x4 ^= rotate( x7+ x6,13);
|
||||
x5 ^= rotate( x4+ x7,18);
|
||||
x11 ^= rotate(x10+ x9, 7);
|
||||
x8 ^= rotate(x11+x10, 9);
|
||||
x9 ^= rotate( x8+x11,13);
|
||||
x10 ^= rotate( x9+ x8,18);
|
||||
x12 ^= rotate(x15+x14, 7);
|
||||
x13 ^= rotate(x12+x15, 9);
|
||||
x14 ^= rotate(x13+x12,13);
|
||||
x15 ^= rotate(x14+x13,18);
|
||||
}
|
||||
|
||||
x0 += j0;
|
||||
x1 += j1;
|
||||
x2 += j2;
|
||||
x3 += j3;
|
||||
x4 += j4;
|
||||
x5 += j5;
|
||||
x6 += j6;
|
||||
x7 += j7;
|
||||
x8 += j8;
|
||||
x9 += j9;
|
||||
x10 += j10;
|
||||
x11 += j11;
|
||||
x12 += j12;
|
||||
x13 += j13;
|
||||
x14 += j14;
|
||||
x15 += j15;
|
||||
|
||||
STORE32_LE(out + 0,x0);
|
||||
STORE32_LE(out + 4,x1);
|
||||
STORE32_LE(out + 8,x2);
|
||||
STORE32_LE(out + 12,x3);
|
||||
STORE32_LE(out + 16,x4);
|
||||
STORE32_LE(out + 20,x5);
|
||||
STORE32_LE(out + 24,x6);
|
||||
STORE32_LE(out + 28,x7);
|
||||
STORE32_LE(out + 32,x8);
|
||||
STORE32_LE(out + 36,x9);
|
||||
STORE32_LE(out + 40,x10);
|
||||
STORE32_LE(out + 44,x11);
|
||||
STORE32_LE(out + 48,x12);
|
||||
STORE32_LE(out + 52,x13);
|
||||
STORE32_LE(out + 56,x14);
|
||||
STORE32_LE(out + 60,x15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
#include "crypto_core_salsa208.h"
|
||||
|
||||
size_t
|
||||
crypto_core_salsa208_outputbytes(void) {
|
||||
return crypto_core_salsa208_OUTPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa208_inputbytes(void) {
|
||||
return crypto_core_salsa208_INPUTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa208_keybytes(void) {
|
||||
return crypto_core_salsa208_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_core_salsa208_constbytes(void) {
|
||||
return crypto_core_salsa208_CONSTBYTES;
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
version 20080913
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_core_salsa208.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#define ROUNDS 8
|
||||
#define U32C(v) (v##U)
|
||||
|
||||
static uint32_t rotate(uint32_t u,int c)
|
||||
{
|
||||
return (u << c) | (u >> (32 - c));
|
||||
}
|
||||
|
||||
int crypto_core_salsa208(
|
||||
unsigned char *out,
|
||||
const unsigned char *in,
|
||||
const unsigned char *k,
|
||||
const unsigned char *c
|
||||
)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
|
||||
int i;
|
||||
|
||||
if (c == NULL) {
|
||||
j0 = x0 = U32C(0x61707865);
|
||||
j5 = x5 = U32C(0x3320646e);
|
||||
j10 = x10 = U32C(0x79622d32);
|
||||
j15 = x15 = U32C(0x6b206574);
|
||||
} else {
|
||||
j0 = x0 = LOAD32_LE(c + 0);
|
||||
j5 = x5 = LOAD32_LE(c + 4);
|
||||
j10 = x10 = LOAD32_LE(c + 8);
|
||||
j15 = x15 = LOAD32_LE(c + 12);
|
||||
}
|
||||
j1 = x1 = LOAD32_LE(k + 0);
|
||||
j2 = x2 = LOAD32_LE(k + 4);
|
||||
j3 = x3 = LOAD32_LE(k + 8);
|
||||
j4 = x4 = LOAD32_LE(k + 12);
|
||||
j6 = x6 = LOAD32_LE(in + 0);
|
||||
j7 = x7 = LOAD32_LE(in + 4);
|
||||
j8 = x8 = LOAD32_LE(in + 8);
|
||||
j9 = x9 = LOAD32_LE(in + 12);
|
||||
j11 = x11 = LOAD32_LE(k + 16);
|
||||
j12 = x12 = LOAD32_LE(k + 20);
|
||||
j13 = x13 = LOAD32_LE(k + 24);
|
||||
j14 = x14 = LOAD32_LE(k + 28);
|
||||
|
||||
for (i = ROUNDS;i > 0;i -= 2) {
|
||||
x4 ^= rotate( x0+x12, 7);
|
||||
x8 ^= rotate( x4+ x0, 9);
|
||||
x12 ^= rotate( x8+ x4,13);
|
||||
x0 ^= rotate(x12+ x8,18);
|
||||
x9 ^= rotate( x5+ x1, 7);
|
||||
x13 ^= rotate( x9+ x5, 9);
|
||||
x1 ^= rotate(x13+ x9,13);
|
||||
x5 ^= rotate( x1+x13,18);
|
||||
x14 ^= rotate(x10+ x6, 7);
|
||||
x2 ^= rotate(x14+x10, 9);
|
||||
x6 ^= rotate( x2+x14,13);
|
||||
x10 ^= rotate( x6+ x2,18);
|
||||
x3 ^= rotate(x15+x11, 7);
|
||||
x7 ^= rotate( x3+x15, 9);
|
||||
x11 ^= rotate( x7+ x3,13);
|
||||
x15 ^= rotate(x11+ x7,18);
|
||||
x1 ^= rotate( x0+ x3, 7);
|
||||
x2 ^= rotate( x1+ x0, 9);
|
||||
x3 ^= rotate( x2+ x1,13);
|
||||
x0 ^= rotate( x3+ x2,18);
|
||||
x6 ^= rotate( x5+ x4, 7);
|
||||
x7 ^= rotate( x6+ x5, 9);
|
||||
x4 ^= rotate( x7+ x6,13);
|
||||
x5 ^= rotate( x4+ x7,18);
|
||||
x11 ^= rotate(x10+ x9, 7);
|
||||
x8 ^= rotate(x11+x10, 9);
|
||||
x9 ^= rotate( x8+x11,13);
|
||||
x10 ^= rotate( x9+ x8,18);
|
||||
x12 ^= rotate(x15+x14, 7);
|
||||
x13 ^= rotate(x12+x15, 9);
|
||||
x14 ^= rotate(x13+x12,13);
|
||||
x15 ^= rotate(x14+x13,18);
|
||||
}
|
||||
|
||||
x0 += j0;
|
||||
x1 += j1;
|
||||
x2 += j2;
|
||||
x3 += j3;
|
||||
x4 += j4;
|
||||
x5 += j5;
|
||||
x6 += j6;
|
||||
x7 += j7;
|
||||
x8 += j8;
|
||||
x9 += j9;
|
||||
x10 += j10;
|
||||
x11 += j11;
|
||||
x12 += j12;
|
||||
x13 += j13;
|
||||
x14 += j14;
|
||||
x15 += j15;
|
||||
|
||||
STORE32_LE(out + 0,x0);
|
||||
STORE32_LE(out + 4,x1);
|
||||
STORE32_LE(out + 8,x2);
|
||||
STORE32_LE(out + 12,x3);
|
||||
STORE32_LE(out + 16,x4);
|
||||
STORE32_LE(out + 20,x5);
|
||||
STORE32_LE(out + 24,x6);
|
||||
STORE32_LE(out + 28,x7);
|
||||
STORE32_LE(out + 32,x8);
|
||||
STORE32_LE(out + 36,x9);
|
||||
STORE32_LE(out + 40,x10);
|
||||
STORE32_LE(out + 44,x11);
|
||||
STORE32_LE(out + 48,x12);
|
||||
STORE32_LE(out + 52,x13);
|
||||
STORE32_LE(out + 56,x14);
|
||||
STORE32_LE(out + 60,x15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#include "crypto_generichash_blake2b.h"
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_bytes_min(void) {
|
||||
return crypto_generichash_blake2b_BYTES_MIN;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_bytes_max(void) {
|
||||
return crypto_generichash_blake2b_BYTES_MAX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_bytes(void) {
|
||||
return crypto_generichash_blake2b_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_keybytes_min(void) {
|
||||
return crypto_generichash_blake2b_KEYBYTES_MIN;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_keybytes_max(void) {
|
||||
return crypto_generichash_blake2b_KEYBYTES_MAX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_keybytes(void) {
|
||||
return crypto_generichash_blake2b_KEYBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_saltbytes(void) {
|
||||
return crypto_generichash_blake2b_SALTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_personalbytes(void) {
|
||||
return crypto_generichash_blake2b_PERSONALBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_blake2b_statebytes(void)
|
||||
{
|
||||
return (sizeof(crypto_generichash_blake2b_state) + (size_t) 63U)
|
||||
& ~(size_t) 63U;
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#ifndef blake2_impl_H
|
||||
#define blake2_impl_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
static inline uint32_t rotl32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w << c ) | ( w >> ( 32 - c ) );
|
||||
}
|
||||
|
||||
static inline uint64_t rotl64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w << c ) | ( w >> ( 64 - c ) );
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static inline uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
/* prevents compiler optimizing out memset() */
|
||||
static inline void secure_zero_memory( void *v, size_t n )
|
||||
{
|
||||
sodium_memzero(v, n);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
All code is triple-licensed under the
|
||||
[CC0](http://creativecommons.org/publicdomain/zero/1.0), the
|
||||
[OpenSSL Licence](https://www.openssl.org/source/license.html), or
|
||||
the [Apache Public License 2.0](http://www.apache.org/licenses/LICENSE-2.0),
|
||||
at your choosing.
|
||||
*/
|
||||
|
||||
#ifndef blake2_H
|
||||
#define blake2_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto_generichash_blake2b.h"
|
||||
#include "export.h"
|
||||
|
||||
#define blake2b_init_param crypto_generichash_blake2b__init_param
|
||||
#define blake2b_init crypto_generichash_blake2b__init
|
||||
#define blake2b_init_salt_personal crypto_generichash_blake2b__init_salt_personal
|
||||
#define blake2b_init_key crypto_generichash_blake2b__init_key
|
||||
#define blake2b_init_key_salt_personal crypto_generichash_blake2b__init_key_salt_personal
|
||||
#define blake2b_update crypto_generichash_blake2b__update
|
||||
#define blake2b_final crypto_generichash_blake2b__final
|
||||
#define blake2b crypto_generichash_blake2b__blake2b
|
||||
#define blake2b_salt_personal crypto_generichash_blake2b__blake2b_salt_personal
|
||||
#define blake2b_pick_best_implementation crypto_generichash_blake2b__pick_best_implementation
|
||||
|
||||
enum blake2b_constant
|
||||
{
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# pragma pack(1)
|
||||
#else
|
||||
# pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
typedef struct blake2b_param_
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint8_t leaf_length[4]; /* 8 */
|
||||
uint8_t node_offset[8]; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
} blake2b_param;
|
||||
|
||||
typedef crypto_generichash_blake2b_state blake2b_state;
|
||||
|
||||
#if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# pragma pack()
|
||||
#else
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
/* Streaming API */
|
||||
int blake2b_init( blake2b_state *S, const uint8_t outlen );
|
||||
int blake2b_init_salt_personal( blake2b_state *S, const uint8_t outlen,
|
||||
const void *personal, const void *salt );
|
||||
int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
|
||||
int blake2b_init_key_salt_personal( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen,
|
||||
const void *salt, const void *personal );
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||
int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen );
|
||||
int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen );
|
||||
|
||||
/* Simple API */
|
||||
int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
|
||||
int blake2b_salt_personal( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen, const void *salt, const void *personal );
|
||||
|
||||
typedef int ( *blake2b_compress_fn )( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] );
|
||||
int blake2b_pick_best_implementation(void);
|
||||
int blake2b_compress_ref( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] );
|
||||
int blake2b_compress_ssse3( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] );
|
||||
int blake2b_compress_sse41( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] );
|
||||
int blake2b_compress_avx2( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] );
|
||||
|
||||
#endif
|
||||
Generated
+45
@@ -0,0 +1,45 @@
|
||||
|
||||
#define BLAKE2_USE_SSSE3
|
||||
#define BLAKE2_USE_SSE41
|
||||
#define BLAKE2_USE_AVX2
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64)) && _MSC_VER >= 1700)
|
||||
|
||||
#pragma GCC target("sse2")
|
||||
#pragma GCC target("ssse3")
|
||||
#pragma GCC target("sse4.1")
|
||||
#pragma GCC target("avx2")
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
#include "blake2b-compress-avx2.h"
|
||||
|
||||
CRYPTO_ALIGN(64) static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
int blake2b_compress_avx2( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
__m256i a = LOADU(&S->h[0]);
|
||||
__m256i b = LOADU(&S->h[4]);
|
||||
BLAKE2B_COMPRESS_V1(a, b, block, S->t[0], S->t[1], S->f[0], S->f[1]);
|
||||
STOREU(&S->h[0], a);
|
||||
STOREU(&S->h[4], b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Generated
+123
@@ -0,0 +1,123 @@
|
||||
|
||||
#ifndef blake2b_compress_avx2_H
|
||||
#define blake2b_compress_avx2_H
|
||||
|
||||
#define LOAD128(p) _mm_load_si128((__m128i *)(p))
|
||||
#define STORE128(p, r) _mm_store_si128((__m128i *)(p), r)
|
||||
|
||||
#define LOADU128(p) _mm_loadu_si128((__m128i *)(p))
|
||||
#define STOREU128(p, r) _mm_storeu_si128((__m128i *)(p), r)
|
||||
|
||||
#define LOAD(p) _mm256_load_si256((__m256i *)(p))
|
||||
#define STORE(p, r) _mm256_store_si256((__m256i *)(p), r)
|
||||
|
||||
#define LOADU(p) _mm256_loadu_si256((__m256i *)(p))
|
||||
#define STOREU(p, r) _mm256_storeu_si256((__m256i *)(p), r)
|
||||
|
||||
static inline uint64_t LOADU64(const void *p) {
|
||||
uint64_t v;
|
||||
memcpy(&v, p, sizeof v);
|
||||
return v;
|
||||
}
|
||||
|
||||
#define ROTATE16 _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, \
|
||||
2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9)
|
||||
|
||||
#define ROTATE24 _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, \
|
||||
3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10)
|
||||
|
||||
#define ADD(a, b) _mm256_add_epi64(a, b)
|
||||
#define SUB(a, b) _mm256_sub_epi64(a, b)
|
||||
|
||||
#define XOR(a, b) _mm256_xor_si256(a, b)
|
||||
#define AND(a, b) _mm256_and_si256(a, b)
|
||||
#define OR(a, b) _mm256_or_si256(a, b)
|
||||
|
||||
#define ROT32(x) _mm256_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1))
|
||||
#define ROT24(x) _mm256_shuffle_epi8((x), ROTATE24)
|
||||
#define ROT16(x) _mm256_shuffle_epi8((x), ROTATE16)
|
||||
#define ROT63(x) _mm256_or_si256(_mm256_srli_epi64((x), 63), ADD((x), (x)))
|
||||
|
||||
#define BLAKE2B_G1_V1(a, b, c, d, m) do { \
|
||||
a = ADD(a, m); \
|
||||
a = ADD(a, b); d = XOR(d, a); d = ROT32(d); \
|
||||
c = ADD(c, d); b = XOR(b, c); b = ROT24(b); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_G2_V1(a, b, c, d, m) do { \
|
||||
a = ADD(a, m); \
|
||||
a = ADD(a, b); d = XOR(d, a); d = ROT16(d); \
|
||||
c = ADD(c, d); b = XOR(b, c); b = ROT63(b); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_DIAG_V1(a, b, c, d) do { \
|
||||
d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(2,1,0,3)); \
|
||||
c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(1,0,3,2)); \
|
||||
b = _mm256_permute4x64_epi64(b, _MM_SHUFFLE(0,3,2,1)); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_UNDIAG_V1(a, b, c, d) do { \
|
||||
d = _mm256_permute4x64_epi64(d, _MM_SHUFFLE(0,3,2,1)); \
|
||||
c = _mm256_permute4x64_epi64(c, _MM_SHUFFLE(1,0,3,2)); \
|
||||
b = _mm256_permute4x64_epi64(b, _MM_SHUFFLE(2,1,0,3)); \
|
||||
} while(0)
|
||||
|
||||
#include "blake2b-load-avx2.h"
|
||||
|
||||
#define BLAKE2B_ROUND_V1(a, b, c, d, r, m) do { \
|
||||
__m256i b0; \
|
||||
BLAKE2B_LOAD_MSG_ ##r ##_1(b0); \
|
||||
BLAKE2B_G1_V1(a, b, c, d, b0); \
|
||||
BLAKE2B_LOAD_MSG_ ##r ##_2(b0); \
|
||||
BLAKE2B_G2_V1(a, b, c, d, b0); \
|
||||
BLAKE2B_DIAG_V1(a, b, c, d); \
|
||||
BLAKE2B_LOAD_MSG_ ##r ##_3(b0); \
|
||||
BLAKE2B_G1_V1(a, b, c, d, b0); \
|
||||
BLAKE2B_LOAD_MSG_ ##r ##_4(b0); \
|
||||
BLAKE2B_G2_V1(a, b, c, d, b0); \
|
||||
BLAKE2B_UNDIAG_V1(a, b, c, d); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_ROUNDS_V1(a, b, c, d, m) do { \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 0, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 1, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 2, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 3, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 4, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 5, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 6, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 7, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 8, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 9, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 10, (m)); \
|
||||
BLAKE2B_ROUND_V1(a, b, c, d, 11, (m)); \
|
||||
} while(0)
|
||||
|
||||
#define DECLARE_MESSAGE_WORDS(m) \
|
||||
const __m256i m0 = _mm256_broadcastsi128_si256(LOADU128((m) + 0)); \
|
||||
const __m256i m1 = _mm256_broadcastsi128_si256(LOADU128((m) + 16)); \
|
||||
const __m256i m2 = _mm256_broadcastsi128_si256(LOADU128((m) + 32)); \
|
||||
const __m256i m3 = _mm256_broadcastsi128_si256(LOADU128((m) + 48)); \
|
||||
const __m256i m4 = _mm256_broadcastsi128_si256(LOADU128((m) + 64)); \
|
||||
const __m256i m5 = _mm256_broadcastsi128_si256(LOADU128((m) + 80)); \
|
||||
const __m256i m6 = _mm256_broadcastsi128_si256(LOADU128((m) + 96)); \
|
||||
const __m256i m7 = _mm256_broadcastsi128_si256(LOADU128((m) + 112)); \
|
||||
__m256i t0, t1;
|
||||
|
||||
#define BLAKE2B_COMPRESS_V1(a, b, m, t0, t1, f0, f1) do { \
|
||||
DECLARE_MESSAGE_WORDS(m) \
|
||||
const __m256i iv0 = a; \
|
||||
const __m256i iv1 = b; \
|
||||
__m256i c = LOAD(&blake2b_IV[0]); \
|
||||
__m256i d = XOR( \
|
||||
LOAD(&blake2b_IV[4]), \
|
||||
_mm256_set_epi64x(f1, f0, t1, t0) \
|
||||
); \
|
||||
BLAKE2B_ROUNDS_V1(a, b, c, d, m); \
|
||||
a = XOR(a, c); \
|
||||
b = XOR(b, d); \
|
||||
a = XOR(a, iv0); \
|
||||
b = XOR(b, iv1); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
#include "private/common.h"
|
||||
|
||||
CRYPTO_ALIGN(64) static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
static const uint8_t blake2b_sigma[12][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
|
||||
};
|
||||
|
||||
int blake2b_compress_ref( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
uint64_t m[16];
|
||||
uint64_t v[16];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 16; ++i )
|
||||
m[i] = LOAD64_LE( block + i * sizeof( m[i] ) );
|
||||
|
||||
for( i = 0; i < 8; ++i )
|
||||
v[i] = S->h[i];
|
||||
|
||||
v[ 8] = blake2b_IV[0];
|
||||
v[ 9] = blake2b_IV[1];
|
||||
v[10] = blake2b_IV[2];
|
||||
v[11] = blake2b_IV[3];
|
||||
v[12] = S->t[0] ^ blake2b_IV[4];
|
||||
v[13] = S->t[1] ^ blake2b_IV[5];
|
||||
v[14] = S->f[0] ^ blake2b_IV[6];
|
||||
v[15] = S->f[1] ^ blake2b_IV[7];
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while(0)
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
ROUND( 10 );
|
||||
ROUND( 11 );
|
||||
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
return 0;
|
||||
}
|
||||
Generated
+80
@@ -0,0 +1,80 @@
|
||||
|
||||
#define BLAKE2_USE_SSSE3
|
||||
#define BLAKE2_USE_SSE41
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
|
||||
#pragma GCC target("sse2")
|
||||
#pragma GCC target("ssse3")
|
||||
#pragma GCC target("sse4.1")
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
#include <smmintrin.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
#include "blake2b-compress-sse41.h"
|
||||
|
||||
CRYPTO_ALIGN(64) static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
int blake2b_compress_sse41( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
__m128i row1l, row1h;
|
||||
__m128i row2l, row2h;
|
||||
__m128i row3l, row3h;
|
||||
__m128i row4l, row4h;
|
||||
__m128i b0, b1;
|
||||
__m128i t0, t1;
|
||||
const __m128i r16 = _mm_setr_epi8( 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9 );
|
||||
const __m128i r24 = _mm_setr_epi8( 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10 );
|
||||
const __m128i m0 = LOADU( block + 00 );
|
||||
const __m128i m1 = LOADU( block + 16 );
|
||||
const __m128i m2 = LOADU( block + 32 );
|
||||
const __m128i m3 = LOADU( block + 48 );
|
||||
const __m128i m4 = LOADU( block + 64 );
|
||||
const __m128i m5 = LOADU( block + 80 );
|
||||
const __m128i m6 = LOADU( block + 96 );
|
||||
const __m128i m7 = LOADU( block + 112 );
|
||||
row1l = LOADU( &S->h[0] );
|
||||
row1h = LOADU( &S->h[2] );
|
||||
row2l = LOADU( &S->h[4] );
|
||||
row2h = LOADU( &S->h[6] );
|
||||
row3l = LOADU( &blake2b_IV[0] );
|
||||
row3h = LOADU( &blake2b_IV[2] );
|
||||
row4l = _mm_xor_si128( LOADU( &blake2b_IV[4] ), LOADU( &S->t[0] ) );
|
||||
row4h = _mm_xor_si128( LOADU( &blake2b_IV[6] ), LOADU( &S->f[0] ) );
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
ROUND( 10 );
|
||||
ROUND( 11 );
|
||||
row1l = _mm_xor_si128( row3l, row1l );
|
||||
row1h = _mm_xor_si128( row3h, row1h );
|
||||
STOREU( &S->h[0], _mm_xor_si128( LOADU( &S->h[0] ), row1l ) );
|
||||
STOREU( &S->h[2], _mm_xor_si128( LOADU( &S->h[2] ), row1h ) );
|
||||
row2l = _mm_xor_si128( row4l, row2l );
|
||||
row2h = _mm_xor_si128( row4h, row2h );
|
||||
STOREU( &S->h[4], _mm_xor_si128( LOADU( &S->h[4] ), row2l ) );
|
||||
STOREU( &S->h[6], _mm_xor_si128( LOADU( &S->h[6] ), row2h ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Generated
+97
@@ -0,0 +1,97 @@
|
||||
|
||||
#ifndef blake2b_compress_sse41_H
|
||||
#define blake2b_compress_sse41_H
|
||||
|
||||
#define LOADU(p) _mm_loadu_si128( (const __m128i *)(const void *)(p) )
|
||||
#define STOREU(p,r) _mm_storeu_si128((__m128i *)(void *)(p), r)
|
||||
|
||||
#define _mm_roti_epi64(x, c) \
|
||||
(-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \
|
||||
: (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \
|
||||
: (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \
|
||||
: (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \
|
||||
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c))))
|
||||
|
||||
#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
|
||||
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
|
||||
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
|
||||
\
|
||||
row4l = _mm_xor_si128(row4l, row1l); \
|
||||
row4h = _mm_xor_si128(row4h, row1h); \
|
||||
\
|
||||
row4l = _mm_roti_epi64(row4l, -32); \
|
||||
row4h = _mm_roti_epi64(row4h, -32); \
|
||||
\
|
||||
row3l = _mm_add_epi64(row3l, row4l); \
|
||||
row3h = _mm_add_epi64(row3h, row4h); \
|
||||
\
|
||||
row2l = _mm_xor_si128(row2l, row3l); \
|
||||
row2h = _mm_xor_si128(row2h, row3h); \
|
||||
\
|
||||
row2l = _mm_roti_epi64(row2l, -24); \
|
||||
row2h = _mm_roti_epi64(row2h, -24); \
|
||||
|
||||
#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
|
||||
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
|
||||
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
|
||||
\
|
||||
row4l = _mm_xor_si128(row4l, row1l); \
|
||||
row4h = _mm_xor_si128(row4h, row1h); \
|
||||
\
|
||||
row4l = _mm_roti_epi64(row4l, -16); \
|
||||
row4h = _mm_roti_epi64(row4h, -16); \
|
||||
\
|
||||
row3l = _mm_add_epi64(row3l, row4l); \
|
||||
row3h = _mm_add_epi64(row3h, row4h); \
|
||||
\
|
||||
row2l = _mm_xor_si128(row2l, row3l); \
|
||||
row2h = _mm_xor_si128(row2h, row3h); \
|
||||
\
|
||||
row2l = _mm_roti_epi64(row2l, -63); \
|
||||
row2h = _mm_roti_epi64(row2h, -63); \
|
||||
|
||||
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
|
||||
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
|
||||
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
|
||||
row2l = t0; \
|
||||
row2h = t1; \
|
||||
\
|
||||
t0 = row3l; \
|
||||
row3l = row3h; \
|
||||
row3h = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
|
||||
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
|
||||
row4l = t1; \
|
||||
row4h = t0;
|
||||
|
||||
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
|
||||
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
|
||||
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
|
||||
row2l = t0; \
|
||||
row2h = t1; \
|
||||
\
|
||||
t0 = row3l; \
|
||||
row3l = row3h; \
|
||||
row3h = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
|
||||
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
|
||||
row4l = t1; \
|
||||
row4h = t0;
|
||||
|
||||
#include "blake2b-load-sse41.h"
|
||||
|
||||
#define ROUND(r) \
|
||||
LOAD_MSG_ ##r ##_1(b0, b1); \
|
||||
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
LOAD_MSG_ ##r ##_2(b0, b1); \
|
||||
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
|
||||
LOAD_MSG_ ##r ##_3(b0, b1); \
|
||||
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
LOAD_MSG_ ##r ##_4(b0, b1); \
|
||||
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
|
||||
|
||||
#endif
|
||||
Generated
+87
@@ -0,0 +1,87 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64)))
|
||||
|
||||
#pragma GCC target("sse2")
|
||||
#pragma GCC target("ssse3")
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h> /* for _mm_set_epi64x */
|
||||
#endif
|
||||
#include <emmintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
#include "blake2b-compress-ssse3.h"
|
||||
|
||||
CRYPTO_ALIGN(64) static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
int blake2b_compress_ssse3( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
__m128i row1l, row1h;
|
||||
__m128i row2l, row2h;
|
||||
__m128i row3l, row3h;
|
||||
__m128i row4l, row4h;
|
||||
__m128i b0, b1;
|
||||
__m128i t0, t1;
|
||||
const __m128i r16 = _mm_setr_epi8( 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9 );
|
||||
const __m128i r24 = _mm_setr_epi8( 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10 );
|
||||
const uint64_t m0 = ( ( uint64_t * )block )[ 0];
|
||||
const uint64_t m1 = ( ( uint64_t * )block )[ 1];
|
||||
const uint64_t m2 = ( ( uint64_t * )block )[ 2];
|
||||
const uint64_t m3 = ( ( uint64_t * )block )[ 3];
|
||||
const uint64_t m4 = ( ( uint64_t * )block )[ 4];
|
||||
const uint64_t m5 = ( ( uint64_t * )block )[ 5];
|
||||
const uint64_t m6 = ( ( uint64_t * )block )[ 6];
|
||||
const uint64_t m7 = ( ( uint64_t * )block )[ 7];
|
||||
const uint64_t m8 = ( ( uint64_t * )block )[ 8];
|
||||
const uint64_t m9 = ( ( uint64_t * )block )[ 9];
|
||||
const uint64_t m10 = ( ( uint64_t * )block )[10];
|
||||
const uint64_t m11 = ( ( uint64_t * )block )[11];
|
||||
const uint64_t m12 = ( ( uint64_t * )block )[12];
|
||||
const uint64_t m13 = ( ( uint64_t * )block )[13];
|
||||
const uint64_t m14 = ( ( uint64_t * )block )[14];
|
||||
const uint64_t m15 = ( ( uint64_t * )block )[15];
|
||||
|
||||
row1l = LOADU( &S->h[0] );
|
||||
row1h = LOADU( &S->h[2] );
|
||||
row2l = LOADU( &S->h[4] );
|
||||
row2h = LOADU( &S->h[6] );
|
||||
row3l = LOADU( &blake2b_IV[0] );
|
||||
row3h = LOADU( &blake2b_IV[2] );
|
||||
row4l = _mm_xor_si128( LOADU( &blake2b_IV[4] ), LOADU( &S->t[0] ) );
|
||||
row4h = _mm_xor_si128( LOADU( &blake2b_IV[6] ), LOADU( &S->f[0] ) );
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
ROUND( 10 );
|
||||
ROUND( 11 );
|
||||
row1l = _mm_xor_si128( row3l, row1l );
|
||||
row1h = _mm_xor_si128( row3h, row1h );
|
||||
STOREU( &S->h[0], _mm_xor_si128( LOADU( &S->h[0] ), row1l ) );
|
||||
STOREU( &S->h[2], _mm_xor_si128( LOADU( &S->h[2] ), row1h ) );
|
||||
row2l = _mm_xor_si128( row4l, row2l );
|
||||
row2h = _mm_xor_si128( row4h, row2h );
|
||||
STOREU( &S->h[4], _mm_xor_si128( LOADU( &S->h[4] ), row2l ) );
|
||||
STOREU( &S->h[6], _mm_xor_si128( LOADU( &S->h[6] ), row2h ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Generated
+97
@@ -0,0 +1,97 @@
|
||||
|
||||
#ifndef blake2b_compress_ssse3_H
|
||||
#define blake2b_compress_ssse3_H
|
||||
|
||||
#define LOADU(p) _mm_loadu_si128( (const __m128i *)(const void *)(p) )
|
||||
#define STOREU(p,r) _mm_storeu_si128((__m128i *)(void *)(p), r)
|
||||
|
||||
#define _mm_roti_epi64(x, c) \
|
||||
(-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \
|
||||
: (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \
|
||||
: (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \
|
||||
: (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \
|
||||
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c))))
|
||||
|
||||
#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
|
||||
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
|
||||
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
|
||||
\
|
||||
row4l = _mm_xor_si128(row4l, row1l); \
|
||||
row4h = _mm_xor_si128(row4h, row1h); \
|
||||
\
|
||||
row4l = _mm_roti_epi64(row4l, -32); \
|
||||
row4h = _mm_roti_epi64(row4h, -32); \
|
||||
\
|
||||
row3l = _mm_add_epi64(row3l, row4l); \
|
||||
row3h = _mm_add_epi64(row3h, row4h); \
|
||||
\
|
||||
row2l = _mm_xor_si128(row2l, row3l); \
|
||||
row2h = _mm_xor_si128(row2h, row3h); \
|
||||
\
|
||||
row2l = _mm_roti_epi64(row2l, -24); \
|
||||
row2h = _mm_roti_epi64(row2h, -24); \
|
||||
|
||||
#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
|
||||
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
|
||||
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
|
||||
\
|
||||
row4l = _mm_xor_si128(row4l, row1l); \
|
||||
row4h = _mm_xor_si128(row4h, row1h); \
|
||||
\
|
||||
row4l = _mm_roti_epi64(row4l, -16); \
|
||||
row4h = _mm_roti_epi64(row4h, -16); \
|
||||
\
|
||||
row3l = _mm_add_epi64(row3l, row4l); \
|
||||
row3h = _mm_add_epi64(row3h, row4h); \
|
||||
\
|
||||
row2l = _mm_xor_si128(row2l, row3l); \
|
||||
row2h = _mm_xor_si128(row2h, row3h); \
|
||||
\
|
||||
row2l = _mm_roti_epi64(row2l, -63); \
|
||||
row2h = _mm_roti_epi64(row2h, -63); \
|
||||
|
||||
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
|
||||
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
|
||||
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
|
||||
row2l = t0; \
|
||||
row2h = t1; \
|
||||
\
|
||||
t0 = row3l; \
|
||||
row3l = row3h; \
|
||||
row3h = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
|
||||
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
|
||||
row4l = t1; \
|
||||
row4h = t0;
|
||||
|
||||
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
|
||||
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
|
||||
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
|
||||
row2l = t0; \
|
||||
row2h = t1; \
|
||||
\
|
||||
t0 = row3l; \
|
||||
row3l = row3h; \
|
||||
row3h = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
|
||||
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
|
||||
row4l = t1; \
|
||||
row4h = t0;
|
||||
|
||||
#include "blake2b-load-sse2.h"
|
||||
|
||||
#define ROUND(r) \
|
||||
LOAD_MSG_ ##r ##_1(b0, b1); \
|
||||
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
LOAD_MSG_ ##r ##_2(b0, b1); \
|
||||
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
|
||||
LOAD_MSG_ ##r ##_3(b0, b1); \
|
||||
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
LOAD_MSG_ ##r ##_4(b0, b1); \
|
||||
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
|
||||
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
|
||||
|
||||
#endif
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
#ifndef blake2b_load_avx2_H
|
||||
#define blake2b_load_avx2_H
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_0_1(b0) do { \
|
||||
t0 = _mm256_unpacklo_epi64(m0, m1); \
|
||||
t1 = _mm256_unpacklo_epi64(m2, m3); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_0_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m0, m1); \
|
||||
t1 = _mm256_unpackhi_epi64(m2, m3); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_0_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m4, m5); \
|
||||
t1 = _mm256_unpacklo_epi64(m6, m7); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_0_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m4, m5); \
|
||||
t1 = _mm256_unpackhi_epi64(m6, m7); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_1_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m7, m2); \
|
||||
t1 = _mm256_unpackhi_epi64(m4, m6); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_1_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m5, m4); \
|
||||
t1 = _mm256_alignr_epi8(m3, m7, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_1_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \
|
||||
t1 = _mm256_unpackhi_epi64(m5, m2); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_1_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m6, m1); \
|
||||
t1 = _mm256_unpackhi_epi64(m3, m1); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_2_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_alignr_epi8(m6, m5, 8); \
|
||||
t1 = _mm256_unpackhi_epi64(m2, m7); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_2_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m4, m0); \
|
||||
t1 = _mm256_blend_epi32(m6, m1, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_2_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m1, m5, 0x33); \
|
||||
t1 = _mm256_unpackhi_epi64(m3, m4); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_2_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m7, m3); \
|
||||
t1 = _mm256_alignr_epi8(m2, m0, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_3_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m3, m1); \
|
||||
t1 = _mm256_unpackhi_epi64(m6, m5); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_3_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m4, m0); \
|
||||
t1 = _mm256_unpacklo_epi64(m6, m7); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_3_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m2, m1, 0x33); \
|
||||
t1 = _mm256_blend_epi32(m7, m2, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_3_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m3, m5); \
|
||||
t1 = _mm256_unpacklo_epi64(m0, m4); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_4_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m4, m2); \
|
||||
t1 = _mm256_unpacklo_epi64(m1, m5); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_4_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m3, m0, 0x33); \
|
||||
t1 = _mm256_blend_epi32(m7, m2, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_4_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m5, m7, 0x33); \
|
||||
t1 = _mm256_blend_epi32(m1, m3, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_4_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_alignr_epi8(m6, m0, 8); \
|
||||
t1 = _mm256_blend_epi32(m6, m4, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_5_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m1, m3); \
|
||||
t1 = _mm256_unpacklo_epi64(m0, m4); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_5_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m6, m5); \
|
||||
t1 = _mm256_unpackhi_epi64(m5, m1); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_5_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m3, m2, 0x33); \
|
||||
t1 = _mm256_unpackhi_epi64(m7, m0); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_5_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m6, m2); \
|
||||
t1 = _mm256_blend_epi32(m4, m7, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_6_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m0, m6, 0x33); \
|
||||
t1 = _mm256_unpacklo_epi64(m7, m2); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_6_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m2, m7); \
|
||||
t1 = _mm256_alignr_epi8(m5, m6, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_6_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m0, m3); \
|
||||
t1 = _mm256_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2)); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_6_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m3, m1); \
|
||||
t1 = _mm256_blend_epi32(m5, m1, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_7_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m6, m3); \
|
||||
t1 = _mm256_blend_epi32(m1, m6, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_7_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_alignr_epi8(m7, m5, 8); \
|
||||
t1 = _mm256_unpackhi_epi64(m0, m4); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_7_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m2, m7); \
|
||||
t1 = _mm256_unpacklo_epi64(m4, m1); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_7_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m0, m2); \
|
||||
t1 = _mm256_unpacklo_epi64(m3, m5); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_8_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m3, m7); \
|
||||
t1 = _mm256_alignr_epi8(m0, m5, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_8_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m7, m4); \
|
||||
t1 = _mm256_alignr_epi8(m4, m1, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_8_3(b0) \
|
||||
do { \
|
||||
t0 = m6; \
|
||||
t1 = _mm256_alignr_epi8(m5, m0, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_8_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_blend_epi32(m3, m1, 0x33); \
|
||||
t1 = m2; \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_9_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m5, m4); \
|
||||
t1 = _mm256_unpackhi_epi64(m3, m0); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_9_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m1, m2); \
|
||||
t1 = _mm256_blend_epi32(m2, m3, 0x33); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_9_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m7, m4); \
|
||||
t1 = _mm256_unpackhi_epi64(m1, m6); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_9_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_alignr_epi8(m7, m5, 8); \
|
||||
t1 = _mm256_unpacklo_epi64(m6, m0); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_10_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m0, m1); \
|
||||
t1 = _mm256_unpacklo_epi64(m2, m3); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_10_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m0, m1); \
|
||||
t1 = _mm256_unpackhi_epi64(m2, m3); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_10_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m4, m5); \
|
||||
t1 = _mm256_unpacklo_epi64(m6, m7); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_10_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpackhi_epi64(m4, m5); \
|
||||
t1 = _mm256_unpackhi_epi64(m6, m7); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_11_1(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m7, m2); \
|
||||
t1 = _mm256_unpackhi_epi64(m4, m6); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_11_2(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m5, m4); \
|
||||
t1 = _mm256_alignr_epi8(m3, m7, 8); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_11_3(b0) \
|
||||
do { \
|
||||
t0 = _mm256_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \
|
||||
t1 = _mm256_unpackhi_epi64(m5, m2); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#define BLAKE2B_LOAD_MSG_11_4(b0) \
|
||||
do { \
|
||||
t0 = _mm256_unpacklo_epi64(m6, m1); \
|
||||
t1 = _mm256_unpackhi_epi64(m3, m1); \
|
||||
b0 = _mm256_blend_epi32(t0, t1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - optimized C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#ifndef blake2b_load_sse2_H
|
||||
#define blake2b_load_sse2_H
|
||||
|
||||
#define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)
|
||||
#define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)
|
||||
#define LOAD_MSG_0_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12)
|
||||
#define LOAD_MSG_0_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13)
|
||||
#define LOAD_MSG_1_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9)
|
||||
#define LOAD_MSG_1_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15)
|
||||
#define LOAD_MSG_1_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11)
|
||||
#define LOAD_MSG_1_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7)
|
||||
#define LOAD_MSG_2_1(b0, b1) b0 = _mm_set_epi64x(m12, m11); b1 = _mm_set_epi64x(m15, m5)
|
||||
#define LOAD_MSG_2_2(b0, b1) b0 = _mm_set_epi64x(m0, m8); b1 = _mm_set_epi64x(m13, m2)
|
||||
#define LOAD_MSG_2_3(b0, b1) b0 = _mm_set_epi64x(m3, m10); b1 = _mm_set_epi64x(m9, m7)
|
||||
#define LOAD_MSG_2_4(b0, b1) b0 = _mm_set_epi64x(m6, m14); b1 = _mm_set_epi64x(m4, m1)
|
||||
#define LOAD_MSG_3_1(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m13)
|
||||
#define LOAD_MSG_3_2(b0, b1) b0 = _mm_set_epi64x(m1, m9); b1 = _mm_set_epi64x(m14, m12)
|
||||
#define LOAD_MSG_3_3(b0, b1) b0 = _mm_set_epi64x(m5, m2); b1 = _mm_set_epi64x(m15, m4)
|
||||
#define LOAD_MSG_3_4(b0, b1) b0 = _mm_set_epi64x(m10, m6); b1 = _mm_set_epi64x(m8, m0)
|
||||
#define LOAD_MSG_4_1(b0, b1) b0 = _mm_set_epi64x(m5, m9); b1 = _mm_set_epi64x(m10, m2)
|
||||
#define LOAD_MSG_4_2(b0, b1) b0 = _mm_set_epi64x(m7, m0); b1 = _mm_set_epi64x(m15, m4)
|
||||
#define LOAD_MSG_4_3(b0, b1) b0 = _mm_set_epi64x(m11, m14); b1 = _mm_set_epi64x(m3, m6)
|
||||
#define LOAD_MSG_4_4(b0, b1) b0 = _mm_set_epi64x(m12, m1); b1 = _mm_set_epi64x(m13, m8)
|
||||
#define LOAD_MSG_5_1(b0, b1) b0 = _mm_set_epi64x(m6, m2); b1 = _mm_set_epi64x(m8, m0)
|
||||
#define LOAD_MSG_5_2(b0, b1) b0 = _mm_set_epi64x(m10, m12); b1 = _mm_set_epi64x(m3, m11)
|
||||
#define LOAD_MSG_5_3(b0, b1) b0 = _mm_set_epi64x(m7, m4); b1 = _mm_set_epi64x(m1, m15)
|
||||
#define LOAD_MSG_5_4(b0, b1) b0 = _mm_set_epi64x(m5, m13); b1 = _mm_set_epi64x(m9, m14)
|
||||
#define LOAD_MSG_6_1(b0, b1) b0 = _mm_set_epi64x(m1, m12); b1 = _mm_set_epi64x(m4, m14)
|
||||
#define LOAD_MSG_6_2(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m10, m13)
|
||||
#define LOAD_MSG_6_3(b0, b1) b0 = _mm_set_epi64x(m6, m0); b1 = _mm_set_epi64x(m8, m9)
|
||||
#define LOAD_MSG_6_4(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m2)
|
||||
#define LOAD_MSG_7_1(b0, b1) b0 = _mm_set_epi64x(m7, m13); b1 = _mm_set_epi64x(m3, m12)
|
||||
#define LOAD_MSG_7_2(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m9, m1)
|
||||
#define LOAD_MSG_7_3(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m2, m8)
|
||||
#define LOAD_MSG_7_4(b0, b1) b0 = _mm_set_epi64x(m4, m0); b1 = _mm_set_epi64x(m10, m6)
|
||||
#define LOAD_MSG_8_1(b0, b1) b0 = _mm_set_epi64x(m14, m6); b1 = _mm_set_epi64x(m0, m11)
|
||||
#define LOAD_MSG_8_2(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m8, m3)
|
||||
#define LOAD_MSG_8_3(b0, b1) b0 = _mm_set_epi64x(m13, m12); b1 = _mm_set_epi64x(m10, m1)
|
||||
#define LOAD_MSG_8_4(b0, b1) b0 = _mm_set_epi64x(m7, m2); b1 = _mm_set_epi64x(m5, m4)
|
||||
#define LOAD_MSG_9_1(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m1, m7)
|
||||
#define LOAD_MSG_9_2(b0, b1) b0 = _mm_set_epi64x(m4, m2); b1 = _mm_set_epi64x(m5, m6)
|
||||
#define LOAD_MSG_9_3(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m13, m3)
|
||||
#define LOAD_MSG_9_4(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m0, m12)
|
||||
#define LOAD_MSG_10_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)
|
||||
#define LOAD_MSG_10_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)
|
||||
#define LOAD_MSG_10_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12)
|
||||
#define LOAD_MSG_10_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13)
|
||||
#define LOAD_MSG_11_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9)
|
||||
#define LOAD_MSG_11_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15)
|
||||
#define LOAD_MSG_11_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11)
|
||||
#define LOAD_MSG_11_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7)
|
||||
|
||||
#endif
|
||||
+400
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - optimized C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#ifndef blake2b_load_sse41_H
|
||||
#define blake2b_load_sse41_H
|
||||
|
||||
#define LOAD_MSG_0_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m0, m1); \
|
||||
b1 = _mm_unpacklo_epi64(m2, m3); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_0_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m0, m1); \
|
||||
b1 = _mm_unpackhi_epi64(m2, m3); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_0_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m4, m5); \
|
||||
b1 = _mm_unpacklo_epi64(m6, m7); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_0_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m4, m5); \
|
||||
b1 = _mm_unpackhi_epi64(m6, m7); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_1_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m7, m2); \
|
||||
b1 = _mm_unpackhi_epi64(m4, m6); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_1_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m5, m4); \
|
||||
b1 = _mm_alignr_epi8(m3, m7, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_1_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \
|
||||
b1 = _mm_unpackhi_epi64(m5, m2); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_1_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m6, m1); \
|
||||
b1 = _mm_unpackhi_epi64(m3, m1); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_2_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_alignr_epi8(m6, m5, 8); \
|
||||
b1 = _mm_unpackhi_epi64(m2, m7); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_2_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m4, m0); \
|
||||
b1 = _mm_blend_epi16(m1, m6, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_2_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m5, m1, 0xF0); \
|
||||
b1 = _mm_unpackhi_epi64(m3, m4); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_2_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m7, m3); \
|
||||
b1 = _mm_alignr_epi8(m2, m0, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_3_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m3, m1); \
|
||||
b1 = _mm_unpackhi_epi64(m6, m5); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_3_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m4, m0); \
|
||||
b1 = _mm_unpacklo_epi64(m6, m7); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_3_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m1, m2, 0xF0); \
|
||||
b1 = _mm_blend_epi16(m2, m7, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_3_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m3, m5); \
|
||||
b1 = _mm_unpacklo_epi64(m0, m4); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_4_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m4, m2); \
|
||||
b1 = _mm_unpacklo_epi64(m1, m5); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_4_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m0, m3, 0xF0); \
|
||||
b1 = _mm_blend_epi16(m2, m7, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_4_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m7, m5, 0xF0); \
|
||||
b1 = _mm_blend_epi16(m3, m1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_4_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_alignr_epi8(m6, m0, 8); \
|
||||
b1 = _mm_blend_epi16(m4, m6, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_5_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m1, m3); \
|
||||
b1 = _mm_unpacklo_epi64(m0, m4); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_5_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m6, m5); \
|
||||
b1 = _mm_unpackhi_epi64(m5, m1); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_5_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m2, m3, 0xF0); \
|
||||
b1 = _mm_unpackhi_epi64(m7, m0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_5_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m6, m2); \
|
||||
b1 = _mm_blend_epi16(m7, m4, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_6_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m6, m0, 0xF0); \
|
||||
b1 = _mm_unpacklo_epi64(m7, m2); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_6_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m2, m7); \
|
||||
b1 = _mm_alignr_epi8(m5, m6, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_6_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m0, m3); \
|
||||
b1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2)); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_6_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m3, m1); \
|
||||
b1 = _mm_blend_epi16(m1, m5, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_7_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m6, m3); \
|
||||
b1 = _mm_blend_epi16(m6, m1, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_7_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_alignr_epi8(m7, m5, 8); \
|
||||
b1 = _mm_unpackhi_epi64(m0, m4); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_7_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m2, m7); \
|
||||
b1 = _mm_unpacklo_epi64(m4, m1); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_7_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m0, m2); \
|
||||
b1 = _mm_unpacklo_epi64(m3, m5); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_8_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m3, m7); \
|
||||
b1 = _mm_alignr_epi8(m0, m5, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_8_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m7, m4); \
|
||||
b1 = _mm_alignr_epi8(m4, m1, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_8_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = m6; \
|
||||
b1 = _mm_alignr_epi8(m5, m0, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_8_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_blend_epi16(m1, m3, 0xF0); \
|
||||
b1 = m2; \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_9_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m5, m4); \
|
||||
b1 = _mm_unpackhi_epi64(m3, m0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_9_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m1, m2); \
|
||||
b1 = _mm_blend_epi16(m3, m2, 0xF0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_9_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m7, m4); \
|
||||
b1 = _mm_unpackhi_epi64(m1, m6); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_9_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_alignr_epi8(m7, m5, 8); \
|
||||
b1 = _mm_unpacklo_epi64(m6, m0); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_10_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m0, m1); \
|
||||
b1 = _mm_unpacklo_epi64(m2, m3); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_10_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m0, m1); \
|
||||
b1 = _mm_unpackhi_epi64(m2, m3); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_10_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m4, m5); \
|
||||
b1 = _mm_unpacklo_epi64(m6, m7); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_10_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpackhi_epi64(m4, m5); \
|
||||
b1 = _mm_unpackhi_epi64(m6, m7); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_11_1(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m7, m2); \
|
||||
b1 = _mm_unpackhi_epi64(m4, m6); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_11_2(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m5, m4); \
|
||||
b1 = _mm_alignr_epi8(m3, m7, 8); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_11_3(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \
|
||||
b1 = _mm_unpackhi_epi64(m5, m2); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define LOAD_MSG_11_4(b0, b1) \
|
||||
do \
|
||||
{ \
|
||||
b0 = _mm_unpacklo_epi64(m6, m1); \
|
||||
b1 = _mm_unpackhi_epi64(m3, m1); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
+456
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
#include "runtime.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#ifdef HAVE_TI_MODE
|
||||
# if defined(__SIZEOF_INT128__)
|
||||
typedef unsigned __int128 uint128_t;
|
||||
# else
|
||||
typedef unsigned uint128_t __attribute__ ((mode(TI)));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static blake2b_compress_fn blake2b_compress = blake2b_compress_ref;
|
||||
|
||||
static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
static inline int blake2b_set_lastnode( blake2b_state *S )
|
||||
{
|
||||
S->f[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
#if 0
|
||||
static inline int blake2b_clear_lastnode( blake2b_state *S )
|
||||
{
|
||||
S->f[1] = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int blake2b_is_lastblock( const blake2b_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_set_lastblock( blake2b_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2b_set_lastnode( S );
|
||||
|
||||
S->f[0] = -1;
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
static inline int blake2b_clear_lastblock( blake2b_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2b_clear_lastnode( S );
|
||||
|
||||
S->f[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
|
||||
{
|
||||
#ifdef HAVE_TI_MODE
|
||||
uint128_t t = ( ( uint128_t )S->t[1] << 64 ) | S->t[0];
|
||||
t += inc;
|
||||
S->t[0] = ( uint64_t )( t >> 0 );
|
||||
S->t[1] = ( uint64_t )( t >> 64 );
|
||||
#else
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parameter-related functions */
|
||||
#if 0
|
||||
/* Redundant: digest length is directly set in blake2b_init(), blake2b_init_salt_personal(),
|
||||
* blake2b_init_key() and blake2b_init_key_salt_personal() */
|
||||
static inline int blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length )
|
||||
{
|
||||
P->digest_length = digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout )
|
||||
{
|
||||
P->fanout = fanout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth )
|
||||
{
|
||||
P->depth = depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length )
|
||||
{
|
||||
STORE32_LE( P->leaf_length, leaf_length );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset )
|
||||
{
|
||||
STORE64_LE( P->node_offset, node_offset );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth )
|
||||
{
|
||||
P->node_depth = node_depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length )
|
||||
{
|
||||
P->inner_length = inner_length;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static inline int blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] )
|
||||
{
|
||||
memcpy( P->salt, salt, BLAKE2B_SALTBYTES );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] )
|
||||
{
|
||||
memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2b_init0( blake2b_state *S )
|
||||
{
|
||||
int i;
|
||||
memset( S, 0, sizeof( blake2b_state ) );
|
||||
|
||||
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init xors IV with input parameter block */
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
||||
{
|
||||
size_t i;
|
||||
const uint8_t *p;
|
||||
|
||||
(void) sizeof(int[sizeof *P == 64 ? 1 : -1]);
|
||||
blake2b_init0( S );
|
||||
p = ( const uint8_t * )( P );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] ^= LOAD64_LE( p + sizeof( S->h[i] ) * i );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_init( blake2b_state *S, const uint8_t outlen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) abort();
|
||||
|
||||
P->digest_length = outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
STORE32_LE( P->leaf_length, 0 );
|
||||
STORE64_LE( P->node_offset, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2b_init_param( S, P );
|
||||
}
|
||||
|
||||
int blake2b_init_salt_personal( blake2b_state *S, const uint8_t outlen,
|
||||
const void *salt, const void *personal )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) abort();
|
||||
|
||||
P->digest_length = outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
STORE32_LE( P->leaf_length, 0 );
|
||||
STORE64_LE( P->node_offset, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
if (salt != NULL) {
|
||||
blake2b_param_set_salt( P, (const uint8_t *) salt );
|
||||
} else {
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
}
|
||||
if (personal != NULL) {
|
||||
blake2b_param_set_personal( P, (const uint8_t *) personal );
|
||||
} else {
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
}
|
||||
return blake2b_init_param( S, P );
|
||||
}
|
||||
|
||||
int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) abort();
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) abort();
|
||||
|
||||
P->digest_length = outlen;
|
||||
P->key_length = keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
STORE32_LE( P->leaf_length, 0 );
|
||||
STORE64_LE( P->node_offset, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2b_init_param( S, P ) < 0 ) abort();
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_init_key_salt_personal( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen,
|
||||
const void *salt, const void *personal )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) abort();
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) abort();
|
||||
|
||||
P->digest_length = outlen;
|
||||
P->key_length = keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
STORE32_LE( P->leaf_length, 0 );
|
||||
STORE64_LE( P->node_offset, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
if (salt != NULL) {
|
||||
blake2b_param_set_salt( P, (const uint8_t *) salt );
|
||||
} else {
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
}
|
||||
if (personal != NULL) {
|
||||
blake2b_param_set_personal( P, (const uint8_t *) personal );
|
||||
} else {
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
}
|
||||
|
||||
if( blake2b_init_param( S, P ) < 0 ) abort();
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* inlen now in bytes */
|
||||
int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen )
|
||||
{
|
||||
while( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
|
||||
|
||||
if( inlen > fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
S->buflen += fill;
|
||||
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
blake2b_compress( S, S->buf ); /* Compress */
|
||||
memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
|
||||
S->buflen -= BLAKE2B_BLOCKBYTES;
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
}
|
||||
else /* inlen <= fill */
|
||||
{
|
||||
memcpy( S->buf + left, in, inlen );
|
||||
S->buflen += inlen; /* Be lazy, do not compress */
|
||||
in += inlen;
|
||||
inlen -= inlen;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen )
|
||||
{
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) {
|
||||
abort(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if( blake2b_is_lastblock( S ) ) {
|
||||
return -1;
|
||||
}
|
||||
if( S->buflen > BLAKE2B_BLOCKBYTES )
|
||||
{
|
||||
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
blake2b_compress( S, S->buf );
|
||||
S->buflen -= BLAKE2B_BLOCKBYTES;
|
||||
assert( S->buflen <= BLAKE2B_BLOCKBYTES );
|
||||
memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen );
|
||||
}
|
||||
|
||||
blake2b_increment_counter( S, S->buflen );
|
||||
blake2b_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2b_compress( S, S->buf );
|
||||
|
||||
#ifdef NATIVE_LITTLE_ENDIAN
|
||||
memcpy( out, &S->h[0], outlen );
|
||||
#else
|
||||
{
|
||||
uint8_t buffer[BLAKE2B_OUTBYTES];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
STORE64_LE( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
memcpy( out, buffer, outlen );
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* inlen, at least, should be uint64_t. Others can be size_t. */
|
||||
int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
|
||||
{
|
||||
blake2b_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if( NULL == in && inlen > 0 ) abort();
|
||||
|
||||
if( NULL == out ) abort();
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) abort();
|
||||
|
||||
if( NULL == key && keylen > 0 ) abort();
|
||||
|
||||
if( keylen > BLAKE2B_KEYBYTES ) abort();
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2b_init( S, outlen ) < 0 ) abort();
|
||||
}
|
||||
|
||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2b_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_salt_personal( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen,
|
||||
const void *salt, const void *personal )
|
||||
{
|
||||
blake2b_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if( NULL == in && inlen > 0 ) abort();
|
||||
|
||||
if( NULL == out ) abort();
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) abort();
|
||||
|
||||
if( NULL == key && keylen > 0 ) abort();
|
||||
|
||||
if( keylen > BLAKE2B_KEYBYTES ) abort();
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2b_init_key_salt_personal( S, outlen, key, keylen, salt, personal ) < 0 ) abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2b_init_salt_personal( S, outlen, salt, personal ) < 0 ) abort();
|
||||
}
|
||||
|
||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2b_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
blake2b_pick_best_implementation(void)
|
||||
{
|
||||
/* LCOV_EXCL_START */
|
||||
#if (defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64)) && _MSC_VER >= 1700)
|
||||
if (sodium_runtime_has_avx2()) {
|
||||
blake2b_compress = blake2b_compress_avx2;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
if (sodium_runtime_has_sse41()) {
|
||||
blake2b_compress = blake2b_compress_sse41;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64)))
|
||||
if (sodium_runtime_has_ssse3()) {
|
||||
blake2b_compress = blake2b_compress_ssse3;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
blake2b_compress = blake2b_compress_ref;
|
||||
|
||||
return 0;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto_generichash_blake2b.h"
|
||||
#include "blake2.h"
|
||||
|
||||
int
|
||||
crypto_generichash_blake2b(unsigned char *out, size_t outlen,
|
||||
const unsigned char *in, unsigned long long inlen,
|
||||
const unsigned char *key, size_t keylen)
|
||||
{
|
||||
if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
|
||||
keylen > BLAKE2B_KEYBYTES || inlen > UINT64_MAX) {
|
||||
return -1;
|
||||
}
|
||||
assert(outlen <= UINT8_MAX);
|
||||
assert(keylen <= UINT8_MAX);
|
||||
|
||||
return blake2b((uint8_t *) out, in, key,
|
||||
(uint8_t) outlen, (uint64_t) inlen, (uint8_t) keylen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_blake2b_salt_personal(unsigned char *out, size_t outlen,
|
||||
const unsigned char *in, unsigned long long inlen,
|
||||
const unsigned char *key, size_t keylen,
|
||||
const unsigned char *salt,
|
||||
const unsigned char *personal)
|
||||
{
|
||||
if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
|
||||
keylen > BLAKE2B_KEYBYTES || inlen > UINT64_MAX) {
|
||||
return -1;
|
||||
}
|
||||
assert(outlen <= UINT8_MAX);
|
||||
assert(keylen <= UINT8_MAX);
|
||||
|
||||
return blake2b_salt_personal((uint8_t *) out, in, key,
|
||||
(uint8_t) outlen, (uint64_t) inlen, (uint8_t) keylen,
|
||||
salt, personal);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_blake2b_init(crypto_generichash_blake2b_state *state,
|
||||
const unsigned char *key,
|
||||
const size_t keylen, const size_t outlen)
|
||||
{
|
||||
if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
|
||||
keylen > BLAKE2B_KEYBYTES) {
|
||||
return -1;
|
||||
}
|
||||
assert(outlen <= UINT8_MAX);
|
||||
assert(keylen <= UINT8_MAX);
|
||||
if (key == NULL || keylen <= 0U) {
|
||||
if (blake2b_init(state, (uint8_t) outlen) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
} else if (blake2b_init_key(state, (uint8_t) outlen, key,
|
||||
(uint8_t) keylen) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_blake2b_init_salt_personal(crypto_generichash_blake2b_state *state,
|
||||
const unsigned char *key,
|
||||
const size_t keylen, const size_t outlen,
|
||||
const unsigned char *salt,
|
||||
const unsigned char *personal)
|
||||
{
|
||||
if (outlen <= 0U || outlen > BLAKE2B_OUTBYTES ||
|
||||
keylen > BLAKE2B_KEYBYTES) {
|
||||
return -1;
|
||||
}
|
||||
assert(outlen <= UINT8_MAX);
|
||||
assert(keylen <= UINT8_MAX);
|
||||
if (key == NULL || keylen <= 0U) {
|
||||
if (blake2b_init_salt_personal(state, (uint8_t) outlen,
|
||||
salt, personal) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
} else if (blake2b_init_key_salt_personal(state,
|
||||
(uint8_t) outlen, key,
|
||||
(uint8_t) keylen,
|
||||
salt, personal) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return blake2b_update(state, (const uint8_t *) in, (uint64_t) inlen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_blake2b_final(crypto_generichash_blake2b_state *state,
|
||||
unsigned char *out,
|
||||
const size_t outlen)
|
||||
{
|
||||
assert(outlen <= UINT8_MAX);
|
||||
return blake2b_final(state, (uint8_t *) out, (uint8_t) outlen);
|
||||
}
|
||||
|
||||
int
|
||||
_crypto_generichash_blake2b_pick_best_implementation(void)
|
||||
{
|
||||
return blake2b_pick_best_implementation();
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
|
||||
#include "crypto_generichash.h"
|
||||
|
||||
size_t
|
||||
crypto_generichash_bytes_min(void)
|
||||
{
|
||||
return crypto_generichash_BYTES_MIN;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_bytes_max(void)
|
||||
{
|
||||
return crypto_generichash_BYTES_MAX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_bytes(void)
|
||||
{
|
||||
return crypto_generichash_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_keybytes_min(void)
|
||||
{
|
||||
return crypto_generichash_KEYBYTES_MIN;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_keybytes_max(void)
|
||||
{
|
||||
return crypto_generichash_KEYBYTES_MAX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_keybytes(void)
|
||||
{
|
||||
return crypto_generichash_KEYBYTES;
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_generichash_primitive(void)
|
||||
{
|
||||
return crypto_generichash_PRIMITIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_generichash_statebytes(void)
|
||||
{
|
||||
return (sizeof(crypto_generichash_state) + (size_t) 63U) & ~(size_t) 63U;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash(unsigned char *out, size_t outlen, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *key,
|
||||
size_t keylen)
|
||||
{
|
||||
return crypto_generichash_blake2b(out, outlen, in, inlen, key, keylen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_init(crypto_generichash_state *state,
|
||||
const unsigned char *key,
|
||||
const size_t keylen, const size_t outlen)
|
||||
{
|
||||
return crypto_generichash_blake2b_init
|
||||
((crypto_generichash_blake2b_state *) state, key, keylen, outlen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_update(crypto_generichash_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return crypto_generichash_blake2b_update
|
||||
((crypto_generichash_blake2b_state *) state, in, inlen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_generichash_final(crypto_generichash_state *state,
|
||||
unsigned char *out, const size_t outlen)
|
||||
{
|
||||
return crypto_generichash_blake2b_final
|
||||
((crypto_generichash_blake2b_state *) state, out, outlen);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
#include "crypto_hash.h"
|
||||
|
||||
size_t
|
||||
crypto_hash_bytes(void)
|
||||
{
|
||||
return crypto_hash_BYTES;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return crypto_hash_sha512(out, in, inlen);
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_hash_primitive(void) {
|
||||
return crypto_hash_PRIMITIVE;
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
|
||||
/*-
|
||||
* 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 "crypto_hash_sha256.h"
|
||||
#include "utils.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 4; i++) {
|
||||
STORE32_BE(dst + i * 4, src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 4; i++) {
|
||||
dst[i] = LOAD32_BE(src + i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
#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 << (32 - n)))
|
||||
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
#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[(64 - i) % 8], S[(65 - i) % 8], \
|
||||
S[(66 - i) % 8], S[(67 - i) % 8], \
|
||||
S[(68 - i) % 8], S[(69 - i) % 8], \
|
||||
S[(70 - i) % 8], S[(71 - i) % 8], \
|
||||
W[i] + k)
|
||||
|
||||
static void
|
||||
SHA256_Transform(uint32_t *state, const unsigned char block[64])
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t S[8];
|
||||
uint32_t t0, t1;
|
||||
int i;
|
||||
|
||||
be32dec_vect(W, block, 64);
|
||||
for (i = 16; i < 64; i++) {
|
||||
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
|
||||
}
|
||||
|
||||
memcpy(S, state, 32);
|
||||
|
||||
RNDr(S, W, 0, 0x428a2f98);
|
||||
RNDr(S, W, 1, 0x71374491);
|
||||
RNDr(S, W, 2, 0xb5c0fbcf);
|
||||
RNDr(S, W, 3, 0xe9b5dba5);
|
||||
RNDr(S, W, 4, 0x3956c25b);
|
||||
RNDr(S, W, 5, 0x59f111f1);
|
||||
RNDr(S, W, 6, 0x923f82a4);
|
||||
RNDr(S, W, 7, 0xab1c5ed5);
|
||||
RNDr(S, W, 8, 0xd807aa98);
|
||||
RNDr(S, W, 9, 0x12835b01);
|
||||
RNDr(S, W, 10, 0x243185be);
|
||||
RNDr(S, W, 11, 0x550c7dc3);
|
||||
RNDr(S, W, 12, 0x72be5d74);
|
||||
RNDr(S, W, 13, 0x80deb1fe);
|
||||
RNDr(S, W, 14, 0x9bdc06a7);
|
||||
RNDr(S, W, 15, 0xc19bf174);
|
||||
RNDr(S, W, 16, 0xe49b69c1);
|
||||
RNDr(S, W, 17, 0xefbe4786);
|
||||
RNDr(S, W, 18, 0x0fc19dc6);
|
||||
RNDr(S, W, 19, 0x240ca1cc);
|
||||
RNDr(S, W, 20, 0x2de92c6f);
|
||||
RNDr(S, W, 21, 0x4a7484aa);
|
||||
RNDr(S, W, 22, 0x5cb0a9dc);
|
||||
RNDr(S, W, 23, 0x76f988da);
|
||||
RNDr(S, W, 24, 0x983e5152);
|
||||
RNDr(S, W, 25, 0xa831c66d);
|
||||
RNDr(S, W, 26, 0xb00327c8);
|
||||
RNDr(S, W, 27, 0xbf597fc7);
|
||||
RNDr(S, W, 28, 0xc6e00bf3);
|
||||
RNDr(S, W, 29, 0xd5a79147);
|
||||
RNDr(S, W, 30, 0x06ca6351);
|
||||
RNDr(S, W, 31, 0x14292967);
|
||||
RNDr(S, W, 32, 0x27b70a85);
|
||||
RNDr(S, W, 33, 0x2e1b2138);
|
||||
RNDr(S, W, 34, 0x4d2c6dfc);
|
||||
RNDr(S, W, 35, 0x53380d13);
|
||||
RNDr(S, W, 36, 0x650a7354);
|
||||
RNDr(S, W, 37, 0x766a0abb);
|
||||
RNDr(S, W, 38, 0x81c2c92e);
|
||||
RNDr(S, W, 39, 0x92722c85);
|
||||
RNDr(S, W, 40, 0xa2bfe8a1);
|
||||
RNDr(S, W, 41, 0xa81a664b);
|
||||
RNDr(S, W, 42, 0xc24b8b70);
|
||||
RNDr(S, W, 43, 0xc76c51a3);
|
||||
RNDr(S, W, 44, 0xd192e819);
|
||||
RNDr(S, W, 45, 0xd6990624);
|
||||
RNDr(S, W, 46, 0xf40e3585);
|
||||
RNDr(S, W, 47, 0x106aa070);
|
||||
RNDr(S, W, 48, 0x19a4c116);
|
||||
RNDr(S, W, 49, 0x1e376c08);
|
||||
RNDr(S, W, 50, 0x2748774c);
|
||||
RNDr(S, W, 51, 0x34b0bcb5);
|
||||
RNDr(S, W, 52, 0x391c0cb3);
|
||||
RNDr(S, W, 53, 0x4ed8aa4a);
|
||||
RNDr(S, W, 54, 0x5b9cca4f);
|
||||
RNDr(S, W, 55, 0x682e6ff3);
|
||||
RNDr(S, W, 56, 0x748f82ee);
|
||||
RNDr(S, W, 57, 0x78a5636f);
|
||||
RNDr(S, W, 58, 0x84c87814);
|
||||
RNDr(S, W, 59, 0x8cc70208);
|
||||
RNDr(S, W, 60, 0x90befffa);
|
||||
RNDr(S, W, 61, 0xa4506ceb);
|
||||
RNDr(S, W, 62, 0xbef9a3f7);
|
||||
RNDr(S, W, 63, 0xc67178f2);
|
||||
|
||||
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[64] = {
|
||||
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
|
||||
};
|
||||
|
||||
static void
|
||||
SHA256_Pad(crypto_hash_sha256_state *state)
|
||||
{
|
||||
unsigned char len[8];
|
||||
uint32_t r, plen;
|
||||
|
||||
STORE64_BE(len, state->count);
|
||||
|
||||
r = (state->count >> 3) & 0x3f;
|
||||
plen = (r < 56) ? (56 - r) : (120 - r);
|
||||
crypto_hash_sha256_update(state, PAD, (unsigned long long) plen);
|
||||
|
||||
crypto_hash_sha256_update(state, len, 8);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256_init(crypto_hash_sha256_state *state)
|
||||
{
|
||||
static const uint32_t sha256_initstate[8] = {
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
};
|
||||
|
||||
state->count = (uint64_t) 0U;
|
||||
memcpy(state->state, sha256_initstate, sizeof sha256_initstate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256_update(crypto_hash_sha256_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
unsigned long long i;
|
||||
uint32_t r;
|
||||
|
||||
if (inlen <= 0U) {
|
||||
return 0;
|
||||
}
|
||||
r = (state->count >> 3) & 0x3f;
|
||||
state->count += (uint64_t)(inlen) << 3;
|
||||
|
||||
if (inlen < 64 - r) {
|
||||
for (i = 0; i < inlen; i++) {
|
||||
state->buf[r + i] = in[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 64 - r; i++) {
|
||||
state->buf[r + i] = in[i];
|
||||
}
|
||||
SHA256_Transform(state->state, state->buf);
|
||||
in += 64 - r;
|
||||
inlen -= 64 - r;
|
||||
|
||||
while (inlen >= 64) {
|
||||
SHA256_Transform(state->state, in);
|
||||
in += 64;
|
||||
inlen -= 64;
|
||||
}
|
||||
inlen &= 63;
|
||||
for (i = 0; i < inlen; i++) {
|
||||
state->buf[i] = in[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256_final(crypto_hash_sha256_state *state,
|
||||
unsigned char *out)
|
||||
{
|
||||
SHA256_Pad(state);
|
||||
be32enc_vect(out, state->state, 32);
|
||||
sodium_memzero((void *) state, sizeof *state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha256(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
crypto_hash_sha256_state state;
|
||||
|
||||
crypto_hash_sha256_init(&state);
|
||||
crypto_hash_sha256_update(&state, in, inlen);
|
||||
crypto_hash_sha256_final(&state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "crypto_hash_sha256.h"
|
||||
|
||||
size_t
|
||||
crypto_hash_sha256_bytes(void) {
|
||||
return crypto_hash_sha256_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_hash_sha256_statebytes(void) {
|
||||
return sizeof(crypto_hash_sha256_state);
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
|
||||
/*-
|
||||
* 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 "crypto_hash_sha512.h"
|
||||
#include "utils.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / 8; i++) {
|
||||
STORE64_BE(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] = LOAD64_BE(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)
|
||||
{
|
||||
static const uint64_t sha512_initstate[8] = {
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
state->count[0] = state->count[1] = (uint64_t) 0U;
|
||||
memcpy(state->state, sha512_initstate, sizeof sha512_initstate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_hash_sha512_update(crypto_hash_sha512_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
unsigned long long i;
|
||||
uint64_t bitlen[2];
|
||||
uint64_t r;
|
||||
|
||||
r = (state->count[1] >> 3) & 0x7f;
|
||||
|
||||
bitlen[1] = ((uint64_t)inlen) << 3;
|
||||
bitlen[0] = ((uint64_t)inlen) >> 61;
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
if ((state->count[1] += bitlen[1]) < bitlen[1]) {
|
||||
state->count[0]++;
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
state->count[0] += bitlen[0];
|
||||
|
||||
if (inlen < 128 - r) {
|
||||
for (i = 0; i < inlen; i++) {
|
||||
state->buf[r + i] = in[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 128 - r; i++) {
|
||||
state->buf[r + i] = in[i];
|
||||
}
|
||||
SHA512_Transform(state->state, state->buf);
|
||||
in += 128 - r;
|
||||
inlen -= 128 - r;
|
||||
|
||||
while (inlen >= 128) {
|
||||
SHA512_Transform(state->state, in);
|
||||
in += 128;
|
||||
inlen -= 128;
|
||||
}
|
||||
inlen &= 127;
|
||||
for (i = 0; i < inlen; i++) {
|
||||
state->buf[i] = in[i];
|
||||
}
|
||||
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_sha512(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;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "crypto_hash_sha512.h"
|
||||
|
||||
size_t
|
||||
crypto_hash_sha512_bytes(void) {
|
||||
return crypto_hash_sha512_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_hash_sha512_statebytes(void) {
|
||||
return sizeof(crypto_hash_sha512_state);
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
|
||||
#include "crypto_onetimeauth.h"
|
||||
|
||||
size_t
|
||||
crypto_onetimeauth_statebytes(void)
|
||||
{
|
||||
return sizeof(crypto_onetimeauth_state);
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_onetimeauth_bytes(void)
|
||||
{
|
||||
return crypto_onetimeauth_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_onetimeauth_keybytes(void)
|
||||
{
|
||||
return crypto_onetimeauth_KEYBYTES;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
return crypto_onetimeauth_poly1305(out, in, inlen, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_verify(const unsigned char *h, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
return crypto_onetimeauth_poly1305_verify(h, in, inlen, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_init(crypto_onetimeauth_state *state,
|
||||
const unsigned char *key)
|
||||
{
|
||||
return crypto_onetimeauth_poly1305_init
|
||||
((crypto_onetimeauth_poly1305_state *) state, key);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_update(crypto_onetimeauth_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return crypto_onetimeauth_poly1305_update
|
||||
((crypto_onetimeauth_poly1305_state *) state, in, inlen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_final(crypto_onetimeauth_state *state,
|
||||
unsigned char *out)
|
||||
{
|
||||
return crypto_onetimeauth_poly1305_final
|
||||
((crypto_onetimeauth_poly1305_state *) state, out);
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_onetimeauth_primitive(void)
|
||||
{
|
||||
return crypto_onetimeauth_PRIMITIVE;
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
|
||||
#include "crypto_verify_16.h"
|
||||
#include "utils.h"
|
||||
#include "poly1305_donna.h"
|
||||
#ifdef HAVE_TI_MODE
|
||||
# include "poly1305_donna64.h"
|
||||
#else
|
||||
# include "poly1305_donna32.h"
|
||||
#endif
|
||||
#include "../onetimeauth_poly1305.h"
|
||||
|
||||
static void
|
||||
poly1305_update(poly1305_state_internal_t *st, const unsigned char *m,
|
||||
unsigned long long bytes)
|
||||
{
|
||||
unsigned long long i;
|
||||
|
||||
/* handle leftover */
|
||||
if (st->leftover) {
|
||||
unsigned long long want = (poly1305_block_size - st->leftover);
|
||||
|
||||
if (want > bytes)
|
||||
want = bytes;
|
||||
for (i = 0; i < want; i++)
|
||||
st->buffer[st->leftover + i] = m[i];
|
||||
bytes -= want;
|
||||
m += want;
|
||||
st->leftover += want;
|
||||
if (st->leftover < poly1305_block_size)
|
||||
return;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
st->leftover = 0;
|
||||
}
|
||||
|
||||
/* process full blocks */
|
||||
if (bytes >= poly1305_block_size) {
|
||||
unsigned long long want = (bytes & ~(poly1305_block_size - 1));
|
||||
|
||||
poly1305_blocks(st, m, want);
|
||||
m += want;
|
||||
bytes -= want;
|
||||
}
|
||||
|
||||
/* store leftover */
|
||||
if (bytes) {
|
||||
for (i = 0; i < bytes; i++) {
|
||||
st->buffer[st->leftover + i] = m[i];
|
||||
}
|
||||
st->leftover += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_donna(unsigned char *out, const unsigned char *m,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *key)
|
||||
{
|
||||
CRYPTO_ALIGN(64) poly1305_state_internal_t state;
|
||||
|
||||
poly1305_init(&state, key);
|
||||
poly1305_update(&state, m, inlen);
|
||||
poly1305_finish(&state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_donna_init(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *key)
|
||||
{
|
||||
(void) sizeof(int[sizeof (crypto_onetimeauth_poly1305_state) >=
|
||||
sizeof (poly1305_state_internal_t) ? 1 : -1]);
|
||||
poly1305_init((poly1305_state_internal_t *)(void *) state, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_donna_update(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
poly1305_update((poly1305_state_internal_t *)(void *) state, in, inlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_donna_final(crypto_onetimeauth_poly1305_state *state,
|
||||
unsigned char *out)
|
||||
{
|
||||
poly1305_finish((poly1305_state_internal_t *)(void *) state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_donna_verify(const unsigned char *h,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned char correct[16];
|
||||
|
||||
crypto_onetimeauth_poly1305_donna(correct,in,inlen,k);
|
||||
|
||||
return crypto_verify_16(h,correct);
|
||||
}
|
||||
|
||||
struct crypto_onetimeauth_poly1305_implementation
|
||||
crypto_onetimeauth_poly1305_donna_implementation = {
|
||||
SODIUM_C99(.onetimeauth =) crypto_onetimeauth_poly1305_donna,
|
||||
SODIUM_C99(.onetimeauth_verify =) crypto_onetimeauth_poly1305_donna_verify,
|
||||
SODIUM_C99(.onetimeauth_init =) crypto_onetimeauth_poly1305_donna_init,
|
||||
SODIUM_C99(.onetimeauth_update =) crypto_onetimeauth_poly1305_donna_update,
|
||||
SODIUM_C99(.onetimeauth_final =) crypto_onetimeauth_poly1305_donna_final
|
||||
};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#ifndef poly1305_donna_H
|
||||
#define poly1305_donna_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "crypto_onetimeauth_poly1305.h"
|
||||
#include "../onetimeauth_poly1305.h"
|
||||
|
||||
extern struct crypto_onetimeauth_poly1305_implementation
|
||||
crypto_onetimeauth_poly1305_donna_implementation;
|
||||
|
||||
#endif /* poly1305_donna_H */
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define POLY1305_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
# define POLY1305_NOINLINE __attribute__ ((noinline))
|
||||
#else
|
||||
# define POLY1305_NOINLINE
|
||||
#endif
|
||||
|
||||
#include "private/common.h"
|
||||
|
||||
#define poly1305_block_size 16
|
||||
|
||||
/* 17 + sizeof(unsigned long long) + 14*sizeof(unsigned long) */
|
||||
typedef struct poly1305_state_internal_t {
|
||||
unsigned long r[5];
|
||||
unsigned long h[5];
|
||||
unsigned long pad[4];
|
||||
unsigned long long leftover;
|
||||
unsigned char buffer[poly1305_block_size];
|
||||
unsigned char final;
|
||||
} poly1305_state_internal_t;
|
||||
|
||||
static void
|
||||
poly1305_init(poly1305_state_internal_t *st, const unsigned char key[32])
|
||||
{
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
st->r[0] = (LOAD32_LE(&key[ 0]) ) & 0x3ffffff;
|
||||
st->r[1] = (LOAD32_LE(&key[ 3]) >> 2) & 0x3ffff03;
|
||||
st->r[2] = (LOAD32_LE(&key[ 6]) >> 4) & 0x3ffc0ff;
|
||||
st->r[3] = (LOAD32_LE(&key[ 9]) >> 6) & 0x3f03fff;
|
||||
st->r[4] = (LOAD32_LE(&key[12]) >> 8) & 0x00fffff;
|
||||
|
||||
/* h = 0 */
|
||||
st->h[0] = 0;
|
||||
st->h[1] = 0;
|
||||
st->h[2] = 0;
|
||||
st->h[3] = 0;
|
||||
st->h[4] = 0;
|
||||
|
||||
/* save pad for later */
|
||||
st->pad[0] = LOAD32_LE(&key[16]);
|
||||
st->pad[1] = LOAD32_LE(&key[20]);
|
||||
st->pad[2] = LOAD32_LE(&key[24]);
|
||||
st->pad[3] = LOAD32_LE(&key[28]);
|
||||
|
||||
st->leftover = 0;
|
||||
st->final = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, unsigned long long bytes)
|
||||
{
|
||||
const unsigned long hibit = (st->final) ? 0UL : (1UL << 24); /* 1 << 128 */
|
||||
unsigned long r0,r1,r2,r3,r4;
|
||||
unsigned long s1,s2,s3,s4;
|
||||
unsigned long h0,h1,h2,h3,h4;
|
||||
unsigned long long d0,d1,d2,d3,d4;
|
||||
unsigned long c;
|
||||
|
||||
r0 = st->r[0];
|
||||
r1 = st->r[1];
|
||||
r2 = st->r[2];
|
||||
r3 = st->r[3];
|
||||
r4 = st->r[4];
|
||||
|
||||
s1 = r1 * 5;
|
||||
s2 = r2 * 5;
|
||||
s3 = r3 * 5;
|
||||
s4 = r4 * 5;
|
||||
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
while (bytes >= poly1305_block_size) {
|
||||
/* h += m[i] */
|
||||
h0 += (LOAD32_LE(m+ 0) ) & 0x3ffffff;
|
||||
h1 += (LOAD32_LE(m+ 3) >> 2) & 0x3ffffff;
|
||||
h2 += (LOAD32_LE(m+ 6) >> 4) & 0x3ffffff;
|
||||
h3 += (LOAD32_LE(m+ 9) >> 6) & 0x3ffffff;
|
||||
h4 += (LOAD32_LE(m+12) >> 8) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
|
||||
d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
|
||||
d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
|
||||
d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
|
||||
d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
|
||||
|
||||
/* (partial) h %= p */
|
||||
c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
bytes -= poly1305_block_size;
|
||||
}
|
||||
|
||||
st->h[0] = h0;
|
||||
st->h[1] = h1;
|
||||
st->h[2] = h2;
|
||||
st->h[3] = h3;
|
||||
st->h[4] = h4;
|
||||
}
|
||||
|
||||
static POLY1305_NOINLINE void
|
||||
poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
|
||||
{
|
||||
unsigned long h0,h1,h2,h3,h4,c;
|
||||
unsigned long g0,g1,g2,g3,g4;
|
||||
unsigned long long f;
|
||||
unsigned long mask;
|
||||
|
||||
/* process the remaining block */
|
||||
if (st->leftover) {
|
||||
unsigned long long i = st->leftover;
|
||||
st->buffer[i++] = 1;
|
||||
for (; i < poly1305_block_size; i++)
|
||||
st->buffer[i] = 0;
|
||||
st->final = 1;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
}
|
||||
|
||||
/* fully carry h */
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
c = h1 >> 26; h1 = h1 & 0x3ffffff;
|
||||
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
|
||||
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
|
||||
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
|
||||
g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
|
||||
g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
|
||||
g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
|
||||
g4 = h4 + c - (1UL << 26);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
|
||||
g0 &= mask;
|
||||
g1 &= mask;
|
||||
g2 &= mask;
|
||||
g3 &= mask;
|
||||
g4 &= mask;
|
||||
mask = ~mask;
|
||||
h0 = (h0 & mask) | g0;
|
||||
h1 = (h1 & mask) | g1;
|
||||
h2 = (h2 & mask) | g2;
|
||||
h3 = (h3 & mask) | g3;
|
||||
h4 = (h4 & mask) | g4;
|
||||
|
||||
/* h = h % (2^128) */
|
||||
h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
|
||||
h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
|
||||
h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
|
||||
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
|
||||
|
||||
/* mac = (h + pad) % (2^128) */
|
||||
f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f;
|
||||
|
||||
STORE32_LE(mac + 0, h0);
|
||||
STORE32_LE(mac + 4, h1);
|
||||
STORE32_LE(mac + 8, h2);
|
||||
STORE32_LE(mac + 12, h3);
|
||||
|
||||
/* zero out the state */
|
||||
sodium_memzero((void *)st, sizeof *st);
|
||||
}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
poly1305 implementation using 64 bit * 64 bit = 128 bit multiplication and 128 bit addition
|
||||
*/
|
||||
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
typedef unsigned __int128 uint128_t;
|
||||
#else
|
||||
typedef unsigned uint128_t __attribute__ ((mode(TI)));
|
||||
#endif
|
||||
|
||||
#define MUL(out, x, y) out = ((uint128_t)x * y)
|
||||
#define ADD(out, in) out += in
|
||||
#define ADDLO(out, in) out += in
|
||||
#define SHR(in, shift) (unsigned long long)(in >> (shift))
|
||||
#define LO(in) (unsigned long long)(in)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define POLY1305_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
# define POLY1305_NOINLINE __attribute__ ((noinline))
|
||||
#else
|
||||
# define POLY1305_NOINLINE
|
||||
#endif
|
||||
|
||||
#include "private/common.h"
|
||||
|
||||
#define poly1305_block_size 16
|
||||
|
||||
/* 17 + sizeof(unsigned long long) + 8*sizeof(unsigned long long) */
|
||||
typedef struct poly1305_state_internal_t {
|
||||
unsigned long long r[3];
|
||||
unsigned long long h[3];
|
||||
unsigned long long pad[2];
|
||||
unsigned long long leftover;
|
||||
unsigned char buffer[poly1305_block_size];
|
||||
unsigned char final;
|
||||
} poly1305_state_internal_t;
|
||||
|
||||
static void
|
||||
poly1305_init(poly1305_state_internal_t *st, const unsigned char key[32])
|
||||
{
|
||||
unsigned long long t0,t1;
|
||||
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
t0 = LOAD64_LE(&key[0]);
|
||||
t1 = LOAD64_LE(&key[8]);
|
||||
|
||||
st->r[0] = ( t0 ) & 0xffc0fffffff;
|
||||
st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
|
||||
st->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
|
||||
|
||||
/* h = 0 */
|
||||
st->h[0] = 0;
|
||||
st->h[1] = 0;
|
||||
st->h[2] = 0;
|
||||
|
||||
/* save pad for later */
|
||||
st->pad[0] = LOAD64_LE(&key[16]);
|
||||
st->pad[1] = LOAD64_LE(&key[24]);
|
||||
|
||||
st->leftover = 0;
|
||||
st->final = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, unsigned long long bytes)
|
||||
{
|
||||
const unsigned long long hibit = (st->final) ? 0ULL : (1ULL << 40); /* 1 << 128 */
|
||||
unsigned long long r0,r1,r2;
|
||||
unsigned long long s1,s2;
|
||||
unsigned long long h0,h1,h2;
|
||||
unsigned long long c;
|
||||
uint128_t d0,d1,d2,d;
|
||||
|
||||
r0 = st->r[0];
|
||||
r1 = st->r[1];
|
||||
r2 = st->r[2];
|
||||
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
|
||||
s1 = r1 * (5 << 2);
|
||||
s2 = r2 * (5 << 2);
|
||||
|
||||
while (bytes >= poly1305_block_size) {
|
||||
unsigned long long t0,t1;
|
||||
|
||||
/* h += m[i] */
|
||||
t0 = LOAD64_LE(&m[0]);
|
||||
t1 = LOAD64_LE(&m[8]);
|
||||
|
||||
h0 += (( t0 ) & 0xfffffffffff);
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
|
||||
h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
|
||||
MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
|
||||
MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
|
||||
|
||||
/* (partial) h %= p */
|
||||
c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
|
||||
ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
|
||||
ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
bytes -= poly1305_block_size;
|
||||
}
|
||||
|
||||
st->h[0] = h0;
|
||||
st->h[1] = h1;
|
||||
st->h[2] = h2;
|
||||
}
|
||||
|
||||
|
||||
static POLY1305_NOINLINE void
|
||||
poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
|
||||
{
|
||||
unsigned long long h0,h1,h2,c;
|
||||
unsigned long long g0,g1,g2;
|
||||
unsigned long long t0,t1;
|
||||
|
||||
/* process the remaining block */
|
||||
if (st->leftover) {
|
||||
unsigned long long i = st->leftover;
|
||||
st->buffer[i] = 1;
|
||||
for (i = i + 1; i < poly1305_block_size; i++)
|
||||
st->buffer[i] = 0;
|
||||
st->final = 1;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
}
|
||||
|
||||
/* fully carry h */
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
|
||||
c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
|
||||
g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
|
||||
g2 = h2 + c - (1ULL << 42);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
c = (g2 >> ((sizeof(unsigned long long) * 8) - 1)) - 1;
|
||||
g0 &= c;
|
||||
g1 &= c;
|
||||
g2 &= c;
|
||||
c = ~c;
|
||||
h0 = (h0 & c) | g0;
|
||||
h1 = (h1 & c) | g1;
|
||||
h2 = (h2 & c) | g2;
|
||||
|
||||
/* h = (h + pad) */
|
||||
t0 = st->pad[0];
|
||||
t1 = st->pad[1];
|
||||
|
||||
h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff;
|
||||
|
||||
/* mac = h % (2^128) */
|
||||
h0 = ((h0 ) | (h1 << 44));
|
||||
h1 = ((h1 >> 20) | (h2 << 24));
|
||||
|
||||
STORE64_LE(&mac[0], h0);
|
||||
STORE64_LE(&mac[8], h1);
|
||||
|
||||
/* zero out the state */
|
||||
sodium_memzero((void *)st, sizeof *st);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
|
||||
#include "crypto_onetimeauth_poly1305.h"
|
||||
#include "onetimeauth_poly1305.h"
|
||||
#include "runtime.h"
|
||||
#include "donna/poly1305_donna.h"
|
||||
#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
|
||||
# include "sse2/poly1305_sse2.h"
|
||||
#endif
|
||||
|
||||
static const crypto_onetimeauth_poly1305_implementation *implementation =
|
||||
&crypto_onetimeauth_poly1305_donna_implementation;
|
||||
|
||||
int
|
||||
crypto_onetimeauth_poly1305(unsigned char *out, const unsigned char *in,
|
||||
unsigned long long inlen, const unsigned char *k)
|
||||
{
|
||||
return implementation->onetimeauth(out, in, inlen, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_poly1305_verify(const unsigned char *h,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *k)
|
||||
{
|
||||
return implementation->onetimeauth_verify(h, in, inlen, k);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_poly1305_init(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *key)
|
||||
{
|
||||
return implementation->onetimeauth_init(state, key);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_poly1305_update(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
return implementation->onetimeauth_update(state, in, inlen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_onetimeauth_poly1305_final(crypto_onetimeauth_poly1305_state *state,
|
||||
unsigned char *out)
|
||||
{
|
||||
return implementation->onetimeauth_final(state, out);
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_onetimeauth_poly1305_bytes(void) {
|
||||
return crypto_onetimeauth_poly1305_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_onetimeauth_poly1305_keybytes(void) {
|
||||
return crypto_onetimeauth_poly1305_KEYBYTES;
|
||||
}
|
||||
|
||||
int
|
||||
_crypto_onetimeauth_poly1305_pick_best_implementation(void)
|
||||
{
|
||||
implementation = &crypto_onetimeauth_poly1305_donna_implementation;
|
||||
#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
|
||||
if (sodium_runtime_has_sse2()) {
|
||||
implementation = &crypto_onetimeauth_poly1305_sse2_implementation;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
|
||||
#ifndef onetimeauth_poly1305_H
|
||||
#define onetimeauth_poly1305_H
|
||||
|
||||
typedef struct crypto_onetimeauth_poly1305_implementation {
|
||||
int (*onetimeauth)(unsigned char *out,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *k);
|
||||
int (*onetimeauth_verify)(const unsigned char *h,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *k);
|
||||
int (*onetimeauth_init)(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *key);
|
||||
int (*onetimeauth_update)(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen);
|
||||
int (*onetimeauth_final)(crypto_onetimeauth_poly1305_state *state,
|
||||
unsigned char *out);
|
||||
} crypto_onetimeauth_poly1305_implementation;
|
||||
|
||||
#endif
|
||||
+706
@@ -0,0 +1,706 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_verify_16.h"
|
||||
#include "utils.h"
|
||||
#include "poly1305_sse2.h"
|
||||
#include "../onetimeauth_poly1305.h"
|
||||
|
||||
#if defined(HAVE_TI_MODE) && defined(HAVE_EMMINTRIN_H)
|
||||
|
||||
#pragma GCC target("sse2")
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
typedef __m128i xmmi;
|
||||
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
typedef unsigned __int128 uint128_t;
|
||||
#else
|
||||
typedef unsigned uint128_t __attribute__ ((mode(TI)));
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define POLY1305_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
# define POLY1305_NOINLINE __attribute__ ((noinline))
|
||||
#else
|
||||
# define POLY1305_NOINLINE
|
||||
#endif
|
||||
|
||||
#define poly1305_block_size 32
|
||||
|
||||
enum poly1305_state_flags_t {
|
||||
poly1305_started = 1,
|
||||
poly1305_final_shift8 = 4,
|
||||
poly1305_final_shift16 = 8,
|
||||
poly1305_final_r2_r = 16, /* use [r^2,r] for the final block */
|
||||
poly1305_final_r_1 = 32, /* use [r,1] for the final block */
|
||||
};
|
||||
|
||||
typedef struct poly1305_state_internal_t {
|
||||
union {
|
||||
uint64_t h[3];
|
||||
uint32_t hh[10];
|
||||
}; /* 40 bytes */
|
||||
uint32_t R[5]; /* 20 bytes */
|
||||
uint32_t R2[5]; /* 20 bytes */
|
||||
uint32_t R4[5]; /* 20 bytes */
|
||||
uint64_t pad[2]; /* 16 bytes */
|
||||
uint64_t flags; /* 8 bytes */
|
||||
unsigned long long leftover; /* 8 bytes */
|
||||
unsigned char buffer[poly1305_block_size]; /* 32 bytes */
|
||||
} poly1305_state_internal_t; /* 164 bytes total */
|
||||
|
||||
/*
|
||||
* _mm_loadl_epi64() is turned into a simple MOVQ. So, unaligned accesses are totally fine, even though this intrinsic requires a __m128i* input.
|
||||
* This confuses dynamic analysis, so force alignment, only in debug mode.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
static xmmi
|
||||
_fakealign_mm_loadl_epi64(const void *m)
|
||||
{
|
||||
xmmi tmp;
|
||||
memcpy(&tmp, m, 8);
|
||||
return _mm_loadl_epi64(&tmp);
|
||||
}
|
||||
# define _mm_loadl_epi64(X) _fakealign_mm_loadl_epi64(X)
|
||||
#endif
|
||||
|
||||
/* copy 0-31 bytes */
|
||||
static inline void
|
||||
poly1305_block_copy31(unsigned char *dst, const unsigned char *src, unsigned long long bytes)
|
||||
{
|
||||
if (bytes & 16) {
|
||||
_mm_store_si128((xmmi *) (void *) dst,
|
||||
_mm_loadu_si128((const xmmi *) (const void *) src));
|
||||
src += 16; dst += 16;
|
||||
}
|
||||
if (bytes & 8) { memcpy(dst, src, 8); src += 8; dst += 8; }
|
||||
if (bytes & 4) { memcpy(dst, src, 4); src += 4; dst += 4; }
|
||||
if (bytes & 2) { memcpy(dst, src, 2); src += 2; dst += 2; }
|
||||
if (bytes & 1) { *dst = *src; }
|
||||
}
|
||||
|
||||
static POLY1305_NOINLINE void
|
||||
poly1305_init_ext(poly1305_state_internal_t *st,
|
||||
const unsigned char key[32], unsigned long long bytes)
|
||||
{
|
||||
uint32_t *R;
|
||||
uint128_t d[3];
|
||||
uint64_t r0,r1,r2;
|
||||
uint64_t rt0,rt1,rt2,st2,c;
|
||||
uint64_t t0,t1;
|
||||
unsigned long long i;
|
||||
|
||||
if (!bytes) bytes = ~(unsigned long long)0;
|
||||
|
||||
/* H = 0 */
|
||||
_mm_storeu_si128((xmmi *)(void *)&st->hh[0], _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)&st->hh[4], _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)&st->hh[8], _mm_setzero_si128());
|
||||
|
||||
/* clamp key */
|
||||
memcpy(&t0, key, 8);
|
||||
memcpy(&t1, key + 8, 8);
|
||||
r0 = t0 & 0xffc0fffffff; t0 >>= 44; t0 |= t1 << 20;
|
||||
r1 = t0 & 0xfffffc0ffff; t1 >>= 24;
|
||||
r2 = t1 & 0x00ffffffc0f;
|
||||
|
||||
/* r^1 */
|
||||
R = st->R;
|
||||
R[0] = (uint32_t)( r0 ) & 0x3ffffff;
|
||||
R[1] = (uint32_t)(( r0 >> 26) | ( r1 << 18)) & 0x3ffffff;
|
||||
R[2] = (uint32_t)(( r1 >> 8) ) & 0x3ffffff;
|
||||
R[3] = (uint32_t)(( r1 >> 34) | ( r2 << 10)) & 0x3ffffff;
|
||||
R[4] = (uint32_t)(( r2 >> 16) );
|
||||
|
||||
/* save pad */
|
||||
memcpy(&st->pad[0], key + 16, 8);
|
||||
memcpy(&st->pad[1], key + 24, 8);
|
||||
|
||||
rt0 = r0;
|
||||
rt1 = r1;
|
||||
rt2 = r2;
|
||||
|
||||
/* r^2, r^4 */
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (i == 0) {
|
||||
R = st->R2;
|
||||
if (bytes <= 16) {
|
||||
break;
|
||||
}
|
||||
} else if (i == 1) {
|
||||
R = st->R4;
|
||||
if (bytes < 96) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
st2 = rt2 * (5 << 2);
|
||||
d[0] = ((uint128_t)rt0 * rt0) + ((uint128_t)(rt1 * 2) * st2);
|
||||
d[1] = ((uint128_t)rt2 * st2) + ((uint128_t)(rt0 * 2) * rt1);
|
||||
d[2] = ((uint128_t)rt1 * rt1) + ((uint128_t)(rt2 * 2) * rt0);
|
||||
rt0 = (uint64_t)d[0] & 0xfffffffffff; c = (uint64_t)(d[0] >> 44);
|
||||
d[1] += c ; rt1 = (uint64_t)d[1] & 0xfffffffffff; c = (uint64_t)(d[1] >> 44);
|
||||
d[2] += c ; rt2 = (uint64_t)d[2] & 0x3ffffffffff; c = (uint64_t)(d[2] >> 42);
|
||||
rt0 += c * 5; c = (rt0 >> 44); rt0 = rt0 & 0xfffffffffff;
|
||||
rt1 += c ; c = (rt1 >> 44); rt1 = rt1 & 0xfffffffffff;
|
||||
rt2 += c ; /* even if rt2 overflows, it will still fit in rp4 safely, and is safe to multiply with */
|
||||
|
||||
R[0] = (uint32_t)( rt0 ) & 0x3ffffff;
|
||||
R[1] = (uint32_t)((rt0 >> 26) | (rt1 << 18)) & 0x3ffffff;
|
||||
R[2] = (uint32_t)((rt1 >> 8) ) & 0x3ffffff;
|
||||
R[3] = (uint32_t)((rt1 >> 34) | (rt2 << 10)) & 0x3ffffff;
|
||||
R[4] = (uint32_t)((rt2 >> 16) );
|
||||
}
|
||||
|
||||
st->flags = 0;
|
||||
st->leftover = 0U;
|
||||
}
|
||||
|
||||
static POLY1305_NOINLINE void
|
||||
poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m,
|
||||
unsigned long long bytes)
|
||||
{
|
||||
CRYPTO_ALIGN(64) xmmi HIBIT = _mm_shuffle_epi32(_mm_cvtsi32_si128(1 << 24), _MM_SHUFFLE(1,0,1,0));
|
||||
const xmmi MMASK = _mm_shuffle_epi32(_mm_cvtsi32_si128((1 << 26) - 1), _MM_SHUFFLE(1,0,1,0));
|
||||
const xmmi FIVE = _mm_shuffle_epi32(_mm_cvtsi32_si128(5), _MM_SHUFFLE(1,0,1,0));
|
||||
xmmi H0,H1,H2,H3,H4;
|
||||
xmmi T0,T1,T2,T3,T4,T5,T6,T7,T8;
|
||||
xmmi M0,M1,M2,M3,M4;
|
||||
xmmi M5,M6,M7,M8;
|
||||
xmmi C1,C2;
|
||||
xmmi R20,R21,R22,R23,R24,S21,S22,S23,S24;
|
||||
xmmi R40,R41,R42,R43,R44,S41,S42,S43,S44;
|
||||
|
||||
if (st->flags & poly1305_final_shift8) HIBIT = _mm_srli_si128(HIBIT, 8);
|
||||
if (st->flags & poly1305_final_shift16) HIBIT = _mm_setzero_si128();
|
||||
|
||||
if (!(st->flags & poly1305_started)) {
|
||||
/* H = [Mx,My] */
|
||||
|
||||
T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(const void *)(m + 0)), _mm_loadl_epi64((const xmmi *)(const void *)(m + 16)));
|
||||
T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(const void *)(m + 8)), _mm_loadl_epi64((const xmmi *)(const void *)(m + 24)));
|
||||
H0 = _mm_and_si128(MMASK, T5);
|
||||
H1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
|
||||
T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
|
||||
H2 = _mm_and_si128(MMASK, T5);
|
||||
H3 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
|
||||
H4 = _mm_srli_epi64(T6, 40);
|
||||
H4 = _mm_or_si128(H4, HIBIT);
|
||||
m += 32;
|
||||
bytes -= 32;
|
||||
st->flags |= poly1305_started;
|
||||
} else {
|
||||
T0 = _mm_loadu_si128((const xmmi *)(const void *)&st->hh[0]);
|
||||
T1 = _mm_loadu_si128((const xmmi *)(const void *)&st->hh[4]);
|
||||
T2 = _mm_loadu_si128((const xmmi *)(const void *)&st->hh[8]);
|
||||
H0 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(1,1,0,0));
|
||||
H1 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3,3,2,2));
|
||||
H2 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(1,1,0,0));
|
||||
H3 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(3,3,2,2));
|
||||
H4 = _mm_shuffle_epi32(T2, _MM_SHUFFLE(1,1,0,0));
|
||||
}
|
||||
|
||||
if (st->flags & (poly1305_final_r2_r|poly1305_final_r_1)) {
|
||||
if (st->flags & poly1305_final_r2_r) {
|
||||
/* use [r^2, r] */
|
||||
T2 = _mm_loadu_si128((const xmmi *)(const void *)&st->R[0]);
|
||||
T3 = _mm_cvtsi32_si128(st->R[4]);
|
||||
T0 = _mm_loadu_si128((const xmmi *)(const void *)&st->R2[0]);
|
||||
T1 = _mm_cvtsi32_si128(st->R2[4]);
|
||||
T4 = _mm_unpacklo_epi32(T0, T2);
|
||||
T5 = _mm_unpackhi_epi32(T0, T2);
|
||||
R24 = _mm_unpacklo_epi64(T1, T3);
|
||||
} else {
|
||||
/* use [r^1, 1] */
|
||||
T0 = _mm_loadu_si128((const xmmi *)(const void *)&st->R[0]);
|
||||
T1 = _mm_cvtsi32_si128(st->R[4]);
|
||||
T2 = _mm_cvtsi32_si128(1);
|
||||
T4 = _mm_unpacklo_epi32(T0, T2);
|
||||
T5 = _mm_unpackhi_epi32(T0, T2);
|
||||
R24 = T1;
|
||||
}
|
||||
|
||||
R20 = _mm_shuffle_epi32(T4, _MM_SHUFFLE(1,1,0,0));
|
||||
R21 = _mm_shuffle_epi32(T4, _MM_SHUFFLE(3,3,2,2));
|
||||
R22 = _mm_shuffle_epi32(T5, _MM_SHUFFLE(1,1,0,0));
|
||||
R23 = _mm_shuffle_epi32(T5, _MM_SHUFFLE(3,3,2,2));
|
||||
} else {
|
||||
/* use [r^2, r^2] */
|
||||
T0 = _mm_loadu_si128((const xmmi *)(const void *)&st->R2[0]);
|
||||
T1 = _mm_cvtsi32_si128(st->R2[4]);
|
||||
R20 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(0,0,0,0));
|
||||
R21 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(1,1,1,1));
|
||||
R22 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(2,2,2,2));
|
||||
R23 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3,3,3,3));
|
||||
R24 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(0,0,0,0));
|
||||
}
|
||||
S21 = _mm_mul_epu32(R21, FIVE);
|
||||
S22 = _mm_mul_epu32(R22, FIVE);
|
||||
S23 = _mm_mul_epu32(R23, FIVE);
|
||||
S24 = _mm_mul_epu32(R24, FIVE);
|
||||
|
||||
if (bytes >= 64) {
|
||||
T0 = _mm_loadu_si128((const xmmi *)(const void *)&st->R4[0]);
|
||||
T1 = _mm_cvtsi32_si128(st->R4[4]);
|
||||
R40 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(0,0,0,0));
|
||||
R41 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(1,1,1,1));
|
||||
R42 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(2,2,2,2));
|
||||
R43 = _mm_shuffle_epi32(T0, _MM_SHUFFLE(3,3,3,3));
|
||||
R44 = _mm_shuffle_epi32(T1, _MM_SHUFFLE(0,0,0,0));
|
||||
S41 = _mm_mul_epu32(R41, FIVE);
|
||||
S42 = _mm_mul_epu32(R42, FIVE);
|
||||
S43 = _mm_mul_epu32(R43, FIVE);
|
||||
S44 = _mm_mul_epu32(R44, FIVE);
|
||||
|
||||
while (bytes >= 64) {
|
||||
xmmi v00,v01,v02,v03,v04;
|
||||
xmmi v10,v11,v12,v13,v14;
|
||||
xmmi v20,v21,v22,v23,v24;
|
||||
xmmi v30,v31,v32,v33,v34;
|
||||
xmmi v40,v41,v42,v43,v44;
|
||||
xmmi T14,T15;
|
||||
|
||||
/* H *= [r^4,r^4], preload [Mx,My] */
|
||||
T15 = S42;
|
||||
T0 = H4; T0 = _mm_mul_epu32(T0, S41);
|
||||
v01 = H3; v01 = _mm_mul_epu32(v01, T15);
|
||||
T14 = S43;
|
||||
T1 = H4; T1 = _mm_mul_epu32(T1 , T15);
|
||||
v11 = H3; v11 = _mm_mul_epu32(v11, T14);
|
||||
T2 = H4; T2 = _mm_mul_epu32(T2 , T14); T0 = _mm_add_epi64(T0, v01);
|
||||
T15 = S44;
|
||||
v02 = H2; v02 = _mm_mul_epu32(v02, T14);
|
||||
T3 = H4; T3 = _mm_mul_epu32(T3 , T15); T1 = _mm_add_epi64(T1, v11);
|
||||
v03 = H1; v03 = _mm_mul_epu32(v03, T15);
|
||||
v12 = H2; v12 = _mm_mul_epu32(v12, T15); T0 = _mm_add_epi64(T0, v02);
|
||||
T14 = R40;
|
||||
v21 = H3; v21 = _mm_mul_epu32(v21, T15);
|
||||
v31 = H3; v31 = _mm_mul_epu32(v31, T14); T0 = _mm_add_epi64(T0, v03);
|
||||
T4 = H4; T4 = _mm_mul_epu32(T4 , T14); T1 = _mm_add_epi64(T1, v12);
|
||||
v04 = H0; v04 = _mm_mul_epu32(v04, T14); T2 = _mm_add_epi64(T2, v21);
|
||||
v13 = H1; v13 = _mm_mul_epu32(v13, T14); T3 = _mm_add_epi64(T3, v31);
|
||||
T15 = R41;
|
||||
v22 = H2; v22 = _mm_mul_epu32(v22, T14);
|
||||
v32 = H2; v32 = _mm_mul_epu32(v32, T15); T0 = _mm_add_epi64(T0, v04);
|
||||
v41 = H3; v41 = _mm_mul_epu32(v41, T15); T1 = _mm_add_epi64(T1, v13);
|
||||
v14 = H0; v14 = _mm_mul_epu32(v14, T15); T2 = _mm_add_epi64(T2, v22);
|
||||
T14 = R42;
|
||||
T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(const void *)(m + 0)), _mm_loadl_epi64((const xmmi *)(const void *)(m + 16)));
|
||||
v23 = H1; v23 = _mm_mul_epu32(v23, T15); T3 = _mm_add_epi64(T3, v32);
|
||||
v33 = H1; v33 = _mm_mul_epu32(v33, T14); T4 = _mm_add_epi64(T4, v41);
|
||||
v42 = H2; v42 = _mm_mul_epu32(v42, T14); T1 = _mm_add_epi64(T1, v14);
|
||||
T15 = R43;
|
||||
T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(const void *)(m + 8)), _mm_loadl_epi64((const xmmi *)(const void *)(m + 24)));
|
||||
v24 = H0; v24 = _mm_mul_epu32(v24, T14); T2 = _mm_add_epi64(T2, v23);
|
||||
v34 = H0; v34 = _mm_mul_epu32(v34, T15); T3 = _mm_add_epi64(T3, v33);
|
||||
M0 = _mm_and_si128(MMASK, T5);
|
||||
v43 = H1; v43 = _mm_mul_epu32(v43, T15); T4 = _mm_add_epi64(T4, v42);
|
||||
M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
|
||||
v44 = H0; v44 = _mm_mul_epu32(v44, R44); T2 = _mm_add_epi64(T2, v24);
|
||||
T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
|
||||
T3 = _mm_add_epi64(T3, v34);
|
||||
M3 = _mm_and_si128(MMASK, _mm_srli_epi64(T6, 14));
|
||||
T4 = _mm_add_epi64(T4, v43);
|
||||
M2 = _mm_and_si128(MMASK, T5);
|
||||
T4 = _mm_add_epi64(T4, v44);
|
||||
M4 = _mm_or_si128(_mm_srli_epi64(T6, 40), HIBIT);
|
||||
|
||||
/* H += [Mx',My'] */
|
||||
T5 = _mm_loadu_si128((const xmmi *)(const void *)(m + 32));
|
||||
T6 = _mm_loadu_si128((const xmmi *)(const void *)(m + 48));
|
||||
T7 = _mm_unpacklo_epi32(T5, T6);
|
||||
T8 = _mm_unpackhi_epi32(T5, T6);
|
||||
M5 = _mm_unpacklo_epi32(T7, _mm_setzero_si128());
|
||||
M6 = _mm_unpackhi_epi32(T7, _mm_setzero_si128());
|
||||
M7 = _mm_unpacklo_epi32(T8, _mm_setzero_si128());
|
||||
M8 = _mm_unpackhi_epi32(T8, _mm_setzero_si128());
|
||||
M6 = _mm_slli_epi64(M6, 6);
|
||||
M7 = _mm_slli_epi64(M7, 12);
|
||||
M8 = _mm_slli_epi64(M8, 18);
|
||||
T0 = _mm_add_epi64(T0, M5);
|
||||
T1 = _mm_add_epi64(T1, M6);
|
||||
T2 = _mm_add_epi64(T2, M7);
|
||||
T3 = _mm_add_epi64(T3, M8);
|
||||
T4 = _mm_add_epi64(T4, HIBIT);
|
||||
|
||||
/* H += [Mx,My]*[r^2,r^2] */
|
||||
T15 = S22;
|
||||
v00 = M4; v00 = _mm_mul_epu32(v00, S21);
|
||||
v01 = M3; v01 = _mm_mul_epu32(v01, T15);
|
||||
T14 = S23;
|
||||
v10 = M4; v10 = _mm_mul_epu32(v10, T15);
|
||||
v11 = M3; v11 = _mm_mul_epu32(v11, T14); T0 = _mm_add_epi64(T0, v00);
|
||||
v20 = M4; v20 = _mm_mul_epu32(v20, T14); T0 = _mm_add_epi64(T0, v01);
|
||||
T15 = S24;
|
||||
v02 = M2; v02 = _mm_mul_epu32(v02, T14); T1 = _mm_add_epi64(T1, v10);
|
||||
v30 = M4; v30 = _mm_mul_epu32(v30, T15); T1 = _mm_add_epi64(T1, v11);
|
||||
v03 = M1; v03 = _mm_mul_epu32(v03, T15); T2 = _mm_add_epi64(T2, v20);
|
||||
v12 = M2; v12 = _mm_mul_epu32(v12, T15); T0 = _mm_add_epi64(T0, v02);
|
||||
T14 = R20;
|
||||
v21 = M3; v21 = _mm_mul_epu32(v21, T15); T3 = _mm_add_epi64(T3, v30);
|
||||
v31 = M3; v31 = _mm_mul_epu32(v31, T14); T0 = _mm_add_epi64(T0, v03);
|
||||
v40 = M4; v40 = _mm_mul_epu32(v40, T14); T1 = _mm_add_epi64(T1, v12);
|
||||
v04 = M0; v04 = _mm_mul_epu32(v04, T14); T2 = _mm_add_epi64(T2, v21);
|
||||
v13 = M1; v13 = _mm_mul_epu32(v13, T14); T3 = _mm_add_epi64(T3, v31);
|
||||
T15 = R21;
|
||||
v22 = M2; v22 = _mm_mul_epu32(v22, T14); T4 = _mm_add_epi64(T4, v40);
|
||||
v32 = M2; v32 = _mm_mul_epu32(v32, T15); T0 = _mm_add_epi64(T0, v04);
|
||||
v41 = M3; v41 = _mm_mul_epu32(v41, T15); T1 = _mm_add_epi64(T1, v13);
|
||||
v14 = M0; v14 = _mm_mul_epu32(v14, T15); T2 = _mm_add_epi64(T2, v22);
|
||||
T14 = R22;
|
||||
v23 = M1; v23 = _mm_mul_epu32(v23, T15); T3 = _mm_add_epi64(T3, v32);
|
||||
v33 = M1; v33 = _mm_mul_epu32(v33, T14); T4 = _mm_add_epi64(T4, v41);
|
||||
v42 = M2; v42 = _mm_mul_epu32(v42, T14); T1 = _mm_add_epi64(T1, v14);
|
||||
T15 = R23;
|
||||
v24 = M0; v24 = _mm_mul_epu32(v24, T14); T2 = _mm_add_epi64(T2, v23);
|
||||
v34 = M0; v34 = _mm_mul_epu32(v34, T15); T3 = _mm_add_epi64(T3, v33);
|
||||
v43 = M1; v43 = _mm_mul_epu32(v43, T15); T4 = _mm_add_epi64(T4, v42);
|
||||
v44 = M0; v44 = _mm_mul_epu32(v44, R24); T2 = _mm_add_epi64(T2, v24);
|
||||
T3 = _mm_add_epi64(T3, v34);
|
||||
T4 = _mm_add_epi64(T4, v43);
|
||||
T4 = _mm_add_epi64(T4, v44);
|
||||
|
||||
/* reduce */
|
||||
C1 = _mm_srli_epi64(T0, 26); C2 = _mm_srli_epi64(T3, 26); T0 = _mm_and_si128(T0, MMASK); T3 = _mm_and_si128(T3, MMASK); T1 = _mm_add_epi64(T1, C1); T4 = _mm_add_epi64(T4, C2);
|
||||
C1 = _mm_srli_epi64(T1, 26); C2 = _mm_srli_epi64(T4, 26); T1 = _mm_and_si128(T1, MMASK); T4 = _mm_and_si128(T4, MMASK); T2 = _mm_add_epi64(T2, C1); T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
|
||||
C1 = _mm_srli_epi64(T2, 26); C2 = _mm_srli_epi64(T0, 26); T2 = _mm_and_si128(T2, MMASK); T0 = _mm_and_si128(T0, MMASK); T3 = _mm_add_epi64(T3, C1); T1 = _mm_add_epi64(T1, C2);
|
||||
C1 = _mm_srli_epi64(T3, 26); T3 = _mm_and_si128(T3, MMASK); T4 = _mm_add_epi64(T4, C1);
|
||||
|
||||
/* Final: H = (H*[r^4,r^4] + [Mx,My]*[r^2,r^2] + [Mx',My']) */
|
||||
H0 = T0;
|
||||
H1 = T1;
|
||||
H2 = T2;
|
||||
H3 = T3;
|
||||
H4 = T4;
|
||||
|
||||
m += 64;
|
||||
bytes -= 64;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes >= 32) {
|
||||
xmmi v01,v02,v03,v04;
|
||||
xmmi v11,v12,v13,v14;
|
||||
xmmi v21,v22,v23,v24;
|
||||
xmmi v31,v32,v33,v34;
|
||||
xmmi v41,v42,v43,v44;
|
||||
xmmi T14,T15;
|
||||
|
||||
/* H *= [r^2,r^2] */
|
||||
T15 = S22;
|
||||
T0 = H4; T0 = _mm_mul_epu32(T0, S21);
|
||||
v01 = H3; v01 = _mm_mul_epu32(v01, T15);
|
||||
T14 = S23;
|
||||
T1 = H4; T1 = _mm_mul_epu32(T1 , T15);
|
||||
v11 = H3; v11 = _mm_mul_epu32(v11, T14);
|
||||
T2 = H4; T2 = _mm_mul_epu32(T2 , T14); T0 = _mm_add_epi64(T0, v01);
|
||||
T15 = S24;
|
||||
v02 = H2; v02 = _mm_mul_epu32(v02, T14);
|
||||
T3 = H4; T3 = _mm_mul_epu32(T3 , T15); T1 = _mm_add_epi64(T1, v11);
|
||||
v03 = H1; v03 = _mm_mul_epu32(v03, T15);
|
||||
v12 = H2; v12 = _mm_mul_epu32(v12, T15); T0 = _mm_add_epi64(T0, v02);
|
||||
T14 = R20;
|
||||
v21 = H3; v21 = _mm_mul_epu32(v21, T15);
|
||||
v31 = H3; v31 = _mm_mul_epu32(v31, T14); T0 = _mm_add_epi64(T0, v03);
|
||||
T4 = H4; T4 = _mm_mul_epu32(T4 , T14); T1 = _mm_add_epi64(T1, v12);
|
||||
v04 = H0; v04 = _mm_mul_epu32(v04, T14); T2 = _mm_add_epi64(T2, v21);
|
||||
v13 = H1; v13 = _mm_mul_epu32(v13, T14); T3 = _mm_add_epi64(T3, v31);
|
||||
T15 = R21;
|
||||
v22 = H2; v22 = _mm_mul_epu32(v22, T14);
|
||||
v32 = H2; v32 = _mm_mul_epu32(v32, T15); T0 = _mm_add_epi64(T0, v04);
|
||||
v41 = H3; v41 = _mm_mul_epu32(v41, T15); T1 = _mm_add_epi64(T1, v13);
|
||||
v14 = H0; v14 = _mm_mul_epu32(v14, T15); T2 = _mm_add_epi64(T2, v22);
|
||||
T14 = R22;
|
||||
v23 = H1; v23 = _mm_mul_epu32(v23, T15); T3 = _mm_add_epi64(T3, v32);
|
||||
v33 = H1; v33 = _mm_mul_epu32(v33, T14); T4 = _mm_add_epi64(T4, v41);
|
||||
v42 = H2; v42 = _mm_mul_epu32(v42, T14); T1 = _mm_add_epi64(T1, v14);
|
||||
T15 = R23;
|
||||
v24 = H0; v24 = _mm_mul_epu32(v24, T14); T2 = _mm_add_epi64(T2, v23);
|
||||
v34 = H0; v34 = _mm_mul_epu32(v34, T15); T3 = _mm_add_epi64(T3, v33);
|
||||
v43 = H1; v43 = _mm_mul_epu32(v43, T15); T4 = _mm_add_epi64(T4, v42);
|
||||
v44 = H0; v44 = _mm_mul_epu32(v44, R24); T2 = _mm_add_epi64(T2, v24);
|
||||
T3 = _mm_add_epi64(T3, v34);
|
||||
T4 = _mm_add_epi64(T4, v43);
|
||||
T4 = _mm_add_epi64(T4, v44);
|
||||
|
||||
/* H += [Mx,My] */
|
||||
if (m) {
|
||||
T5 = _mm_loadu_si128((const xmmi *)(const void *)(m + 0));
|
||||
T6 = _mm_loadu_si128((const xmmi *)(const void *)(m + 16));
|
||||
T7 = _mm_unpacklo_epi32(T5, T6);
|
||||
T8 = _mm_unpackhi_epi32(T5, T6);
|
||||
M0 = _mm_unpacklo_epi32(T7, _mm_setzero_si128());
|
||||
M1 = _mm_unpackhi_epi32(T7, _mm_setzero_si128());
|
||||
M2 = _mm_unpacklo_epi32(T8, _mm_setzero_si128());
|
||||
M3 = _mm_unpackhi_epi32(T8, _mm_setzero_si128());
|
||||
M1 = _mm_slli_epi64(M1, 6);
|
||||
M2 = _mm_slli_epi64(M2, 12);
|
||||
M3 = _mm_slli_epi64(M3, 18);
|
||||
T0 = _mm_add_epi64(T0, M0);
|
||||
T1 = _mm_add_epi64(T1, M1);
|
||||
T2 = _mm_add_epi64(T2, M2);
|
||||
T3 = _mm_add_epi64(T3, M3);
|
||||
T4 = _mm_add_epi64(T4, HIBIT);
|
||||
}
|
||||
|
||||
/* reduce */
|
||||
C1 = _mm_srli_epi64(T0, 26); C2 = _mm_srli_epi64(T3, 26); T0 = _mm_and_si128(T0, MMASK); T3 = _mm_and_si128(T3, MMASK); T1 = _mm_add_epi64(T1, C1); T4 = _mm_add_epi64(T4, C2);
|
||||
C1 = _mm_srli_epi64(T1, 26); C2 = _mm_srli_epi64(T4, 26); T1 = _mm_and_si128(T1, MMASK); T4 = _mm_and_si128(T4, MMASK); T2 = _mm_add_epi64(T2, C1); T0 = _mm_add_epi64(T0, _mm_mul_epu32(C2, FIVE));
|
||||
C1 = _mm_srli_epi64(T2, 26); C2 = _mm_srli_epi64(T0, 26); T2 = _mm_and_si128(T2, MMASK); T0 = _mm_and_si128(T0, MMASK); T3 = _mm_add_epi64(T3, C1); T1 = _mm_add_epi64(T1, C2);
|
||||
C1 = _mm_srli_epi64(T3, 26); T3 = _mm_and_si128(T3, MMASK); T4 = _mm_add_epi64(T4, C1);
|
||||
|
||||
/* H = (H*[r^2,r^2] + [Mx,My]) */
|
||||
H0 = T0;
|
||||
H1 = T1;
|
||||
H2 = T2;
|
||||
H3 = T3;
|
||||
H4 = T4;
|
||||
}
|
||||
|
||||
if (m) {
|
||||
T0 = _mm_shuffle_epi32(H0, _MM_SHUFFLE(0,0,2,0));
|
||||
T1 = _mm_shuffle_epi32(H1, _MM_SHUFFLE(0,0,2,0));
|
||||
T2 = _mm_shuffle_epi32(H2, _MM_SHUFFLE(0,0,2,0));
|
||||
T3 = _mm_shuffle_epi32(H3, _MM_SHUFFLE(0,0,2,0));
|
||||
T4 = _mm_shuffle_epi32(H4, _MM_SHUFFLE(0,0,2,0));
|
||||
T0 = _mm_unpacklo_epi64(T0, T1);
|
||||
T1 = _mm_unpacklo_epi64(T2, T3);
|
||||
_mm_storeu_si128((xmmi *)(void *)&st->hh[0], T0);
|
||||
_mm_storeu_si128((xmmi *)(void *)&st->hh[4], T1);
|
||||
_mm_storel_epi64((xmmi *)(void *)&st->hh[8], T4);
|
||||
} else {
|
||||
uint32_t t0,t1,t2,t3,t4,b;
|
||||
uint64_t h0,h1,h2,g0,g1,g2,c,nc;
|
||||
|
||||
/* H = H[0]+H[1] */
|
||||
T0 = H0;
|
||||
T1 = H1;
|
||||
T2 = H2;
|
||||
T3 = H3;
|
||||
T4 = H4;
|
||||
|
||||
T0 = _mm_add_epi64(T0, _mm_srli_si128(T0, 8));
|
||||
T1 = _mm_add_epi64(T1, _mm_srli_si128(T1, 8));
|
||||
T2 = _mm_add_epi64(T2, _mm_srli_si128(T2, 8));
|
||||
T3 = _mm_add_epi64(T3, _mm_srli_si128(T3, 8));
|
||||
T4 = _mm_add_epi64(T4, _mm_srli_si128(T4, 8));
|
||||
|
||||
t0 = _mm_cvtsi128_si32(T0) ; b = (t0 >> 26); t0 &= 0x3ffffff;
|
||||
t1 = _mm_cvtsi128_si32(T1) + b; b = (t1 >> 26); t1 &= 0x3ffffff;
|
||||
t2 = _mm_cvtsi128_si32(T2) + b; b = (t2 >> 26); t2 &= 0x3ffffff;
|
||||
t3 = _mm_cvtsi128_si32(T3) + b; b = (t3 >> 26); t3 &= 0x3ffffff;
|
||||
t4 = _mm_cvtsi128_si32(T4) + b;
|
||||
|
||||
/* everything except t4 is in range, so this is all safe */
|
||||
h0 = (((uint64_t)t0 ) | ((uint64_t)t1 << 26) ) & 0xfffffffffffull;
|
||||
h1 = (((uint64_t)t1 >> 18) | ((uint64_t)t2 << 8) | ((uint64_t)t3 << 34)) & 0xfffffffffffull;
|
||||
h2 = (((uint64_t)t3 >> 10) | ((uint64_t)t4 << 16) );
|
||||
|
||||
c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
|
||||
g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
|
||||
g2 = h2 + c - ((uint64_t)1 << 42);
|
||||
|
||||
c = (g2 >> 63) - 1;
|
||||
nc = ~c;
|
||||
h0 = (h0 & nc) | (g0 & c);
|
||||
h1 = (h1 & nc) | (g1 & c);
|
||||
h2 = (h2 & nc) | (g2 & c);
|
||||
|
||||
st->h[0] = h0;
|
||||
st->h[1] = h1;
|
||||
st->h[2] = h2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
poly1305_update(poly1305_state_internal_t *st, const unsigned char *m,
|
||||
unsigned long long bytes)
|
||||
{
|
||||
unsigned long long i;
|
||||
|
||||
/* handle leftover */
|
||||
if (st->leftover) {
|
||||
unsigned long long want = (poly1305_block_size - st->leftover);
|
||||
|
||||
if (want > bytes)
|
||||
want = bytes;
|
||||
for (i = 0; i < want; i++)
|
||||
st->buffer[st->leftover + i] = m[i];
|
||||
bytes -= want;
|
||||
m += want;
|
||||
st->leftover += want;
|
||||
if (st->leftover < poly1305_block_size)
|
||||
return;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
st->leftover = 0;
|
||||
}
|
||||
|
||||
/* process full blocks */
|
||||
if (bytes >= poly1305_block_size) {
|
||||
unsigned long long want = (bytes & ~(poly1305_block_size - 1));
|
||||
|
||||
poly1305_blocks(st, m, want);
|
||||
m += want;
|
||||
bytes -= want;
|
||||
}
|
||||
|
||||
/* store leftover */
|
||||
if (bytes) {
|
||||
for (i = 0; i < bytes; i++) {
|
||||
st->buffer[st->leftover + i] = m[i];
|
||||
}
|
||||
st->leftover += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static POLY1305_NOINLINE void
|
||||
poly1305_finish_ext(poly1305_state_internal_t *st, const unsigned char *m,
|
||||
unsigned long long leftover, unsigned char mac[16])
|
||||
{
|
||||
uint64_t h0,h1,h2;
|
||||
|
||||
if (leftover) {
|
||||
CRYPTO_ALIGN(16) unsigned char final[32] = {0};
|
||||
poly1305_block_copy31(final, m, leftover);
|
||||
if (leftover != 16) final[leftover] = 1;
|
||||
st->flags |= (leftover >= 16) ? poly1305_final_shift8 : poly1305_final_shift16;
|
||||
poly1305_blocks(st, final, 32);
|
||||
}
|
||||
|
||||
if (st->flags & poly1305_started) {
|
||||
/* finalize, H *= [r^2,r], or H *= [r,1] */
|
||||
if (!leftover || (leftover > 16)) {
|
||||
st->flags |= poly1305_final_r2_r;
|
||||
} else {
|
||||
st->flags |= poly1305_final_r_1;
|
||||
}
|
||||
poly1305_blocks(st, NULL, 32);
|
||||
}
|
||||
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
|
||||
/* pad */
|
||||
h0 = ((h0 ) | (h1 << 44));
|
||||
h1 = ((h1 >> 20) | (h2 << 24));
|
||||
#ifdef HAVE_AMD64_ASM
|
||||
__asm__ __volatile__("addq %2, %0 ;\n"
|
||||
"adcq %3, %1 ;\n"
|
||||
: "+r"(h0), "+r"(h1)
|
||||
: "r"(st->pad[0]), "r"(st->pad[1])
|
||||
: "flags", "cc");
|
||||
#else
|
||||
{
|
||||
uint128_t h;
|
||||
|
||||
memcpy(&h, &st->pad[0], 16);
|
||||
h += ((uint128_t) h1 << 64) | h0;
|
||||
h0 = (uint64_t) h;
|
||||
h1 = (uint64_t) (h >> 64);
|
||||
}
|
||||
#endif
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 0, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 1, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 2, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 3, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 4, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 5, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 6, _mm_setzero_si128());
|
||||
_mm_storeu_si128((xmmi *)(void *)st + 7, _mm_setzero_si128());
|
||||
|
||||
memcpy(&mac[0], &h0, 8);
|
||||
memcpy(&mac[8], &h1, 8);
|
||||
|
||||
sodium_memzero((void *)st, sizeof *st);
|
||||
}
|
||||
|
||||
static void
|
||||
poly1305_finish(poly1305_state_internal_t *st, unsigned char mac[16])
|
||||
{
|
||||
poly1305_finish_ext(st, st->buffer, st->leftover, mac);
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_sse2_init(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *key)
|
||||
{
|
||||
(void) sizeof(int[sizeof (crypto_onetimeauth_poly1305_state) >=
|
||||
sizeof (poly1305_state_internal_t) ? 1 : -1]);
|
||||
poly1305_init_ext((poly1305_state_internal_t *)(void *) state, key, 0U);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_sse2_update(crypto_onetimeauth_poly1305_state *state,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen)
|
||||
{
|
||||
poly1305_update((poly1305_state_internal_t *)(void *) state, in, inlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_sse2_final(crypto_onetimeauth_poly1305_state *state,
|
||||
unsigned char *out)
|
||||
{
|
||||
poly1305_finish((poly1305_state_internal_t *)(void *) state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_sse2(unsigned char *out, const unsigned char *m,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *key)
|
||||
{
|
||||
CRYPTO_ALIGN(64) poly1305_state_internal_t st;
|
||||
unsigned long long blocks;
|
||||
|
||||
poly1305_init_ext(&st, key, inlen);
|
||||
blocks = inlen & ~31;
|
||||
if (blocks > 0) {
|
||||
poly1305_blocks(&st, m, blocks);
|
||||
m += blocks;
|
||||
inlen -= blocks;
|
||||
}
|
||||
poly1305_finish_ext(&st, m, inlen, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_onetimeauth_poly1305_sse2_verify(const unsigned char *h,
|
||||
const unsigned char *in,
|
||||
unsigned long long inlen,
|
||||
const unsigned char *k)
|
||||
{
|
||||
unsigned char correct[16];
|
||||
|
||||
crypto_onetimeauth_poly1305_sse2(correct,in,inlen,k);
|
||||
|
||||
return crypto_verify_16(h,correct);
|
||||
}
|
||||
|
||||
struct crypto_onetimeauth_poly1305_implementation
|
||||
crypto_onetimeauth_poly1305_sse2_implementation = {
|
||||
SODIUM_C99(.onetimeauth =) crypto_onetimeauth_poly1305_sse2,
|
||||
SODIUM_C99(.onetimeauth_verify =) crypto_onetimeauth_poly1305_sse2_verify,
|
||||
SODIUM_C99(.onetimeauth_init =) crypto_onetimeauth_poly1305_sse2_init,
|
||||
SODIUM_C99(.onetimeauth_update =) crypto_onetimeauth_poly1305_sse2_update,
|
||||
SODIUM_C99(.onetimeauth_final =) crypto_onetimeauth_poly1305_sse2_final
|
||||
};
|
||||
|
||||
#endif
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#ifndef poly1305_sse2_H
|
||||
#define poly1305_sse2_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "crypto_onetimeauth_poly1305.h"
|
||||
#include "../onetimeauth_poly1305.h"
|
||||
|
||||
extern struct crypto_onetimeauth_poly1305_implementation
|
||||
crypto_onetimeauth_poly1305_sse2_implementation;
|
||||
|
||||
#endif /* poly1305_sse2_H */
|
||||
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* Argon2 source code package
|
||||
*
|
||||
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
||||
*
|
||||
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication along
|
||||
* with
|
||||
* this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_generichash_blake2b.h"
|
||||
#include "runtime.h"
|
||||
#include "utils.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#include "argon2-core.h"
|
||||
#include "argon2-impl.h"
|
||||
#include "blake2b-long.h"
|
||||
|
||||
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
|
||||
# define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
static fill_segment_fn fill_segment = fill_segment_ref;
|
||||
|
||||
/***************Instance and Position constructors**********/
|
||||
void init_block_value(block *b, uint8_t in) {
|
||||
memset(b->v, in, sizeof(b->v));
|
||||
}
|
||||
|
||||
void copy_block(block *dst, const block *src) {
|
||||
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
|
||||
}
|
||||
|
||||
void xor_block(block *dst, const block *src) {
|
||||
int i;
|
||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
||||
dst->v[i] ^= src->v[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void load_block(block *dst, const void *input) {
|
||||
unsigned i;
|
||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
||||
dst->v[i] = LOAD64_LE((const uint8_t *)input + i * sizeof(dst->v[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void store_block(void *output, const block *src) {
|
||||
unsigned i;
|
||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
||||
STORE64_LE((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/***************Memory allocators*****************/
|
||||
/* Allocates memory to the given pointer
|
||||
* @param memory pointer to the pointer to the memory
|
||||
* @param m_cost number of blocks to allocate in the memory
|
||||
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
|
||||
*/
|
||||
static int allocate_memory(block_region **memory, uint32_t m_cost);
|
||||
|
||||
static int allocate_memory(block_region **region, uint32_t m_cost) {
|
||||
void *base;
|
||||
block *memory;
|
||||
size_t memory_size;
|
||||
|
||||
if (region == NULL) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
memory_size = sizeof(block) * m_cost;
|
||||
if (m_cost == 0 ||
|
||||
memory_size / m_cost != sizeof(block)) { /*1. Check for multiplication overflow*/
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
*region = (block_region *)malloc(sizeof(block_region)); /*2. Try to allocate region*/
|
||||
if (!*region) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
|
||||
#if defined(MAP_ANON) && defined(HAVE_MMAP)
|
||||
if ((base = mmap(NULL, memory_size, PROT_READ | PROT_WRITE,
|
||||
# ifdef MAP_NOCORE
|
||||
MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
|
||||
# else
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
# endif
|
||||
-1, 0)) == MAP_FAILED) {
|
||||
base = NULL; /* LCOV_EXCL_LINE */
|
||||
} /* LCOV_EXCL_LINE */
|
||||
memcpy(&memory, &base, sizeof memory);
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
if ((errno = posix_memalign((void **) &base, 64, memory_size)) != 0) {
|
||||
base = NULL;
|
||||
}
|
||||
memcpy(&memory, &base, sizeof memory);
|
||||
#else
|
||||
memory = NULL;
|
||||
if (memory_size + 63 < memory_size) {
|
||||
base = NULL;
|
||||
errno = ENOMEM;
|
||||
} else if ((base = malloc(memory_size + 63)) != NULL) {
|
||||
uint8_t *aligned = ((uint8_t *) base) + 63;
|
||||
aligned -= (uintptr_t) aligned & 63;
|
||||
memcpy(&memory, &aligned, sizeof memory);
|
||||
}
|
||||
#endif
|
||||
if (base == NULL) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
(*region)->base = base;
|
||||
(*region)->memory = memory;
|
||||
(*region)->size = memory_size;
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
/*********Memory functions*/
|
||||
|
||||
/* Clears memory
|
||||
* @param instance pointer to the current instance
|
||||
* @param clear_memory indicates if we clear the memory with zeros.
|
||||
*/
|
||||
static void clear_memory(argon2_instance_t *instance, int clear);
|
||||
|
||||
static void clear_memory(argon2_instance_t *instance, int clear) {
|
||||
if (instance->region != NULL && clear) {
|
||||
/* LCOV_EXCL_START */
|
||||
sodium_memzero(instance->region->memory,
|
||||
sizeof(block) * instance->memory_blocks);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
|
||||
/* Deallocates memory
|
||||
* @param memory pointer to the blocks
|
||||
*/
|
||||
static void free_memory(block_region *memory);
|
||||
|
||||
static void free_memory(block_region *region) {
|
||||
if (region->base) {
|
||||
#if defined(MAP_ANON) && defined(HAVE_MMAP)
|
||||
if (munmap(region->base, region->size)) {
|
||||
return; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
#else
|
||||
free(region->base);
|
||||
#endif
|
||||
}
|
||||
free(region);
|
||||
}
|
||||
|
||||
void finalize(const argon2_context *context, argon2_instance_t *instance) {
|
||||
if (context != NULL && instance != NULL) {
|
||||
block blockhash;
|
||||
uint32_t l;
|
||||
|
||||
copy_block(&blockhash, instance->region->memory + instance->lane_length - 1);
|
||||
|
||||
/* XOR the last blocks */
|
||||
for (l = 1; l < instance->lanes; ++l) {
|
||||
uint32_t last_block_in_lane =
|
||||
l * instance->lane_length + (instance->lane_length - 1);
|
||||
xor_block(&blockhash, instance->region->memory + last_block_in_lane);
|
||||
}
|
||||
|
||||
/* Hash the result */
|
||||
{
|
||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
||||
store_block(blockhash_bytes, &blockhash);
|
||||
blake2b_long(context->out, context->outlen, blockhash_bytes,
|
||||
ARGON2_BLOCK_SIZE);
|
||||
sodium_memzero(blockhash.v,
|
||||
ARGON2_BLOCK_SIZE); /* clear blockhash */
|
||||
sodium_memzero(blockhash_bytes,
|
||||
ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
|
||||
}
|
||||
|
||||
/* Clear memory */
|
||||
clear_memory(instance, context->flags & ARGON2_FLAG_CLEAR_PASSWORD);
|
||||
|
||||
/* Deallocate the memory */
|
||||
free_memory(instance->region);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t index_alpha(const argon2_instance_t *instance,
|
||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
||||
int same_lane) {
|
||||
/*
|
||||
* Pass 0:
|
||||
* This lane : all already finished segments plus already constructed
|
||||
* blocks in this segment
|
||||
* Other lanes : all already finished segments
|
||||
* Pass 1+:
|
||||
* This lane : (SYNC_POINTS - 1) last segments plus already constructed
|
||||
* blocks in this segment
|
||||
* Other lanes : (SYNC_POINTS - 1) last segments
|
||||
*/
|
||||
uint32_t reference_area_size;
|
||||
uint64_t relative_position;
|
||||
uint32_t start_position, absolute_position;
|
||||
|
||||
if (position->pass == 0) {
|
||||
/* First pass */
|
||||
if (position->slice == 0) {
|
||||
/* First slice */
|
||||
reference_area_size =
|
||||
position->index - 1; /* all but the previous */
|
||||
} else {
|
||||
if (same_lane) {
|
||||
/* The same lane => add current segment */
|
||||
reference_area_size =
|
||||
position->slice * instance->segment_length +
|
||||
position->index - 1;
|
||||
} else {
|
||||
reference_area_size =
|
||||
position->slice * instance->segment_length +
|
||||
((position->index == 0) ? (-1) : 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Second pass */
|
||||
if (same_lane) {
|
||||
reference_area_size = instance->lane_length -
|
||||
instance->segment_length + position->index -
|
||||
1;
|
||||
} else {
|
||||
reference_area_size = instance->lane_length -
|
||||
instance->segment_length +
|
||||
((position->index == 0) ? (-1) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
|
||||
* relative position */
|
||||
relative_position = pseudo_rand;
|
||||
relative_position = relative_position * relative_position >> 32;
|
||||
relative_position = reference_area_size - 1 -
|
||||
(reference_area_size * relative_position >> 32);
|
||||
|
||||
/* 1.2.5 Computing starting position */
|
||||
start_position = 0;
|
||||
|
||||
if (position->pass != 0) {
|
||||
start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
|
||||
? 0
|
||||
: (position->slice + 1) * instance->segment_length;
|
||||
}
|
||||
|
||||
/* 1.2.6. Computing absolute position */
|
||||
absolute_position = (start_position + relative_position) %
|
||||
instance->lane_length; /* absolute position */
|
||||
return absolute_position;
|
||||
}
|
||||
|
||||
int fill_memory_blocks(argon2_instance_t *instance) {
|
||||
int result;
|
||||
uint32_t r, s;
|
||||
|
||||
if (instance == NULL || instance->lanes == 0) {
|
||||
return ARGON2_OK; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
|
||||
for (r = 0; r < instance->passes; ++r) {
|
||||
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
|
||||
uint32_t l;
|
||||
|
||||
for (l = 0; l < instance->lanes; ++l) {
|
||||
argon2_position_t position;
|
||||
|
||||
position.pass = r;
|
||||
position.lane = l;
|
||||
position.slice = (uint8_t)s;
|
||||
position.index = 0;
|
||||
result = fill_segment(instance, position);
|
||||
if (ARGON2_OK != result) {
|
||||
return result; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int validate_inputs(const argon2_context *context) {
|
||||
/* LCOV_EXCL_START */
|
||||
if (NULL == context) {
|
||||
return ARGON2_INCORRECT_PARAMETER;
|
||||
}
|
||||
|
||||
if (NULL == context->out) {
|
||||
return ARGON2_OUTPUT_PTR_NULL;
|
||||
}
|
||||
|
||||
/* Validate output length */
|
||||
if (ARGON2_MIN_OUTLEN > context->outlen) {
|
||||
return ARGON2_OUTPUT_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_OUTLEN < context->outlen) {
|
||||
return ARGON2_OUTPUT_TOO_LONG;
|
||||
}
|
||||
|
||||
/* Validate password length */
|
||||
if (NULL == context->pwd) {
|
||||
if (0 != context->pwdlen) {
|
||||
return ARGON2_PWD_PTR_MISMATCH;
|
||||
}
|
||||
} else {
|
||||
if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
|
||||
return ARGON2_PWD_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
|
||||
return ARGON2_PWD_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate salt length */
|
||||
if (NULL == context->salt) {
|
||||
if (0 != context->saltlen) {
|
||||
return ARGON2_SALT_PTR_MISMATCH;
|
||||
}
|
||||
} else {
|
||||
if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
|
||||
return ARGON2_SALT_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
|
||||
return ARGON2_SALT_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate secret length */
|
||||
if (NULL == context->secret) {
|
||||
if (0 != context->secretlen) {
|
||||
return ARGON2_SECRET_PTR_MISMATCH;
|
||||
}
|
||||
} else {
|
||||
if (ARGON2_MIN_SECRET > context->secretlen) {
|
||||
return ARGON2_SECRET_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_SECRET < context->secretlen) {
|
||||
return ARGON2_SECRET_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate associated data */
|
||||
if (NULL == context->ad) {
|
||||
if (0 != context->adlen) {
|
||||
return ARGON2_AD_PTR_MISMATCH;
|
||||
}
|
||||
} else {
|
||||
if (ARGON2_MIN_AD_LENGTH > context->adlen) {
|
||||
return ARGON2_AD_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_AD_LENGTH < context->adlen) {
|
||||
return ARGON2_AD_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate memory cost */
|
||||
if (ARGON2_MIN_MEMORY > context->m_cost) {
|
||||
return ARGON2_MEMORY_TOO_LITTLE;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_MEMORY < context->m_cost) {
|
||||
return ARGON2_MEMORY_TOO_MUCH;
|
||||
}
|
||||
|
||||
if (context->m_cost < 8 * context->lanes) {
|
||||
return ARGON2_MEMORY_TOO_LITTLE;
|
||||
}
|
||||
|
||||
/* Validate time cost */
|
||||
if (ARGON2_MIN_TIME > context->t_cost) {
|
||||
return ARGON2_TIME_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_TIME < context->t_cost) {
|
||||
return ARGON2_TIME_TOO_LARGE;
|
||||
}
|
||||
|
||||
/* Validate lanes */
|
||||
if (ARGON2_MIN_LANES > context->lanes) {
|
||||
return ARGON2_LANES_TOO_FEW;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_LANES < context->lanes) {
|
||||
return ARGON2_LANES_TOO_MANY;
|
||||
}
|
||||
|
||||
/* Validate threads */
|
||||
if (ARGON2_MIN_THREADS > context->threads) {
|
||||
return ARGON2_THREADS_TOO_FEW;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_THREADS < context->threads) {
|
||||
return ARGON2_THREADS_TOO_MANY;
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
||||
uint32_t l;
|
||||
/* Make the first and second block in each lane as G(H0||i||0) or
|
||||
G(H0||i||1) */
|
||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
||||
for (l = 0; l < instance->lanes; ++l) {
|
||||
|
||||
STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
|
||||
STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
|
||||
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
|
||||
ARGON2_PREHASH_SEED_LENGTH);
|
||||
load_block(&instance->region->memory[l * instance->lane_length + 0],
|
||||
blockhash_bytes);
|
||||
|
||||
STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
|
||||
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
|
||||
ARGON2_PREHASH_SEED_LENGTH);
|
||||
load_block(&instance->region->memory[l * instance->lane_length + 1],
|
||||
blockhash_bytes);
|
||||
}
|
||||
sodium_memzero(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||
argon2_type type) {
|
||||
crypto_generichash_blake2b_state BlakeHash;
|
||||
uint8_t value[4U /* sizeof(uint32_t) */];
|
||||
|
||||
if (NULL == context || NULL == blockhash) {
|
||||
return; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
|
||||
crypto_generichash_blake2b_init(&BlakeHash, NULL, 0U,
|
||||
ARGON2_PREHASH_DIGEST_LENGTH);
|
||||
|
||||
STORE32_LE(value, context->lanes);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
STORE32_LE(value, context->outlen);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
STORE32_LE(value, context->m_cost);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
STORE32_LE(value, context->t_cost);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
STORE32_LE(value, ARGON2_VERSION_NUMBER);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
STORE32_LE(value, (uint32_t)type);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
STORE32_LE(value, context->pwdlen);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
if (context->pwd != NULL) {
|
||||
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
|
||||
context->pwdlen);
|
||||
|
||||
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
|
||||
sodium_memzero(context->pwd, context->pwdlen); /* LCOV_EXCL_LINE */
|
||||
context->pwdlen = 0; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
}
|
||||
|
||||
STORE32_LE(value, context->saltlen);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
if (context->salt != NULL) {
|
||||
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
|
||||
context->saltlen);
|
||||
}
|
||||
|
||||
STORE32_LE(value, context->secretlen);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
if (context->secret != NULL) {
|
||||
/* LCOV_EXCL_START */
|
||||
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
|
||||
context->secretlen);
|
||||
|
||||
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
|
||||
sodium_memzero(context->secret, context->secretlen);
|
||||
context->secretlen = 0;
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
STORE32_LE(value, context->adlen);
|
||||
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
|
||||
|
||||
if (context->ad != NULL) {
|
||||
/* LCOV_EXCL_START */
|
||||
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
|
||||
context->adlen);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
crypto_generichash_blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
int initialize(argon2_instance_t *instance, argon2_context *context) {
|
||||
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
||||
int result = ARGON2_OK;
|
||||
|
||||
if (instance == NULL || context == NULL)
|
||||
return ARGON2_INCORRECT_PARAMETER;
|
||||
|
||||
/* 1. Memory allocation */
|
||||
|
||||
result = allocate_memory(&(instance->region), instance->memory_blocks);
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 2. Initial hashing */
|
||||
/* H_0 + 8 extra bytes to produce the first blocks */
|
||||
/* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
|
||||
/* Hashing all inputs */
|
||||
initial_hash(blockhash, context, instance->type);
|
||||
/* Zeroing 8 extra bytes */
|
||||
sodium_memzero(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
|
||||
ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
|
||||
|
||||
/* 3. Creating first blocks, we always have at least two blocks in a slice
|
||||
*/
|
||||
fill_first_blocks(blockhash, instance);
|
||||
/* Clearing the hash */
|
||||
sodium_memzero(blockhash, ARGON2_PREHASH_SEED_LENGTH);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int argon2_pick_best_implementation(void)
|
||||
{
|
||||
/* LCOV_EXCL_START */
|
||||
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
if (sodium_runtime_has_ssse3()) {
|
||||
fill_segment = fill_segment_ssse3;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
fill_segment = fill_segment_ref;
|
||||
|
||||
return 0;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Argon2 source code package
|
||||
*
|
||||
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
||||
*
|
||||
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication along
|
||||
* with
|
||||
* this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#ifndef argon2_core_H
|
||||
#define argon2_core_H
|
||||
|
||||
#include "argon2.h"
|
||||
|
||||
/*************************Argon2 internal
|
||||
* constants**************************************************/
|
||||
|
||||
enum argon2_ctx_constants {
|
||||
/* Version of the algorithm */
|
||||
ARGON2_VERSION_NUMBER = 0x13,
|
||||
|
||||
/* Memory block size in bytes */
|
||||
ARGON2_BLOCK_SIZE = 1024,
|
||||
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
|
||||
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
|
||||
|
||||
/* Number of pseudo-random values generated by one call to Blake in Argon2i
|
||||
to
|
||||
generate reference block positions */
|
||||
ARGON2_ADDRESSES_IN_BLOCK = 128,
|
||||
|
||||
/* Pre-hashing digest length and its extension*/
|
||||
ARGON2_PREHASH_DIGEST_LENGTH = 64,
|
||||
ARGON2_PREHASH_SEED_LENGTH = 72
|
||||
};
|
||||
|
||||
/*************************Argon2 internal data
|
||||
* types**************************************************/
|
||||
|
||||
/*
|
||||
* Structure for the (1KB) memory block implemented as 128 64-bit words.
|
||||
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
|
||||
* bounds checking).
|
||||
*/
|
||||
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
|
||||
|
||||
typedef struct block_region_ {
|
||||
void *base;
|
||||
block *memory;
|
||||
size_t size;
|
||||
} block_region;
|
||||
|
||||
/*****************Functions that work with the block******************/
|
||||
|
||||
/* Initialize each byte of the block with @in */
|
||||
void init_block_value(block *b, uint8_t in);
|
||||
|
||||
/* Copy block @src to block @dst */
|
||||
void copy_block(block *dst, const block *src);
|
||||
|
||||
/* XOR @src onto @dst bytewise */
|
||||
void xor_block(block *dst, const block *src);
|
||||
|
||||
/*
|
||||
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
|
||||
* and derived values.
|
||||
* Used to evaluate the number and location of blocks to construct in each
|
||||
* thread
|
||||
*/
|
||||
typedef struct Argon2_instance_t {
|
||||
block_region *region; /* Memory region pointer */
|
||||
uint32_t passes; /* Number of passes */
|
||||
uint32_t memory_blocks; /* Number of blocks in memory */
|
||||
uint32_t segment_length;
|
||||
uint32_t lane_length;
|
||||
uint32_t lanes;
|
||||
uint32_t threads;
|
||||
argon2_type type;
|
||||
int print_internals; /* whether to print the memory blocks */
|
||||
} argon2_instance_t;
|
||||
|
||||
/*
|
||||
* Argon2 position: where we construct the block right now. Used to distribute
|
||||
* work between threads.
|
||||
*/
|
||||
typedef struct Argon2_position_t {
|
||||
uint32_t pass;
|
||||
uint32_t lane;
|
||||
uint8_t slice;
|
||||
uint32_t index;
|
||||
} argon2_position_t;
|
||||
|
||||
/*Struct that holds the inputs for thread handling FillSegment*/
|
||||
typedef struct Argon2_thread_data {
|
||||
argon2_instance_t *instance_ptr;
|
||||
argon2_position_t pos;
|
||||
} argon2_thread_data;
|
||||
|
||||
/*************************Argon2 core
|
||||
* functions**************************************************/
|
||||
|
||||
/*
|
||||
* Computes absolute position of reference block in the lane following a skewed
|
||||
* distribution and using a pseudo-random value as input
|
||||
* @param instance Pointer to the current instance
|
||||
* @param position Pointer to the current position
|
||||
* @param pseudo_rand 32-bit pseudo-random value used to determine the position
|
||||
* @param same_lane Indicates if the block will be taken from the current lane.
|
||||
* If so we can reference the current segment
|
||||
* @pre All pointers must be valid
|
||||
*/
|
||||
uint32_t index_alpha(const argon2_instance_t *instance,
|
||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
||||
int same_lane);
|
||||
|
||||
/*
|
||||
* Function that validates all inputs against predefined restrictions and return
|
||||
* an error code
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @return ARGON2_OK if everything is all right, otherwise one of error codes
|
||||
* (all defined in <argon2.h>
|
||||
*/
|
||||
int validate_inputs(const argon2_context *context);
|
||||
|
||||
/*
|
||||
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
|
||||
* password and secret if needed
|
||||
* @param context Pointer to the Argon2 internal structure containing memory
|
||||
* pointer, and parameters for time and space requirements.
|
||||
* @param blockhash Buffer for pre-hashing digest
|
||||
* @param type Argon2 type
|
||||
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
|
||||
* allocated
|
||||
*/
|
||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||
argon2_type type);
|
||||
|
||||
/*
|
||||
* Function creates first 2 blocks per lane
|
||||
* @param instance Pointer to the current instance
|
||||
* @param blockhash Pointer to the pre-hashing digest
|
||||
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
|
||||
*/
|
||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
|
||||
|
||||
/*
|
||||
* Function allocates memory, hashes the inputs with Blake, and creates first
|
||||
* two blocks. Returns the pointer to the main memory with 2 blocks per lane
|
||||
* initialized
|
||||
* @param context Pointer to the Argon2 internal structure containing memory
|
||||
* pointer, and parameters for time and space requirements.
|
||||
* @param instance Current Argon2 instance
|
||||
* @return Zero if successful, -1 if memory failed to allocate. @context->state
|
||||
* will be modified if successful.
|
||||
*/
|
||||
int initialize(argon2_instance_t *instance, argon2_context *context);
|
||||
|
||||
/*
|
||||
* XORing the last block of each lane, hashing it, making the tag. Deallocates
|
||||
* the memory.
|
||||
* @param context Pointer to current Argon2 context (use only the out parameters
|
||||
* from it)
|
||||
* @param instance Pointer to current instance of Argon2
|
||||
* @pre instance->state must point to necessary amount of memory
|
||||
* @pre context->out must point to outlen bytes of memory
|
||||
* @pre if context->free_cbk is not NULL, it should point to a function that
|
||||
* deallocates memory
|
||||
*/
|
||||
void finalize(const argon2_context *context, argon2_instance_t *instance);
|
||||
|
||||
/*
|
||||
* Function that fills the segment using previous segments also from other
|
||||
* threads
|
||||
* @param instance Pointer to the current instance
|
||||
* @param position Current position
|
||||
* @pre all block pointers must be valid
|
||||
*/
|
||||
typedef int (*fill_segment_fn)(const argon2_instance_t *instance,
|
||||
argon2_position_t position);
|
||||
int argon2_pick_best_implementation(void);
|
||||
int fill_segment_ssse3(const argon2_instance_t *instance,
|
||||
argon2_position_t position);
|
||||
int fill_segment_ref(const argon2_instance_t *instance,
|
||||
argon2_position_t position);
|
||||
|
||||
/*
|
||||
* Function that fills the entire memory t_cost times based on the first two
|
||||
* blocks in each lane
|
||||
* @param instance Pointer to the current instance
|
||||
* @return Zero if successful, -1 if memory failed to allocate
|
||||
*/
|
||||
int fill_memory_blocks(argon2_instance_t *instance);
|
||||
|
||||
#endif
|
||||
+443
@@ -0,0 +1,443 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "argon2-core.h"
|
||||
#include "argon2-encoding.h"
|
||||
|
||||
/*
|
||||
* Example code for a decoder and encoder of "hash strings", with Argon2
|
||||
* parameters.
|
||||
*
|
||||
* This code comprises three sections:
|
||||
*
|
||||
* -- The first section contains generic Base64 encoding and decoding
|
||||
* functions. It is conceptually applicable to any hash function
|
||||
* implementation that uses Base64 to encode and decode parameters,
|
||||
* salts and outputs. It could be made into a library, provided that
|
||||
* the relevant functions are made public (non-static) and be given
|
||||
* reasonable names to avoid collisions with other functions.
|
||||
*
|
||||
* -- The second section is specific to Argon2. It encodes and decodes
|
||||
* the parameters, salts and outputs. It does not compute the hash
|
||||
* itself.
|
||||
*
|
||||
* -- The third section is test code, with a main() function. With
|
||||
* this section, the whole file compiles as a stand-alone program
|
||||
* that exercises the encoding and decoding functions with some
|
||||
* test vectors.
|
||||
*
|
||||
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
|
||||
* to whom comments and remarks may be sent. It is released under what
|
||||
* should amount to Public Domain or its closest equivalent; the
|
||||
* following mantra is supposed to incarnate that fact with all the
|
||||
* proper legal rituals:
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
* This file is provided under the terms of Creative Commons CC0 1.0
|
||||
* Public Domain Dedication. To the extent possible under law, the
|
||||
* author (Thomas Pornin) has waived all copyright and related or
|
||||
* neighboring rights to this file. This work is published from: Canada.
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2015 Thomas Pornin
|
||||
*/
|
||||
|
||||
/* ==================================================================== */
|
||||
/*
|
||||
* Common code; could be shared between different hash functions.
|
||||
*
|
||||
* Note: the Base64 functions below assume that uppercase letters (resp.
|
||||
* lowercase letters) have consecutive numerical codes, that fit on 8
|
||||
* bits. All modern systems use ASCII-compatible charsets, where these
|
||||
* properties are true. If you are stuck with a dinosaur of a system
|
||||
* that still defaults to EBCDIC then you already have much bigger
|
||||
* interoperability issues to deal with.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some macros for constant-time comparisons. These work over values in
|
||||
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
|
||||
*/
|
||||
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
|
||||
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
|
||||
#define GE(x, y) (GT(y, x) ^ 0xFF)
|
||||
#define LT(x, y) GT(y, x)
|
||||
#define LE(x, y) GE(y, x)
|
||||
|
||||
/*
|
||||
* Convert value x (0..63) to corresponding Base64 character.
|
||||
*/
|
||||
static int b64_byte_to_char(unsigned x) {
|
||||
return (LT(x, 26) & (x + 'A')) |
|
||||
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
|
||||
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
|
||||
(EQ(x, 63) & '/');
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert character c to the corresponding 6-bit value. If character c
|
||||
* is not a Base64 character, then 0xFF (255) is returned.
|
||||
*/
|
||||
static unsigned b64_char_to_byte(int c) {
|
||||
unsigned x;
|
||||
|
||||
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
|
||||
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
|
||||
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
|
||||
(EQ(c, '/') & 63);
|
||||
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
|
||||
* of the output buffer 'dst'; if that buffer is not large enough to
|
||||
* receive the result (including the terminating 0), then (size_t)-1
|
||||
* is returned. Otherwise, the zero-terminated Base64 string is written
|
||||
* in the buffer, and the output length (counted WITHOUT the terminating
|
||||
* zero) is returned.
|
||||
*/
|
||||
static size_t to_base64(char *dst, size_t dst_len, const void *src,
|
||||
size_t src_len) {
|
||||
size_t olen;
|
||||
const unsigned char *buf;
|
||||
unsigned acc, acc_len;
|
||||
|
||||
olen = (src_len / 3) << 2;
|
||||
switch (src_len % 3) {
|
||||
case 2:
|
||||
olen++;
|
||||
/* fall through */
|
||||
case 1:
|
||||
olen += 2;
|
||||
break;
|
||||
}
|
||||
if (dst_len <= olen) {
|
||||
return (size_t)-1;
|
||||
}
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
buf = (const unsigned char *)src;
|
||||
while (src_len-- > 0) {
|
||||
acc = (acc << 8) + (*buf++);
|
||||
acc_len += 8;
|
||||
while (acc_len >= 6) {
|
||||
acc_len -= 6;
|
||||
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
|
||||
}
|
||||
}
|
||||
if (acc_len > 0) {
|
||||
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
|
||||
}
|
||||
*dst++ = 0;
|
||||
return olen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode Base64 chars into bytes. The '*dst_len' value must initially
|
||||
* contain the length of the output buffer '*dst'; when the decoding
|
||||
* ends, the actual number of decoded bytes is written back in
|
||||
* '*dst_len'.
|
||||
*
|
||||
* Decoding stops when a non-Base64 character is encountered, or when
|
||||
* the output buffer capacity is exceeded. If an error occurred (output
|
||||
* buffer is too small, invalid last characters leading to unprocessed
|
||||
* buffered bits), then NULL is returned; otherwise, the returned value
|
||||
* points to the first non-Base64 character in the source stream, which
|
||||
* may be the terminating zero.
|
||||
*/
|
||||
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
unsigned acc, acc_len;
|
||||
|
||||
buf = (unsigned char *)dst;
|
||||
len = 0;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
for (;;) {
|
||||
unsigned d;
|
||||
|
||||
d = b64_char_to_byte(*src);
|
||||
if (d == 0xFF) {
|
||||
break;
|
||||
}
|
||||
src++;
|
||||
acc = (acc << 6) + d;
|
||||
acc_len += 6;
|
||||
if (acc_len >= 8) {
|
||||
acc_len -= 8;
|
||||
if ((len++) >= *dst_len) {
|
||||
return NULL;
|
||||
}
|
||||
*buf++ = (acc >> acc_len) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the input length is equal to 1 modulo 4 (which is
|
||||
* invalid), then there will remain 6 unprocessed bits;
|
||||
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
|
||||
* bits must also all be zero.
|
||||
*/
|
||||
if (acc_len > 4 || (acc & ((1U << acc_len) - 1)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
*dst_len = len;
|
||||
return src;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode decimal integer from 'str'; the value is written in '*v'.
|
||||
* Returned value is a pointer to the next non-decimal character in the
|
||||
* string. If there is no digit at all, or the value encoding is not
|
||||
* minimal (extra leading zeros), or the value does not fit in an
|
||||
* 'unsigned long', then NULL is returned.
|
||||
*/
|
||||
static const char *decode_decimal(const char *str, unsigned long *v) {
|
||||
const char *orig;
|
||||
unsigned long acc;
|
||||
|
||||
acc = 0;
|
||||
for (orig = str;; str++) {
|
||||
int c;
|
||||
|
||||
c = *str;
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
c -= '0';
|
||||
if (acc > (ULONG_MAX / 10)) {
|
||||
return NULL;
|
||||
}
|
||||
acc *= 10;
|
||||
if ((unsigned long)c > (ULONG_MAX - acc)) {
|
||||
return NULL;
|
||||
}
|
||||
acc += (unsigned long)c;
|
||||
}
|
||||
if (str == orig || (*orig == '0' && str != (orig + 1))) {
|
||||
return NULL;
|
||||
}
|
||||
*v = acc;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/*
|
||||
* Code specific to Argon2.
|
||||
*
|
||||
* The code below applies the following format:
|
||||
*
|
||||
* $argon2<T>$v=<num>$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
|
||||
*
|
||||
* where <T> is either 'd' or 'i', <num> is a decimal integer (positive, fits in an 'unsigned long')
|
||||
* and <bin> is Base64-encoded data (no '=' padding characters, no newline
|
||||
* or whitespace). The "keyid" is a binary identifier for a key (up to 8
|
||||
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
|
||||
* (resp. the 'data') is empty, then it is ommitted from the output.
|
||||
*
|
||||
* The last two binary chunks (encoded in Base64) are, in that order,
|
||||
* the salt and the output. Both are optional, but you cannot have an
|
||||
* output without a salt. The binary salt length is between 8 and 48 bytes.
|
||||
* The output length is always exactly 32 bytes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Decode an Argon2i hash string into the provided structure 'ctx'.
|
||||
* Returned value is ARGON2_OK on success.
|
||||
*/
|
||||
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
|
||||
/* Prefix checking */
|
||||
#define CC(prefix) \
|
||||
do { \
|
||||
size_t cc_len = strlen(prefix); \
|
||||
if (strncmp(str, prefix, cc_len) != 0) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
str += cc_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
/* Prefix checking with supplied code */
|
||||
#define CC_opt(prefix, code) \
|
||||
do { \
|
||||
size_t cc_len = strlen(prefix); \
|
||||
if (strncmp(str, prefix, cc_len) == 0) { \
|
||||
str += cc_len; \
|
||||
{ code; } \
|
||||
} \
|
||||
} while ((void)0, 0)
|
||||
|
||||
/* Decoding prefix into decimal */
|
||||
#define DECIMAL(x) \
|
||||
do { \
|
||||
unsigned long dec_x; \
|
||||
str = decode_decimal(str, &dec_x); \
|
||||
if (str == NULL) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
(x) = dec_x; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
/* Decoding prefix into binary */
|
||||
#define BIN(buf, max_len, len) \
|
||||
do { \
|
||||
size_t bin_len = (max_len); \
|
||||
str = from_base64(buf, &bin_len, str); \
|
||||
if (str == NULL || bin_len > UINT32_MAX) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
(len) = (uint32_t)bin_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
size_t maxadlen = ctx->adlen;
|
||||
size_t maxsaltlen = ctx->saltlen;
|
||||
size_t maxoutlen = ctx->outlen;
|
||||
unsigned long version = 0;
|
||||
int validation_result;
|
||||
|
||||
ctx->adlen = 0;
|
||||
ctx->saltlen = 0;
|
||||
ctx->outlen = 0;
|
||||
if (type == Argon2_i) {
|
||||
CC("$argon2i");
|
||||
} else {
|
||||
return ARGON2_INCORRECT_TYPE;
|
||||
}
|
||||
CC("$v=");
|
||||
DECIMAL(version);
|
||||
if (version != ARGON2_VERSION_NUMBER) {
|
||||
return ARGON2_INCORRECT_TYPE;
|
||||
}
|
||||
CC("$m=");
|
||||
DECIMAL(ctx->m_cost);
|
||||
CC(",t=");
|
||||
DECIMAL(ctx->t_cost);
|
||||
CC(",p=");
|
||||
DECIMAL(ctx->lanes);
|
||||
ctx->threads = ctx->lanes;
|
||||
|
||||
CC_opt(",data=", BIN(ctx->ad, maxadlen, ctx->adlen));
|
||||
if (*str == 0) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
CC("$");
|
||||
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
|
||||
if (*str == 0) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
CC("$");
|
||||
BIN(ctx->out, maxoutlen, ctx->outlen);
|
||||
validation_result = validate_inputs(ctx);
|
||||
if (validation_result != ARGON2_OK) {
|
||||
return validation_result;
|
||||
}
|
||||
if (*str == 0) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
return ARGON2_DECODING_FAIL;
|
||||
|
||||
#undef CC
|
||||
#undef CC_opt
|
||||
#undef DECIMAL
|
||||
#undef BIN
|
||||
}
|
||||
|
||||
#define U32_STR_MAXSIZE 11U
|
||||
|
||||
static void u32_to_string(char *str, uint32_t x) {
|
||||
char tmp[U32_STR_MAXSIZE - 1U];
|
||||
size_t i;
|
||||
|
||||
i = sizeof tmp;
|
||||
do {
|
||||
tmp[--i] = (x % (uint32_t) 10U) + '0';
|
||||
x /= (uint32_t) 10U;
|
||||
} while (x != 0U && i != 0U);
|
||||
memcpy(str, &tmp[i], (sizeof tmp) - i);
|
||||
str[(sizeof tmp) - i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an argon2i hash string into the provided buffer. 'dst_len'
|
||||
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
|
||||
* is less than the number of required characters (including the
|
||||
* terminating 0), then this function returns 0.
|
||||
*
|
||||
* If pp->output_len is 0, then the hash string will be a salt string
|
||||
* (no output). if pp->salt_len is also 0, then the string will be a
|
||||
* parameter-only string (no salt and no output).
|
||||
*
|
||||
* On success, ARGON2_OK is returned.
|
||||
*/
|
||||
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
||||
argon2_type type) {
|
||||
#define SS(str) \
|
||||
do { \
|
||||
size_t pp_len = strlen(str); \
|
||||
if (pp_len >= dst_len) { \
|
||||
return ARGON2_ENCODING_FAIL; \
|
||||
} \
|
||||
memcpy(dst, str, pp_len + 1); \
|
||||
dst += pp_len; \
|
||||
dst_len -= pp_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define SX(x) \
|
||||
do { \
|
||||
char tmp[U32_STR_MAXSIZE]; \
|
||||
u32_to_string(tmp, x); \
|
||||
SS(tmp); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define SB(buf, len) \
|
||||
do { \
|
||||
size_t sb_len = to_base64(dst, dst_len, buf, len); \
|
||||
if (sb_len == (size_t)-1) { \
|
||||
return ARGON2_ENCODING_FAIL; \
|
||||
} \
|
||||
dst += sb_len; \
|
||||
dst_len -= sb_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
int validation_result;
|
||||
|
||||
if (type == Argon2_i) {
|
||||
SS("$argon2i$v=");
|
||||
} else {
|
||||
return ARGON2_ENCODING_FAIL;
|
||||
}
|
||||
validation_result = validate_inputs(ctx);
|
||||
if (validation_result != ARGON2_OK) {
|
||||
return validation_result;
|
||||
}
|
||||
SX(ARGON2_VERSION_NUMBER);
|
||||
SS("$m=");
|
||||
SX(ctx->m_cost);
|
||||
SS(",t=");
|
||||
SX(ctx->t_cost);
|
||||
SS(",p=");
|
||||
SX(ctx->lanes);
|
||||
|
||||
if (ctx->adlen > 0) {
|
||||
SS(",data=");
|
||||
SB(ctx->ad, ctx->adlen);
|
||||
}
|
||||
|
||||
if (ctx->saltlen == 0) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
SS("$");
|
||||
SB(ctx->salt, ctx->saltlen);
|
||||
|
||||
if (ctx->outlen == 0) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
SS("$");
|
||||
SB(ctx->out, ctx->outlen);
|
||||
return ARGON2_OK;
|
||||
|
||||
#undef SS
|
||||
#undef SX
|
||||
#undef SB
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef argon2_encoding_H
|
||||
#define argon2_encoding_H
|
||||
|
||||
#include "argon2.h"
|
||||
|
||||
/*
|
||||
* encode an Argon2 hash string into the provided buffer. 'dst_len'
|
||||
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
|
||||
* is less than the number of required characters (including the
|
||||
* terminating 0), then this function returns 0.
|
||||
*
|
||||
* if ctx->outlen is 0, then the hash string will be a salt string
|
||||
* (no output). if ctx->saltlen is also 0, then the string will be a
|
||||
* parameter-only string (no salt and no output).
|
||||
*
|
||||
* On success, ARGON2_OK is returned.
|
||||
*
|
||||
* No other parameters are checked
|
||||
*/
|
||||
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
||||
argon2_type type);
|
||||
|
||||
/*
|
||||
* Decodes an Argon2 hash string into the provided structure 'ctx'.
|
||||
* The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out length values
|
||||
* that are allowed; invalid input string causes an error
|
||||
*
|
||||
* Returned value is ARGON2_OK on success.
|
||||
*/
|
||||
int decode_string(argon2_context *ctx, const char *str, argon2_type type);
|
||||
|
||||
#endif
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Argon2 source code package
|
||||
*
|
||||
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
||||
*
|
||||
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication along
|
||||
* with
|
||||
* this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "argon2-core.h"
|
||||
#include "argon2-impl.h"
|
||||
#include "blamka-round-ref.h"
|
||||
|
||||
static void fill_block(const block *prev_block, const block *ref_block,
|
||||
block *next_block) {
|
||||
block blockR, block_tmp;
|
||||
unsigned i;
|
||||
|
||||
copy_block(&blockR, ref_block);
|
||||
xor_block(&blockR, prev_block);
|
||||
copy_block(&block_tmp, &blockR);
|
||||
/* Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block
|
||||
Apply Blake2 on columns of 64-bit words: (0,1,...,15), then
|
||||
(16,17,..31)... finally (112,113,...127) */
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND_NOMSG(
|
||||
blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
|
||||
blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
|
||||
blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
|
||||
blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
|
||||
blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
|
||||
blockR.v[16 * i + 15]);
|
||||
}
|
||||
|
||||
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
|
||||
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
|
||||
for (i = 0; i < 8; i++) {
|
||||
BLAKE2_ROUND_NOMSG(
|
||||
blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
|
||||
blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
|
||||
blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
|
||||
blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
|
||||
blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
|
||||
blockR.v[2 * i + 113]);
|
||||
}
|
||||
|
||||
copy_block(next_block, &block_tmp);
|
||||
xor_block(next_block, &blockR);
|
||||
}
|
||||
|
||||
static void fill_block_with_xor(const block *prev_block, const block *ref_block,
|
||||
block *next_block) {
|
||||
block blockR, block_tmp;
|
||||
unsigned i;
|
||||
|
||||
copy_block(&blockR, ref_block);
|
||||
xor_block(&blockR, prev_block);
|
||||
copy_block(&block_tmp, &blockR);
|
||||
xor_block(&block_tmp, next_block); /* Saving the next block contents for XOR over */
|
||||
/* Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block + next_block */
|
||||
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
|
||||
(16,17,..31)... finally (112,113,...127) */
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND_NOMSG(
|
||||
blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
|
||||
blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
|
||||
blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
|
||||
blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
|
||||
blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
|
||||
blockR.v[16 * i + 15]);
|
||||
}
|
||||
|
||||
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
|
||||
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
|
||||
for (i = 0; i < 8; i++) {
|
||||
BLAKE2_ROUND_NOMSG(
|
||||
blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
|
||||
blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
|
||||
blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
|
||||
blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
|
||||
blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
|
||||
blockR.v[2 * i + 113]);
|
||||
}
|
||||
|
||||
copy_block(next_block, &block_tmp);
|
||||
xor_block(next_block, &blockR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate pseudo-random values to reference blocks in the segment and puts
|
||||
* them into the array
|
||||
* @param instance Pointer to the current instance
|
||||
* @param position Pointer to the current position
|
||||
* @param pseudo_rands Pointer to the array of 64-bit values
|
||||
* @pre pseudo_rands must point to @a instance->segment_length allocated values
|
||||
*/
|
||||
static void generate_addresses(const argon2_instance_t *instance,
|
||||
const argon2_position_t *position,
|
||||
uint64_t *pseudo_rands) {
|
||||
block zero_block, input_block, address_block, tmp_block;
|
||||
uint32_t i;
|
||||
|
||||
init_block_value(&zero_block, 0);
|
||||
init_block_value(&input_block, 0);
|
||||
|
||||
if (instance != NULL && position != NULL) {
|
||||
input_block.v[0] = position->pass;
|
||||
input_block.v[1] = position->lane;
|
||||
input_block.v[2] = position->slice;
|
||||
input_block.v[3] = instance->memory_blocks;
|
||||
input_block.v[4] = instance->passes;
|
||||
input_block.v[5] = instance->type;
|
||||
|
||||
for (i = 0; i < instance->segment_length; ++i) {
|
||||
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
||||
input_block.v[6]++;
|
||||
init_block_value(&tmp_block, 0);
|
||||
init_block_value(&address_block, 0);
|
||||
fill_block_with_xor(&zero_block, &input_block, &tmp_block);
|
||||
fill_block_with_xor(&zero_block, &tmp_block, &address_block);
|
||||
}
|
||||
|
||||
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fill_segment_ref(const argon2_instance_t *instance,
|
||||
argon2_position_t position) {
|
||||
block *ref_block = NULL, *curr_block = NULL;
|
||||
uint64_t pseudo_rand, ref_index, ref_lane;
|
||||
uint32_t prev_offset, curr_offset;
|
||||
uint32_t starting_index;
|
||||
uint32_t i;
|
||||
const int data_independent_addressing = 1; /* instance->type == Argon2_i */
|
||||
/* Pseudo-random values that determine the reference block position */
|
||||
uint64_t *pseudo_rands = NULL;
|
||||
|
||||
if (instance == NULL) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
pseudo_rands =
|
||||
(uint64_t *)malloc(sizeof(uint64_t) * (instance->segment_length));
|
||||
|
||||
if (pseudo_rands == NULL) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
if (data_independent_addressing) {
|
||||
generate_addresses(instance, &position, pseudo_rands);
|
||||
}
|
||||
|
||||
starting_index = 0;
|
||||
|
||||
if ((0 == position.pass) && (0 == position.slice)) {
|
||||
starting_index = 2; /* we have already generated the first two blocks */
|
||||
}
|
||||
|
||||
/* Offset of the current block */
|
||||
curr_offset = position.lane * instance->lane_length +
|
||||
position.slice * instance->segment_length + starting_index;
|
||||
|
||||
if (0 == curr_offset % instance->lane_length) {
|
||||
/* Last block in this lane */
|
||||
prev_offset = curr_offset + instance->lane_length - 1;
|
||||
} else {
|
||||
/* Previous block */
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
for (i = starting_index; i < instance->segment_length;
|
||||
++i, ++curr_offset, ++prev_offset) {
|
||||
/*1.1 Rotating prev_offset if needed */
|
||||
if (curr_offset % instance->lane_length == 1) {
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
/* 1.2 Computing the index of the reference block */
|
||||
/* 1.2.1 Taking pseudo-random value from the previous block */
|
||||
if (data_independent_addressing) {
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6385)
|
||||
pseudo_rand = pseudo_rands[i];
|
||||
#pragma warning(pop)
|
||||
} else {
|
||||
pseudo_rand = instance->region->memory[prev_offset].v[0];
|
||||
}
|
||||
|
||||
/* 1.2.2 Computing the lane of the reference block */
|
||||
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
|
||||
|
||||
if ((position.pass == 0) && (position.slice == 0)) {
|
||||
/* Can not reference other lanes yet */
|
||||
ref_lane = position.lane;
|
||||
}
|
||||
|
||||
/* 1.2.3 Computing the number of possible reference block within the
|
||||
* lane.
|
||||
*/
|
||||
position.index = i;
|
||||
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
|
||||
ref_lane == position.lane);
|
||||
|
||||
/* 2 Creating a new block */
|
||||
ref_block =
|
||||
instance->region->memory + instance->lane_length * ref_lane + ref_index;
|
||||
curr_block = instance->region->memory + curr_offset;
|
||||
if (position.pass != 0) {
|
||||
fill_block_with_xor(instance->region->memory + prev_offset, ref_block, curr_block);
|
||||
} else {
|
||||
fill_block(instance->region->memory + prev_offset, ref_block, curr_block);
|
||||
}
|
||||
}
|
||||
|
||||
free(pseudo_rands);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Argon2 source code package
|
||||
*
|
||||
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
||||
*
|
||||
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication along
|
||||
* with
|
||||
* this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
|
||||
#pragma GCC target("sse2")
|
||||
#pragma GCC target("ssse3")
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h> /* for _mm_set_epi64x */
|
||||
#endif
|
||||
#include <emmintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "argon2-core.h"
|
||||
#include "argon2-impl.h"
|
||||
#include "blamka-round-ssse3.h"
|
||||
|
||||
static void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
|
||||
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
block_XY[i] = state[i] = _mm_xor_si128(
|
||||
state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
|
||||
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
|
||||
state[8 * i + 6], state[8 * i + 7]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
|
||||
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
|
||||
state[8 * 6 + i], state[8 * 7 + i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm_xor_si128(state[i], block_XY[i]);
|
||||
_mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
|
||||
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm_xor_si128(state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
|
||||
block_XY[i] = _mm_xor_si128(state[i], _mm_loadu_si128((__m128i const *)(&next_block[16 * i])));
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
|
||||
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
|
||||
state[8 * i + 6], state[8 * i + 7]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
|
||||
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
|
||||
state[8 * 6 + i], state[8 * 7 + i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm_xor_si128(state[i], block_XY[i]);
|
||||
_mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_addresses(const argon2_instance_t *instance,
|
||||
const argon2_position_t *position,
|
||||
uint64_t *pseudo_rands) {
|
||||
block address_block, input_block, tmp_block;
|
||||
uint32_t i;
|
||||
|
||||
init_block_value(&address_block, 0);
|
||||
init_block_value(&input_block, 0);
|
||||
|
||||
if (instance != NULL && position != NULL) {
|
||||
input_block.v[0] = position->pass;
|
||||
input_block.v[1] = position->lane;
|
||||
input_block.v[2] = position->slice;
|
||||
input_block.v[3] = instance->memory_blocks;
|
||||
input_block.v[4] = instance->passes;
|
||||
input_block.v[5] = instance->type;
|
||||
|
||||
for (i = 0; i < instance->segment_length; ++i) {
|
||||
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
||||
/* Temporary zero-initialized blocks */
|
||||
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
|
||||
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
|
||||
memset(zero_block, 0, sizeof(zero_block));
|
||||
memset(zero2_block, 0, sizeof(zero2_block));
|
||||
init_block_value(&address_block, 0);
|
||||
init_block_value(&tmp_block, 0);
|
||||
/* Increasing index counter */
|
||||
input_block.v[6]++;
|
||||
/* First iteration of G */
|
||||
fill_block_with_xor(zero_block, (uint8_t *)&input_block.v, (uint8_t *)&tmp_block.v);
|
||||
/* Second iteration of G */
|
||||
fill_block_with_xor(zero2_block, (uint8_t *)&tmp_block.v, (uint8_t *)&address_block.v);
|
||||
}
|
||||
|
||||
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fill_segment_ssse3(const argon2_instance_t *instance,
|
||||
argon2_position_t position) {
|
||||
block *ref_block = NULL, *curr_block = NULL;
|
||||
uint64_t pseudo_rand, ref_index, ref_lane;
|
||||
uint32_t prev_offset, curr_offset;
|
||||
uint32_t starting_index, i;
|
||||
__m128i state[64];
|
||||
const int data_independent_addressing = 1; /* instance->type == Argon2_i */
|
||||
|
||||
/* Pseudo-random values that determine the reference block position */
|
||||
uint64_t *pseudo_rands = NULL;
|
||||
|
||||
if (instance == NULL) {
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
pseudo_rands =
|
||||
(uint64_t *)malloc(sizeof(uint64_t) * instance->segment_length);
|
||||
if (pseudo_rands == NULL) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
if (data_independent_addressing) {
|
||||
generate_addresses(instance, &position, pseudo_rands);
|
||||
}
|
||||
|
||||
starting_index = 0;
|
||||
|
||||
if ((0 == position.pass) && (0 == position.slice)) {
|
||||
starting_index = 2; /* we have already generated the first two blocks */
|
||||
}
|
||||
|
||||
/* Offset of the current block */
|
||||
curr_offset = position.lane * instance->lane_length +
|
||||
position.slice * instance->segment_length + starting_index;
|
||||
|
||||
if (0 == curr_offset % instance->lane_length) {
|
||||
/* Last block in this lane */
|
||||
prev_offset = curr_offset + instance->lane_length - 1;
|
||||
} else {
|
||||
/* Previous block */
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
memcpy(state, ((instance->region->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
|
||||
|
||||
for (i = starting_index; i < instance->segment_length;
|
||||
++i, ++curr_offset, ++prev_offset) {
|
||||
/*1.1 Rotating prev_offset if needed */
|
||||
if (curr_offset % instance->lane_length == 1) {
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
/* 1.2 Computing the index of the reference block */
|
||||
/* 1.2.1 Taking pseudo-random value from the previous block */
|
||||
if (data_independent_addressing) {
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6385)
|
||||
pseudo_rand = pseudo_rands[i];
|
||||
#pragma warning(pop)
|
||||
} else {
|
||||
pseudo_rand = instance->region->memory[prev_offset].v[0];
|
||||
}
|
||||
|
||||
/* 1.2.2 Computing the lane of the reference block */
|
||||
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
|
||||
|
||||
if ((position.pass == 0) && (position.slice == 0)) {
|
||||
/* Can not reference other lanes yet */
|
||||
ref_lane = position.lane;
|
||||
}
|
||||
|
||||
/* 1.2.3 Computing the number of possible reference block within the
|
||||
* lane.
|
||||
*/
|
||||
position.index = i;
|
||||
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
|
||||
ref_lane == position.lane);
|
||||
|
||||
/* 2 Creating a new block */
|
||||
ref_block =
|
||||
instance->region->memory + instance->lane_length * ref_lane + ref_index;
|
||||
curr_block = instance->region->memory + curr_offset;
|
||||
if (position.pass != 0) {
|
||||
fill_block_with_xor(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
|
||||
} else {
|
||||
fill_block(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
|
||||
}
|
||||
}
|
||||
|
||||
free(pseudo_rands);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#ifndef argon2_impl_H
|
||||
#define argon2_impl_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static inline uint32_t rotl32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w << c ) | ( w >> ( 32 - c ) );
|
||||
}
|
||||
|
||||
static inline uint64_t rotl64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w << c ) | ( w >> ( 64 - c ) );
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static inline uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Argon2 source code package
|
||||
*
|
||||
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
||||
*
|
||||
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication along
|
||||
* with
|
||||
* this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "argon2.h"
|
||||
#include "argon2-encoding.h"
|
||||
#include "argon2-core.h"
|
||||
|
||||
int argon2_ctx(argon2_context *context, argon2_type type) {
|
||||
/* 1. Validate all inputs */
|
||||
int result = validate_inputs(context);
|
||||
uint32_t memory_blocks, segment_length;
|
||||
argon2_instance_t instance;
|
||||
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Argon2_i != type) {
|
||||
return ARGON2_INCORRECT_TYPE;
|
||||
}
|
||||
|
||||
/* 2. Align memory size */
|
||||
/* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
|
||||
memory_blocks = context->m_cost;
|
||||
|
||||
if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
|
||||
memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
|
||||
}
|
||||
|
||||
segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
|
||||
/* Ensure that all segments have equal length */
|
||||
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
|
||||
|
||||
instance.region = NULL;
|
||||
instance.passes = context->t_cost;
|
||||
instance.memory_blocks = memory_blocks;
|
||||
instance.segment_length = segment_length;
|
||||
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
|
||||
instance.lanes = context->lanes;
|
||||
instance.threads = context->threads;
|
||||
instance.type = type;
|
||||
|
||||
/* 3. Initialization: Hashing inputs, allocating memory, filling first
|
||||
* blocks
|
||||
*/
|
||||
result = initialize(&instance, context);
|
||||
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 4. Filling memory */
|
||||
result = fill_memory_blocks(&instance);
|
||||
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 5. Finalization */
|
||||
finalize(context, &instance);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt, const size_t saltlen,
|
||||
void *hash, const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen, argon2_type type) {
|
||||
|
||||
argon2_context context;
|
||||
int result;
|
||||
uint8_t *out;
|
||||
|
||||
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
|
||||
return ARGON2_PWD_TOO_LONG;
|
||||
}
|
||||
|
||||
if (hashlen > ARGON2_MAX_OUTLEN) {
|
||||
return ARGON2_OUTPUT_TOO_LONG;
|
||||
}
|
||||
|
||||
if (saltlen > ARGON2_MAX_SALT_LENGTH) {
|
||||
return ARGON2_SALT_TOO_LONG;
|
||||
}
|
||||
|
||||
out = (uint8_t *) malloc(hashlen);
|
||||
if (!out) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
context.out = (uint8_t *)out;
|
||||
context.outlen = (uint32_t)hashlen;
|
||||
context.pwd = (uint8_t *)pwd;
|
||||
context.pwdlen = (uint32_t)pwdlen;
|
||||
context.salt = (uint8_t *)salt;
|
||||
context.saltlen = (uint32_t)saltlen;
|
||||
context.secret = NULL;
|
||||
context.secretlen = 0;
|
||||
context.ad = NULL;
|
||||
context.adlen = 0;
|
||||
context.t_cost = t_cost;
|
||||
context.m_cost = m_cost;
|
||||
context.lanes = parallelism;
|
||||
context.threads = parallelism;
|
||||
context.flags = ARGON2_DEFAULT_FLAGS;
|
||||
|
||||
result = argon2_ctx(&context, type);
|
||||
|
||||
if (result != ARGON2_OK) {
|
||||
sodium_memzero(out, hashlen);
|
||||
free(out);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* if raw hash requested, write it */
|
||||
if (hash) {
|
||||
memcpy(hash, out, hashlen);
|
||||
}
|
||||
|
||||
/* if encoding requested, write it */
|
||||
if (encoded && encodedlen) {
|
||||
if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
|
||||
sodium_memzero(out, hashlen);
|
||||
sodium_memzero(encoded, encodedlen);
|
||||
free(out);
|
||||
return ARGON2_ENCODING_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
sodium_memzero(out, hashlen);
|
||||
free(out);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, const size_t hashlen,
|
||||
char *encoded, const size_t encodedlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
NULL, hashlen, encoded, encodedlen, Argon2_i);
|
||||
}
|
||||
|
||||
int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash, const size_t hashlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
hash, hashlen, NULL, 0, Argon2_i);
|
||||
}
|
||||
|
||||
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
|
||||
argon2_type type) {
|
||||
|
||||
argon2_context ctx;
|
||||
uint8_t *out;
|
||||
int decode_result;
|
||||
int ret;
|
||||
size_t encoded_len;
|
||||
|
||||
memset(&ctx, 0, sizeof ctx);
|
||||
|
||||
ctx.pwd = NULL;
|
||||
ctx.pwdlen = 0;
|
||||
ctx.secret = NULL;
|
||||
ctx.secretlen = 0;
|
||||
|
||||
/* max values, to be updated in decode_string */
|
||||
encoded_len = strlen(encoded);
|
||||
if (encoded_len > UINT32_MAX) {
|
||||
return ARGON2_DECODING_LENGTH_FAIL;
|
||||
}
|
||||
ctx.adlen = (uint32_t) encoded_len;
|
||||
ctx.saltlen = (uint32_t) encoded_len;
|
||||
ctx.outlen = (uint32_t) encoded_len;
|
||||
|
||||
ctx.ad = (uint8_t *) malloc(ctx.adlen);
|
||||
ctx.salt = (uint8_t *) malloc(ctx.saltlen);
|
||||
ctx.out = (uint8_t *) malloc(ctx.outlen);
|
||||
if (!ctx.out || !ctx.salt || !ctx.ad) {
|
||||
free(ctx.ad);
|
||||
free(ctx.salt);
|
||||
free(ctx.out);
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
out = (uint8_t *) malloc(ctx.outlen);
|
||||
if (!out) {
|
||||
free(ctx.ad);
|
||||
free(ctx.salt);
|
||||
free(ctx.out);
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
decode_result = decode_string(&ctx, encoded, type);
|
||||
if (decode_result != ARGON2_OK) {
|
||||
free(ctx.ad);
|
||||
free(ctx.salt);
|
||||
free(ctx.out);
|
||||
free(out);
|
||||
return decode_result;
|
||||
}
|
||||
|
||||
ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt,
|
||||
ctx.saltlen, out, ctx.outlen, NULL, 0, type);
|
||||
|
||||
free(ctx.ad);
|
||||
free(ctx.salt);
|
||||
|
||||
if (ret != ARGON2_OK || sodium_memcmp(out, ctx.out, ctx.outlen) != 0) {
|
||||
ret = ARGON2_VERIFY_MISMATCH;
|
||||
}
|
||||
free(out);
|
||||
free(ctx.out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
|
||||
return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Argon2 source code package
|
||||
*
|
||||
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
||||
*
|
||||
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication along
|
||||
* with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#ifndef argon2_H
|
||||
#define argon2_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* Argon2 input parameter restrictions
|
||||
*/
|
||||
|
||||
/* Minimum and maximum number of lanes (degree of parallelism) */
|
||||
#define ARGON2_MIN_LANES UINT32_C(1)
|
||||
#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
|
||||
|
||||
/* Minimum and maximum number of threads */
|
||||
#define ARGON2_MIN_THREADS UINT32_C(1)
|
||||
#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
|
||||
|
||||
/* Number of synchronization points between lanes per pass */
|
||||
#define ARGON2_SYNC_POINTS UINT32_C(4)
|
||||
|
||||
/* Minimum and maximum digest size in bytes */
|
||||
#define ARGON2_MIN_OUTLEN UINT32_C(16)
|
||||
#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
|
||||
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
|
||||
|
||||
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB) */
|
||||
#define ARGON2_MAX_MEMORY_BITS \
|
||||
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
|
||||
#define ARGON2_MAX_MEMORY \
|
||||
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
|
||||
|
||||
/* Minimum and maximum number of passes */
|
||||
#define ARGON2_MIN_TIME UINT32_C(3)
|
||||
#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum password length in bytes */
|
||||
#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
|
||||
#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum associated data length in bytes */
|
||||
#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
|
||||
#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum salt length in bytes */
|
||||
#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
|
||||
#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum key length in bytes */
|
||||
#define ARGON2_MIN_SECRET UINT32_C(0)
|
||||
#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
|
||||
|
||||
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
|
||||
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
|
||||
#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)
|
||||
#define ARGON2_DEFAULT_FLAGS (ARGON2_FLAG_CLEAR_MEMORY)
|
||||
|
||||
/* Error codes */
|
||||
typedef enum Argon2_ErrorCodes {
|
||||
ARGON2_OK = 0,
|
||||
|
||||
ARGON2_OUTPUT_PTR_NULL = -1,
|
||||
|
||||
ARGON2_OUTPUT_TOO_SHORT = -2,
|
||||
ARGON2_OUTPUT_TOO_LONG = -3,
|
||||
|
||||
ARGON2_PWD_TOO_SHORT = -4,
|
||||
ARGON2_PWD_TOO_LONG = -5,
|
||||
|
||||
ARGON2_SALT_TOO_SHORT = -6,
|
||||
ARGON2_SALT_TOO_LONG = -7,
|
||||
|
||||
ARGON2_AD_TOO_SHORT = -8,
|
||||
ARGON2_AD_TOO_LONG = -9,
|
||||
|
||||
ARGON2_SECRET_TOO_SHORT = -10,
|
||||
ARGON2_SECRET_TOO_LONG = -11,
|
||||
|
||||
ARGON2_TIME_TOO_SMALL = -12,
|
||||
ARGON2_TIME_TOO_LARGE = -13,
|
||||
|
||||
ARGON2_MEMORY_TOO_LITTLE = -14,
|
||||
ARGON2_MEMORY_TOO_MUCH = -15,
|
||||
|
||||
ARGON2_LANES_TOO_FEW = -16,
|
||||
ARGON2_LANES_TOO_MANY = -17,
|
||||
|
||||
ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
|
||||
ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
|
||||
ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
|
||||
ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
|
||||
|
||||
ARGON2_MEMORY_ALLOCATION_ERROR = -22,
|
||||
|
||||
ARGON2_FREE_MEMORY_CBK_NULL = -23,
|
||||
ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
|
||||
|
||||
ARGON2_INCORRECT_PARAMETER = -25,
|
||||
ARGON2_INCORRECT_TYPE = -26,
|
||||
|
||||
ARGON2_OUT_PTR_MISMATCH = -27,
|
||||
|
||||
ARGON2_THREADS_TOO_FEW = -28,
|
||||
ARGON2_THREADS_TOO_MANY = -29,
|
||||
|
||||
ARGON2_MISSING_ARGS = -30,
|
||||
|
||||
ARGON2_ENCODING_FAIL = -31,
|
||||
|
||||
ARGON2_DECODING_FAIL = -32,
|
||||
|
||||
ARGON2_THREAD_FAIL = -33,
|
||||
|
||||
ARGON2_DECODING_LENGTH_FAIL = -34,
|
||||
|
||||
ARGON2_VERIFY_MISMATCH = -35
|
||||
} argon2_error_codes;
|
||||
|
||||
/* Argon2 external data structures */
|
||||
|
||||
/*
|
||||
* Context: structure to hold Argon2 inputs:
|
||||
* output array and its length,
|
||||
* password and its length,
|
||||
* salt and its length,
|
||||
* secret and its length,
|
||||
* associated data and its length,
|
||||
* number of passes, amount of used memory (in KBytes, can be rounded up a bit)
|
||||
* number of parallel threads that will be run.
|
||||
* All the parameters above affect the output hash value.
|
||||
* Additionally, two function pointers can be provided to allocate and
|
||||
* deallocate the memory (if NULL, memory will be allocated internally).
|
||||
* Also, three flags indicate whether to erase password, secret as soon as they
|
||||
* are pre-hashed (and thus not needed anymore), and the entire memory
|
||||
*****
|
||||
* Simplest situation: you have output array out[8], password is stored in
|
||||
* pwd[32], salt is stored in salt[16], you do not have keys nor associated data.
|
||||
* You need to spend 1 GB of RAM and you run 5 passes of Argon2 with 4 parallel lanes.
|
||||
* You want to erase the password, but you're OK with last pass not being erased.
|
||||
* You want to use the default memory allocator.
|
||||
* Then you initialize:
|
||||
* Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false).
|
||||
*/
|
||||
typedef struct Argon2_Context {
|
||||
uint8_t *out; /* output array */
|
||||
uint32_t outlen; /* digest length */
|
||||
|
||||
uint8_t *pwd; /* password array */
|
||||
uint32_t pwdlen; /* password length */
|
||||
|
||||
uint8_t *salt; /* salt array */
|
||||
uint32_t saltlen; /* salt length */
|
||||
|
||||
uint8_t *secret; /* key array */
|
||||
uint32_t secretlen; /* key length */
|
||||
|
||||
uint8_t *ad; /* associated data array */
|
||||
uint32_t adlen; /* associated data length */
|
||||
|
||||
uint32_t t_cost; /* number of passes */
|
||||
uint32_t m_cost; /* amount of memory requested (KB) */
|
||||
uint32_t lanes; /* number of lanes */
|
||||
uint32_t threads; /* maximum number of threads */
|
||||
|
||||
uint32_t flags; /* array of bool options */
|
||||
} argon2_context;
|
||||
|
||||
/* Argon2 primitive type */
|
||||
typedef enum Argon2_type { Argon2_i = 1 } argon2_type;
|
||||
|
||||
/*
|
||||
* Function that performs memory-hard hashing with certain degree of parallelism
|
||||
* @param context Pointer to the Argon2 internal structure
|
||||
* @return Error code if smth is wrong, ARGON2_OK otherwise
|
||||
*/
|
||||
int argon2_ctx(argon2_context *context, argon2_type type);
|
||||
|
||||
/**
|
||||
* Hashes a password with Argon2i, producing an encoded hash
|
||||
* @param t_cost Number of iterations
|
||||
* @param m_cost Sets memory usage to m_cost kibibytes
|
||||
* @param parallelism Number of threads and compute lanes
|
||||
* @param pwd Pointer to password
|
||||
* @param pwdlen Password size in bytes
|
||||
* @param salt Pointer to salt
|
||||
* @param saltlen Salt size in bytes
|
||||
* @param hashlen Desired length of the hash in bytes
|
||||
* @param encoded Buffer where to write the encoded hash
|
||||
* @param encodedlen Size of the buffer (thus max size of the encoded hash)
|
||||
* @pre Different parallelism levels will give different results
|
||||
* @pre Returns ARGON2_OK if successful
|
||||
*/
|
||||
int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, const size_t hashlen,
|
||||
char *encoded, const size_t encodedlen);
|
||||
|
||||
/**
|
||||
* Hashes a password with Argon2i, producing a raw hash
|
||||
* @param t_cost Number of iterations
|
||||
* @param m_cost Sets memory usage to m_cost kibibytes
|
||||
* @param parallelism Number of threads and compute lanes
|
||||
* @param pwd Pointer to password
|
||||
* @param pwdlen Password size in bytes
|
||||
* @param salt Pointer to salt
|
||||
* @param saltlen Salt size in bytes
|
||||
* @param hash Buffer where to write the raw hash
|
||||
* @param hashlen Desired length of the hash in bytes
|
||||
* @pre Different parallelism levels will give different results
|
||||
* @pre Returns ARGON2_OK if successful
|
||||
*/
|
||||
int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash, const size_t hashlen);
|
||||
|
||||
/* generic function underlying the above ones */
|
||||
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt, const size_t saltlen,
|
||||
void *hash, const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen, argon2_type type);
|
||||
|
||||
/**
|
||||
* Verifies a password against an encoded string
|
||||
* Encoded string is restricted as in validate_inputs()
|
||||
* @param encoded String encoding parameters, salt, hash
|
||||
* @param pwd Pointer to password
|
||||
* @pre Returns ARGON2_OK if successful
|
||||
*/
|
||||
int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen);
|
||||
|
||||
/* generic function underlying the above ones */
|
||||
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
|
||||
argon2_type type);
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_generichash_blake2b.h"
|
||||
#include "utils.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#include "argon2-impl.h"
|
||||
#include "blake2b-long.h"
|
||||
|
||||
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
|
||||
uint8_t *out = (uint8_t *)pout;
|
||||
crypto_generichash_blake2b_state blake_state;
|
||||
uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = {0};
|
||||
int ret = -1;
|
||||
|
||||
if (outlen > UINT32_MAX) {
|
||||
goto fail; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
|
||||
/* Ensure little-endian byte order! */
|
||||
STORE32_LE(outlen_bytes, (uint32_t)outlen);
|
||||
|
||||
#define TRY(statement) \
|
||||
do { \
|
||||
ret = statement; \
|
||||
if (ret < 0) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while ((void)0, 0)
|
||||
|
||||
if (outlen <= crypto_generichash_blake2b_BYTES_MAX) {
|
||||
TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U, outlen));
|
||||
TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
|
||||
sizeof(outlen_bytes)));
|
||||
TRY(crypto_generichash_blake2b_update(&blake_state,
|
||||
(const unsigned char *) in,
|
||||
inlen));
|
||||
TRY(crypto_generichash_blake2b_final(&blake_state, out, outlen));
|
||||
} else {
|
||||
uint32_t toproduce;
|
||||
uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX];
|
||||
uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX];
|
||||
TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U,
|
||||
crypto_generichash_blake2b_BYTES_MAX));
|
||||
TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
|
||||
sizeof(outlen_bytes)));
|
||||
TRY(crypto_generichash_blake2b_update(&blake_state,
|
||||
(const unsigned char *) in,
|
||||
inlen));
|
||||
TRY(crypto_generichash_blake2b_final(&blake_state, out_buffer,
|
||||
crypto_generichash_blake2b_BYTES_MAX));
|
||||
memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
|
||||
out += crypto_generichash_blake2b_BYTES_MAX / 2;
|
||||
toproduce = (uint32_t)outlen - crypto_generichash_blake2b_BYTES_MAX / 2;
|
||||
|
||||
while (toproduce > crypto_generichash_blake2b_BYTES_MAX) {
|
||||
memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
|
||||
TRY(crypto_generichash_blake2b(out_buffer, crypto_generichash_blake2b_BYTES_MAX,
|
||||
in_buffer,
|
||||
crypto_generichash_blake2b_BYTES_MAX,
|
||||
NULL, 0U));
|
||||
memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
|
||||
out += crypto_generichash_blake2b_BYTES_MAX / 2;
|
||||
toproduce -= crypto_generichash_blake2b_BYTES_MAX / 2;
|
||||
}
|
||||
|
||||
memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
|
||||
TRY(crypto_generichash_blake2b(out_buffer, toproduce, in_buffer,
|
||||
crypto_generichash_blake2b_BYTES_MAX,
|
||||
NULL, 0U));
|
||||
memcpy(out, out_buffer, toproduce);
|
||||
}
|
||||
fail:
|
||||
sodium_memzero(&blake_state, sizeof(blake_state));
|
||||
return ret;
|
||||
#undef TRY
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef blake2b_long_H
|
||||
#define blake2b_long_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen);
|
||||
|
||||
#endif
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#ifndef blamka_round_ref_H
|
||||
#define blamka_round_ref_H
|
||||
|
||||
#include "argon2-impl.h"
|
||||
|
||||
/*designed by the Lyra PHC team */
|
||||
static inline uint64_t fBlaMka(uint64_t x, uint64_t y) {
|
||||
const uint64_t m = UINT64_C(0xFFFFFFFF);
|
||||
const uint64_t xy = (x & m) * (y & m);
|
||||
return x + y + 2 * xy;
|
||||
}
|
||||
|
||||
#define G(a, b, c, d) \
|
||||
do { \
|
||||
a = fBlaMka(a, b); \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = fBlaMka(c, d); \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = fBlaMka(a, b); \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = fBlaMka(c, d); \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
|
||||
v12, v13, v14, v15) \
|
||||
do { \
|
||||
G(v0, v4, v8, v12); \
|
||||
G(v1, v5, v9, v13); \
|
||||
G(v2, v6, v10, v14); \
|
||||
G(v3, v7, v11, v15); \
|
||||
G(v0, v5, v10, v15); \
|
||||
G(v1, v6, v11, v12); \
|
||||
G(v2, v7, v8, v13); \
|
||||
G(v3, v4, v9, v14); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#endif
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#ifndef blamka_round_ssse3_H
|
||||
#define blamka_round_ssse3_H
|
||||
|
||||
#include "argon2-impl.h"
|
||||
|
||||
#define r16 \
|
||||
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
|
||||
#define r24 \
|
||||
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
|
||||
#define _mm_roti_epi64(x, c) \
|
||||
(-(c) == 32) \
|
||||
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
|
||||
: (-(c) == 24) \
|
||||
? _mm_shuffle_epi8((x), r24) \
|
||||
: (-(c) == 16) \
|
||||
? _mm_shuffle_epi8((x), r16) \
|
||||
: (-(c) == 63) \
|
||||
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
|
||||
_mm_add_epi64((x), (x))) \
|
||||
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
|
||||
_mm_slli_epi64((x), 64 - (-(c))))
|
||||
|
||||
static inline __m128i fBlaMka(__m128i x, __m128i y) {
|
||||
const __m128i z = _mm_mul_epu32(x, y);
|
||||
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
|
||||
}
|
||||
|
||||
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
A0 = fBlaMka(A0, B0); \
|
||||
A1 = fBlaMka(A1, B1); \
|
||||
\
|
||||
D0 = _mm_xor_si128(D0, A0); \
|
||||
D1 = _mm_xor_si128(D1, A1); \
|
||||
\
|
||||
D0 = _mm_roti_epi64(D0, -32); \
|
||||
D1 = _mm_roti_epi64(D1, -32); \
|
||||
\
|
||||
C0 = fBlaMka(C0, D0); \
|
||||
C1 = fBlaMka(C1, D1); \
|
||||
\
|
||||
B0 = _mm_xor_si128(B0, C0); \
|
||||
B1 = _mm_xor_si128(B1, C1); \
|
||||
\
|
||||
B0 = _mm_roti_epi64(B0, -24); \
|
||||
B1 = _mm_roti_epi64(B1, -24); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
A0 = fBlaMka(A0, B0); \
|
||||
A1 = fBlaMka(A1, B1); \
|
||||
\
|
||||
D0 = _mm_xor_si128(D0, A0); \
|
||||
D1 = _mm_xor_si128(D1, A1); \
|
||||
\
|
||||
D0 = _mm_roti_epi64(D0, -16); \
|
||||
D1 = _mm_roti_epi64(D1, -16); \
|
||||
\
|
||||
C0 = fBlaMka(C0, D0); \
|
||||
C1 = fBlaMka(C1, D1); \
|
||||
\
|
||||
B0 = _mm_xor_si128(B0, C0); \
|
||||
B1 = _mm_xor_si128(B1, C1); \
|
||||
\
|
||||
B0 = _mm_roti_epi64(B0, -63); \
|
||||
B1 = _mm_roti_epi64(B1, -63); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
|
||||
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
|
||||
B0 = t0; \
|
||||
B1 = t1; \
|
||||
\
|
||||
t0 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(D1, D0, 8); \
|
||||
t1 = _mm_alignr_epi8(D0, D1, 8); \
|
||||
D0 = t1; \
|
||||
D1 = t0; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
|
||||
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
|
||||
B0 = t0; \
|
||||
B1 = t1; \
|
||||
\
|
||||
t0 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(D0, D1, 8); \
|
||||
t1 = _mm_alignr_epi8(D1, D0, 8); \
|
||||
D0 = t1; \
|
||||
D1 = t0; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,164 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "argon2-core.h"
|
||||
#include "crypto_pwhash_argon2i.h"
|
||||
#include "randombytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define STR_HASHBYTES 32U
|
||||
|
||||
int
|
||||
crypto_pwhash_argon2i_alg_argon2i13(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_ALG_ARGON2I13;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_saltbytes(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_SALTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_strbytes(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_STRBYTES;
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_pwhash_argon2i_strprefix(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_STRPREFIX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_opslimit_interactive(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_memlimit_interactive(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_opslimit_moderate(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_OPSLIMIT_MODERATE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_memlimit_moderate(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_MEMLIMIT_MODERATE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_opslimit_sensitive(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_argon2i_memlimit_sensitive(void)
|
||||
{
|
||||
return crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_argon2i(unsigned char * const out,
|
||||
unsigned long long outlen,
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen,
|
||||
const unsigned char * const salt,
|
||||
unsigned long long opslimit,
|
||||
size_t memlimit, int alg)
|
||||
{
|
||||
if (alg != crypto_pwhash_argon2i_ALG_ARGON2I13) {
|
||||
return -1;
|
||||
}
|
||||
memlimit /= 1024U;
|
||||
if (outlen > ARGON2_MAX_OUTLEN || passwdlen > ARGON2_MAX_PWD_LENGTH ||
|
||||
opslimit > ARGON2_MAX_TIME || memlimit > ARGON2_MAX_MEMORY) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (outlen < ARGON2_MIN_OUTLEN || passwdlen < ARGON2_MIN_PWD_LENGTH ||
|
||||
opslimit < ARGON2_MIN_TIME || memlimit < ARGON2_MIN_MEMORY) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) memlimit,
|
||||
(uint32_t) 1U, passwd, (size_t) passwdlen,
|
||||
salt, (size_t) crypto_pwhash_argon2i_SALTBYTES,
|
||||
out, (size_t) outlen) != ARGON2_OK) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen,
|
||||
unsigned long long opslimit,
|
||||
size_t memlimit)
|
||||
{
|
||||
unsigned char salt[crypto_pwhash_argon2i_SALTBYTES];
|
||||
|
||||
memset(out, 0, crypto_pwhash_argon2i_STRBYTES);
|
||||
memlimit /= 1024U;
|
||||
if (passwdlen > ARGON2_MAX_PWD_LENGTH ||
|
||||
opslimit > ARGON2_MAX_TIME || memlimit > ARGON2_MAX_MEMORY) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (passwdlen < ARGON2_MIN_PWD_LENGTH ||
|
||||
opslimit < ARGON2_MIN_TIME || memlimit < ARGON2_MIN_MEMORY) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
randombytes_buf(salt, sizeof salt);
|
||||
if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) memlimit,
|
||||
(uint32_t) 1U, passwd, (size_t) passwdlen,
|
||||
salt, sizeof salt, STR_HASHBYTES,
|
||||
out, crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen)
|
||||
{
|
||||
if (passwdlen > ARGON2_MAX_PWD_LENGTH) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
/* LCOV_EXCL_START */
|
||||
if (passwdlen < ARGON2_MIN_PWD_LENGTH) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
if (argon2i_verify(str, passwd, (size_t) passwdlen) != ARGON2_OK) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_crypto_pwhash_argon2i_pick_best_implementation(void)
|
||||
{
|
||||
return argon2_pick_best_implementation();
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "crypto_pwhash.h"
|
||||
|
||||
int
|
||||
crypto_pwhash_alg_argon2i13(void)
|
||||
{
|
||||
return crypto_pwhash_ALG_ARGON2I13;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_alg_default(void)
|
||||
{
|
||||
return crypto_pwhash_ALG_ARGON2I13;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_saltbytes(void)
|
||||
{
|
||||
return crypto_pwhash_SALTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_strbytes(void)
|
||||
{
|
||||
return crypto_pwhash_STRBYTES;
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_pwhash_strprefix(void)
|
||||
{
|
||||
return crypto_pwhash_STRPREFIX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_opslimit_interactive(void)
|
||||
{
|
||||
return crypto_pwhash_OPSLIMIT_INTERACTIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_memlimit_interactive(void)
|
||||
{
|
||||
return crypto_pwhash_MEMLIMIT_INTERACTIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_opslimit_moderate(void)
|
||||
{
|
||||
return crypto_pwhash_OPSLIMIT_MODERATE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_memlimit_moderate(void)
|
||||
{
|
||||
return crypto_pwhash_MEMLIMIT_MODERATE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_opslimit_sensitive(void)
|
||||
{
|
||||
return crypto_pwhash_OPSLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_memlimit_sensitive(void)
|
||||
{
|
||||
return crypto_pwhash_MEMLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash(unsigned char * const out, unsigned long long outlen,
|
||||
const char * const passwd, unsigned long long passwdlen,
|
||||
const unsigned char * const salt,
|
||||
unsigned long long opslimit, size_t memlimit, int alg)
|
||||
{
|
||||
if (alg != crypto_pwhash_ALG_ARGON2I13) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return crypto_pwhash_argon2i(out, outlen, passwd, passwdlen, salt,
|
||||
opslimit, memlimit, alg);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
|
||||
const char * const passwd, unsigned long long passwdlen,
|
||||
unsigned long long opslimit, size_t memlimit)
|
||||
{
|
||||
return crypto_pwhash_argon2i_str(out, passwd, passwdlen,
|
||||
opslimit, memlimit);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen)
|
||||
{
|
||||
return crypto_pwhash_argon2i_str_verify(str, passwd, passwdlen);
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_pwhash_primitive(void) {
|
||||
return crypto_pwhash_PRIMITIVE;
|
||||
}
|
||||
Generated
+252
@@ -0,0 +1,252 @@
|
||||
/*-
|
||||
* Copyright 2013 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_pwhash_scryptsalsa208sha256.h"
|
||||
#include "crypto_scrypt.h"
|
||||
#include "runtime.h"
|
||||
#include "utils.h"
|
||||
|
||||
static const char * const itoa64 =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
static uint8_t *
|
||||
encode64_uint32(uint8_t * dst, size_t dstlen, uint32_t src, uint32_t srcbits)
|
||||
{
|
||||
uint32_t bit;
|
||||
|
||||
for (bit = 0; bit < srcbits; bit += 6) {
|
||||
if (dstlen < 1) {
|
||||
return NULL; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
*dst++ = itoa64[src & 0x3f];
|
||||
dstlen--;
|
||||
src >>= 6;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
encode64(uint8_t * dst, size_t dstlen, const uint8_t * src, size_t srclen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < srclen; ) {
|
||||
uint8_t * dnext;
|
||||
uint32_t value = 0, bits = 0;
|
||||
do {
|
||||
value |= (uint32_t)src[i++] << bits;
|
||||
bits += 8;
|
||||
} while (bits < 24 && i < srclen);
|
||||
dnext = encode64_uint32(dst, dstlen, value, bits);
|
||||
if (!dnext) {
|
||||
return NULL; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
dstlen -= dnext - dst;
|
||||
dst = dnext;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static int
|
||||
decode64_one(uint32_t * dst, uint8_t src)
|
||||
{
|
||||
const char *ptr = strchr(itoa64, src);
|
||||
|
||||
if (ptr) {
|
||||
*dst = (uint32_t) (ptr - itoa64);
|
||||
return 0;
|
||||
}
|
||||
*dst = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const uint8_t *
|
||||
decode64_uint32(uint32_t * dst, uint32_t dstbits, const uint8_t * src)
|
||||
{
|
||||
uint32_t bit;
|
||||
uint32_t value;
|
||||
|
||||
value = 0;
|
||||
for (bit = 0; bit < dstbits; bit += 6) {
|
||||
uint32_t one;
|
||||
if (decode64_one(&one, *src)) {
|
||||
*dst = 0;
|
||||
return NULL;
|
||||
}
|
||||
src++;
|
||||
value |= one << bit;
|
||||
}
|
||||
|
||||
*dst = value;
|
||||
return src;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
escrypt_r(escrypt_local_t * local, const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * setting, uint8_t * buf, size_t buflen)
|
||||
{
|
||||
uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
|
||||
escrypt_kdf_t escrypt_kdf;
|
||||
const uint8_t *src;
|
||||
const uint8_t *salt;
|
||||
uint8_t *dst;
|
||||
size_t prefixlen;
|
||||
size_t saltlen;
|
||||
size_t need;
|
||||
uint64_t N;
|
||||
uint32_t N_log2;
|
||||
uint32_t r;
|
||||
uint32_t p;
|
||||
|
||||
if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
|
||||
return NULL;
|
||||
}
|
||||
src = setting + 3;
|
||||
|
||||
if (decode64_one(&N_log2, *src)) {
|
||||
return NULL;
|
||||
}
|
||||
src++;
|
||||
N = (uint64_t) 1 << N_log2;
|
||||
|
||||
src = decode64_uint32(&r, 30, src);
|
||||
if (!src) {
|
||||
return NULL;
|
||||
}
|
||||
src = decode64_uint32(&p, 30, src);
|
||||
if (!src) {
|
||||
return NULL;
|
||||
}
|
||||
prefixlen = src - setting;
|
||||
|
||||
salt = src;
|
||||
src = (uint8_t *) strrchr((char *)salt, '$');
|
||||
if (src) {
|
||||
saltlen = src - salt;
|
||||
} else {
|
||||
saltlen = strlen((char *)salt);
|
||||
}
|
||||
need = prefixlen + saltlen + 1 +
|
||||
crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
|
||||
if (need > buflen || need < saltlen) {
|
||||
return NULL;
|
||||
}
|
||||
#if defined(HAVE_EMMINTRIN_H) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
escrypt_kdf =
|
||||
sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
|
||||
#else
|
||||
escrypt_kdf = escrypt_kdf_nosse;
|
||||
#endif
|
||||
if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
|
||||
N, r, p, hash, sizeof(hash))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst = buf;
|
||||
memcpy(dst, setting, prefixlen + saltlen);
|
||||
dst += prefixlen + saltlen;
|
||||
*dst++ = '$';
|
||||
|
||||
dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
|
||||
sodium_memzero(hash, sizeof hash);
|
||||
if (!dst || dst >= buf + buflen) {
|
||||
return NULL; /* Can't happen LCOV_EXCL_LINE */
|
||||
}
|
||||
*dst = 0; /* NUL termination */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p,
|
||||
const uint8_t * src, size_t srclen,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
uint8_t *dst;
|
||||
size_t prefixlen =
|
||||
(sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
|
||||
size_t saltlen = BYTES2CHARS(srclen);
|
||||
size_t need;
|
||||
|
||||
need = prefixlen + saltlen + 1;
|
||||
if (need > buflen || need < saltlen || saltlen < srclen) {
|
||||
return NULL; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) {
|
||||
return NULL;
|
||||
}
|
||||
dst = buf;
|
||||
*dst++ = '$';
|
||||
*dst++ = '7';
|
||||
*dst++ = '$';
|
||||
|
||||
*dst++ = itoa64[N_log2];
|
||||
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
|
||||
if (!dst) {
|
||||
return NULL; /* Can't happen LCOV_EXCL_LINE */
|
||||
}
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
|
||||
if (!dst) {
|
||||
return NULL; /* Can't happen LCOV_EXCL_LINE */
|
||||
}
|
||||
dst = encode64(dst, buflen - (dst - buf), src, srclen);
|
||||
if (!dst || dst >= buf + buflen) {
|
||||
return NULL; /* Can't happen LCOV_EXCL_LINE */
|
||||
}
|
||||
*dst = 0; /* NUL termination */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen,
|
||||
uint64_t N, uint32_t r, uint32_t p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
escrypt_kdf_t escrypt_kdf;
|
||||
escrypt_local_t local;
|
||||
int retval;
|
||||
|
||||
if (escrypt_init_local(&local)) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
#if defined(HAVE_EMMINTRIN_H) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
escrypt_kdf =
|
||||
sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
|
||||
#else
|
||||
escrypt_kdf = escrypt_kdf_nosse;
|
||||
#endif
|
||||
retval = escrypt_kdf(&local,
|
||||
passwd, passwdlen, salt, saltlen,
|
||||
N, r, p, buf, buflen);
|
||||
if (escrypt_free_local(&local)) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2013 Alexander Peslyak
|
||||
* 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.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef crypto_scrypt_H
|
||||
#define crypto_scrypt_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if SIZE_MAX > 0xffffffffULL
|
||||
# define ARCH_BITS 64
|
||||
#else
|
||||
# define ARCH_BITS 32
|
||||
#endif
|
||||
|
||||
#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14
|
||||
#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57
|
||||
#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32
|
||||
#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43
|
||||
#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32
|
||||
#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43
|
||||
|
||||
#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6)
|
||||
|
||||
typedef struct {
|
||||
void * base, * aligned;
|
||||
size_t size;
|
||||
} escrypt_region_t;
|
||||
|
||||
typedef union {
|
||||
uint64_t d[8];
|
||||
uint32_t w[16];
|
||||
} escrypt_block_t;
|
||||
|
||||
typedef escrypt_region_t escrypt_local_t;
|
||||
|
||||
extern int escrypt_init_local(escrypt_local_t * __local);
|
||||
|
||||
extern int escrypt_free_local(escrypt_local_t * __local);
|
||||
|
||||
extern void *alloc_region(escrypt_region_t * region, size_t size);
|
||||
extern int free_region(escrypt_region_t * region);
|
||||
|
||||
typedef int (*escrypt_kdf_t)(escrypt_local_t * __local,
|
||||
const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __salt, size_t __saltlen,
|
||||
uint64_t __N, uint32_t __r, uint32_t __p,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
extern int escrypt_kdf_nosse(escrypt_local_t * __local,
|
||||
const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __salt, size_t __saltlen,
|
||||
uint64_t __N, uint32_t __r, uint32_t __p,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
extern int escrypt_kdf_sse(escrypt_local_t * __local,
|
||||
const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __salt, size_t __saltlen,
|
||||
uint64_t __N, uint32_t __r, uint32_t __p,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
extern uint8_t * escrypt_r(escrypt_local_t * __local,
|
||||
const uint8_t * __passwd, size_t __passwdlen,
|
||||
const uint8_t * __setting,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
extern uint8_t * escrypt_gensalt_r(
|
||||
uint32_t __N_log2, uint32_t __r, uint32_t __p,
|
||||
const uint8_t * __src, size_t __srclen,
|
||||
uint8_t * __buf, size_t __buflen);
|
||||
|
||||
#endif /* !_CRYPTO_SCRYPT_H_ */
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2013 Alexander Peslyak
|
||||
* 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.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../pbkdf2-sha256.h"
|
||||
#include "../crypto_scrypt.h"
|
||||
#include "private/common.h"
|
||||
|
||||
static inline void
|
||||
blkcpy_64(escrypt_block_t *dest, const escrypt_block_t *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if (ARCH_BITS==32)
|
||||
for (i = 0; i < 16; ++i)
|
||||
dest->w[i] = src->w[i];
|
||||
#else
|
||||
for (i = 0; i < 8; ++i)
|
||||
dest->d[i] = src->d[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
blkxor_64(escrypt_block_t *dest, const escrypt_block_t *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if (ARCH_BITS==32)
|
||||
for (i = 0; i < 16; ++i)
|
||||
dest->w[i] ^= src->w[i];
|
||||
#else
|
||||
for (i = 0; i < 8; ++i)
|
||||
dest->d[i] ^= src->d[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
blkcpy(escrypt_block_t *dest, const escrypt_block_t *src, size_t len)
|
||||
{
|
||||
size_t i, L;
|
||||
#if (ARCH_BITS==32)
|
||||
L = (len>>2);
|
||||
for (i = 0; i < L; ++i)
|
||||
dest->w[i] = src->w[i];
|
||||
#else
|
||||
L = (len>>3);
|
||||
for (i = 0; i < L; ++i)
|
||||
dest->d[i] = src->d[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
blkxor(escrypt_block_t *dest, const escrypt_block_t *src, size_t len)
|
||||
{
|
||||
size_t i, L;
|
||||
#if (ARCH_BITS==32)
|
||||
L = (len>>2);
|
||||
for (i = 0; i < L; ++i)
|
||||
dest->w[i] ^= src->w[i];
|
||||
#else
|
||||
L = (len>>3);
|
||||
for (i = 0; i < L; ++i)
|
||||
dest->d[i] ^= src->d[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20_8(B):
|
||||
* Apply the salsa20/8 core to the provided block.
|
||||
*/
|
||||
static void
|
||||
salsa20_8(uint32_t B[16])
|
||||
{
|
||||
escrypt_block_t X;
|
||||
uint32_t *x = X.w;
|
||||
size_t i;
|
||||
|
||||
blkcpy_64(&X, (escrypt_block_t*)B);
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
/* Operate on columns. */
|
||||
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
|
||||
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
|
||||
|
||||
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
|
||||
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
|
||||
|
||||
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
|
||||
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
|
||||
|
||||
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
|
||||
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
|
||||
|
||||
/* Operate on rows. */
|
||||
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
|
||||
|
||||
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
|
||||
|
||||
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
|
||||
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
|
||||
|
||||
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
|
||||
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
|
||||
#undef R
|
||||
}
|
||||
for (i = 0; i < 16; i++)
|
||||
B[i] += x[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(Bin, Bout, X, r):
|
||||
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
|
||||
* bytes in length; the output Bout must also be the same size. The
|
||||
* temporary space X must be 64 bytes.
|
||||
*/
|
||||
static void
|
||||
blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy_64((escrypt_block_t*)X, (escrypt_block_t*)&Bin[(2 * r - 1) * 16]);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < 2 * r; i += 2) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor_64((escrypt_block_t*)X, (escrypt_block_t*)&Bin[i * 16]);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy_64((escrypt_block_t*)&Bout[i * 8], (escrypt_block_t*)X);
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
blkxor_64((escrypt_block_t*)X, (escrypt_block_t*)&Bin[i * 16 + 16]);
|
||||
salsa20_8(X);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
blkcpy_64((escrypt_block_t*)&Bout[i * 8 + r * 16], (escrypt_block_t*)X);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static inline uint64_t
|
||||
integerify(const void * B, size_t r)
|
||||
{
|
||||
const uint32_t * X = (const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
|
||||
return (((uint64_t)(X[1]) << 32) + X[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*/
|
||||
static void
|
||||
smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
|
||||
{
|
||||
uint32_t * X = XY;
|
||||
uint32_t * Y = &XY[32 * r];
|
||||
uint32_t * Z = &XY[64 * r];
|
||||
uint64_t i;
|
||||
uint64_t j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
for (k = 0; k < 32 * r; k++)
|
||||
X[k] = LOAD32_LE(&B[4 * k]);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((escrypt_block_t*)&V[i * (32 * r)], (escrypt_block_t*)X, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy((escrypt_block_t*)&V[(i + 1) * (32 * r)], (escrypt_block_t*)Y, 128 * r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor((escrypt_block_t*)X, (escrypt_block_t*)&V[j * (32 * r)], 128 * r);
|
||||
blockmix_salsa8(X, Y, Z, r);
|
||||
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(Y, r) & (N - 1);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
blkxor((escrypt_block_t*)Y, (escrypt_block_t*)&V[j * (32 * r)], 128 * r);
|
||||
blockmix_salsa8(Y, X, Z, r);
|
||||
}
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 32 * r; k++)
|
||||
STORE32_LE(&B[4 * k], X[k]);
|
||||
}
|
||||
|
||||
/**
|
||||
* escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
|
||||
* N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
escrypt_kdf_nosse(escrypt_local_t * local,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen,
|
||||
uint64_t N, uint32_t _r, uint32_t _p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
size_t B_size, V_size, XY_size, need;
|
||||
uint8_t * B;
|
||||
uint32_t * V, * XY;
|
||||
size_t r = _r, p = _p;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= ((uint64_t) 1 << 30)) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (N > UINT32_MAX) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N < 2)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (r == 0 || p == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > SIZE_MAX / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
B_size = (size_t)128 * r * p;
|
||||
V_size = (size_t)128 * r * N;
|
||||
need = B_size + V_size;
|
||||
if (need < V_size) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
XY_size = (size_t)256 * r + 64;
|
||||
need += XY_size;
|
||||
if (need < XY_size) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (local->size < need) {
|
||||
if (free_region(local))
|
||||
return -1;
|
||||
if (!alloc_region(local, need))
|
||||
return -1;
|
||||
}
|
||||
B = (uint8_t *)local->aligned;
|
||||
V = (uint32_t *)((uint8_t *)B + B_size);
|
||||
XY = (uint32_t *)((uint8_t *)V + V_size);
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[(size_t)128 * i * r], r, N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
|
||||
|
||||
/* Success! */
|
||||
return 0;
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*-
|
||||
* 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 <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_auth_hmacsha256.h"
|
||||
#include "pbkdf2-sha256.h"
|
||||
#include "utils.h"
|
||||
#include "private/common.h"
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
|
||||
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
|
||||
{
|
||||
crypto_auth_hmacsha256_state PShctx, hctx;
|
||||
size_t i;
|
||||
uint8_t ivec[4];
|
||||
uint8_t U[32];
|
||||
uint8_t T[32];
|
||||
uint64_t j;
|
||||
int k;
|
||||
size_t clen;
|
||||
|
||||
if (dkLen > 0x1fffffffe0ULL) {
|
||||
abort();
|
||||
}
|
||||
crypto_auth_hmacsha256_init(&PShctx, passwd, passwdlen);
|
||||
crypto_auth_hmacsha256_update(&PShctx, salt, saltlen);
|
||||
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
STORE32_BE(ivec, (uint32_t)(i + 1));
|
||||
memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha256_state));
|
||||
crypto_auth_hmacsha256_update(&hctx, ivec, 4);
|
||||
crypto_auth_hmacsha256_final(&hctx, U);
|
||||
|
||||
memcpy(T, U, 32);
|
||||
/* LCOV_EXCL_START */
|
||||
for (j = 2; j <= c; j++) {
|
||||
crypto_auth_hmacsha256_init(&hctx, passwd, passwdlen);
|
||||
crypto_auth_hmacsha256_update(&hctx, U, 32);
|
||||
crypto_auth_hmacsha256_final(&hctx, U);
|
||||
|
||||
for (k = 0; k < 32; k++) {
|
||||
T[k] ^= U[k];
|
||||
}
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
clen = dkLen - i * 32;
|
||||
if (clen > 32) {
|
||||
clen = 32;
|
||||
}
|
||||
memcpy(&buf[i * 32], T, clen);
|
||||
}
|
||||
sodium_memzero((void *) &PShctx, sizeof PShctx);
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef pbkdf2_sha256_H
|
||||
#define pbkdf2_sha256_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto_auth_hmacsha256.h"
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||
uint64_t, uint8_t *, size_t);
|
||||
|
||||
#endif /* !_SHA256_H_ */
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_pwhash_scryptsalsa208sha256.h"
|
||||
#include "crypto_scrypt.h"
|
||||
#include "randombytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define SETTING_SIZE(saltbytes) \
|
||||
((sizeof "$7$" - 1U) + \
|
||||
(1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes))
|
||||
|
||||
static int
|
||||
pickparams(unsigned long long opslimit, const size_t memlimit,
|
||||
uint32_t * const N_log2, uint32_t * const p, uint32_t * const r)
|
||||
{
|
||||
unsigned long long maxN;
|
||||
unsigned long long maxrp;
|
||||
|
||||
if (opslimit < 32768) {
|
||||
opslimit = 32768;
|
||||
}
|
||||
*r = 8;
|
||||
if (opslimit < memlimit / 32) {
|
||||
*p = 1;
|
||||
maxN = opslimit / (*r * 4);
|
||||
for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
|
||||
if ((uint64_t)(1) << *N_log2 > maxN / 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
maxN = memlimit / ((size_t) *r * 128);
|
||||
for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
|
||||
if ((uint64_t) (1) << *N_log2 > maxN / 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2);
|
||||
/* LCOV_EXCL_START */
|
||||
if (maxrp > 0x3fffffff) {
|
||||
maxrp = 0x3fffffff;
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
*p = (uint32_t) (maxrp) / *r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_scryptsalsa208sha256_strbytes(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
|
||||
}
|
||||
|
||||
const char *
|
||||
crypto_pwhash_scryptsalsa208sha256_strprefix(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
|
||||
{
|
||||
return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
|
||||
unsigned long long outlen,
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen,
|
||||
const unsigned char * const salt,
|
||||
unsigned long long opslimit,
|
||||
size_t memlimit)
|
||||
{
|
||||
uint32_t N_log2;
|
||||
uint32_t p;
|
||||
uint32_t r;
|
||||
|
||||
memset(out, 0, outlen);
|
||||
if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) {
|
||||
errno = EFBIG; /* LCOV_EXCL_LINE */
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
|
||||
errno = EINVAL; /* LCOV_EXCL_LINE */
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd,
|
||||
(size_t) passwdlen,
|
||||
(const uint8_t *) salt,
|
||||
crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
|
||||
(uint64_t) (1) << N_log2, r, p,
|
||||
out, (size_t) outlen);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen,
|
||||
unsigned long long opslimit,
|
||||
size_t memlimit)
|
||||
{
|
||||
uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
|
||||
char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
|
||||
escrypt_local_t escrypt_local;
|
||||
uint32_t N_log2;
|
||||
uint32_t p;
|
||||
uint32_t r;
|
||||
|
||||
memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
|
||||
if (passwdlen > SIZE_MAX) {
|
||||
errno = EFBIG; /* LCOV_EXCL_LINE */
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
|
||||
errno = EINVAL; /* LCOV_EXCL_LINE */
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
randombytes_buf(salt, sizeof salt);
|
||||
if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt,
|
||||
(uint8_t *) setting, sizeof setting) == NULL) {
|
||||
errno = EINVAL; /* LCOV_EXCL_LINE */
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (escrypt_init_local(&escrypt_local) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
|
||||
(const uint8_t *) setting, (uint8_t *) out,
|
||||
crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
|
||||
/* LCOV_EXCL_START */
|
||||
escrypt_free_local(&escrypt_local);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
escrypt_free_local(&escrypt_local);
|
||||
|
||||
(void) sizeof
|
||||
(int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES)
|
||||
== crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]);
|
||||
(void) sizeof
|
||||
(int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
|
||||
crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U
|
||||
== crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
|
||||
const char * const passwd,
|
||||
unsigned long long passwdlen)
|
||||
{
|
||||
char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
|
||||
escrypt_local_t escrypt_local;
|
||||
int ret = -1;
|
||||
|
||||
if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
|
||||
&str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
|
||||
return -1;
|
||||
}
|
||||
if (escrypt_init_local(&escrypt_local) != 0) {
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
memset(wanted, 0, sizeof wanted);
|
||||
if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
|
||||
(const uint8_t *) str, (uint8_t *) wanted,
|
||||
sizeof wanted) == NULL) {
|
||||
escrypt_free_local(&escrypt_local);
|
||||
return -1;
|
||||
}
|
||||
escrypt_free_local(&escrypt_local);
|
||||
ret = sodium_memcmp(wanted, str, sizeof wanted);
|
||||
sodium_memzero(wanted, sizeof wanted);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*-
|
||||
* Copyright 2013 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "crypto_scrypt.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
|
||||
# define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
void *
|
||||
alloc_region(escrypt_region_t * region, size_t size)
|
||||
{
|
||||
uint8_t * base, * aligned;
|
||||
#if defined(MAP_ANON) && defined(HAVE_MMAP)
|
||||
if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
|
||||
#else
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
#endif
|
||||
-1, 0)) == MAP_FAILED)
|
||||
base = NULL; /* LCOV_EXCL_LINE */
|
||||
aligned = base;
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
if ((errno = posix_memalign((void **) &base, 64, size)) != 0)
|
||||
base = NULL;
|
||||
aligned = base;
|
||||
#else
|
||||
base = aligned = NULL;
|
||||
if (size + 63 < size)
|
||||
errno = ENOMEM;
|
||||
else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
|
||||
aligned = base + 63;
|
||||
aligned -= (uintptr_t)aligned & 63;
|
||||
}
|
||||
#endif
|
||||
region->base = base;
|
||||
region->aligned = aligned;
|
||||
region->size = base ? size : 0;
|
||||
return aligned;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_region(escrypt_region_t * region)
|
||||
{
|
||||
region->base = region->aligned = NULL;
|
||||
region->size = 0;
|
||||
}
|
||||
|
||||
int
|
||||
free_region(escrypt_region_t * region)
|
||||
{
|
||||
if (region->base) {
|
||||
#if defined(MAP_ANON) && defined(HAVE_MMAP)
|
||||
if (munmap(region->base, region->size))
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
#else
|
||||
free(region->base);
|
||||
#endif
|
||||
}
|
||||
init_region(region);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
escrypt_init_local(escrypt_local_t * local)
|
||||
{
|
||||
init_region(local);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
escrypt_free_local(escrypt_local_t * local)
|
||||
{
|
||||
return free_region(local);
|
||||
}
|
||||
+392
@@ -0,0 +1,392 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2012,2013 Alexander Peslyak
|
||||
* 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.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_EMMINTRIN_H) || \
|
||||
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC target("sse2")
|
||||
#endif
|
||||
#include <emmintrin.h>
|
||||
#if defined(__XOP__) && defined(DISABLED)
|
||||
# include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../pbkdf2-sha256.h"
|
||||
#include "../crypto_scrypt.h"
|
||||
#include "private/common.h"
|
||||
|
||||
#if defined(__XOP__) && defined(DISABLED)
|
||||
#define ARX(out, in1, in2, s) \
|
||||
out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s));
|
||||
#else
|
||||
#define ARX(out, in1, in2, s) \
|
||||
{ \
|
||||
__m128i T = _mm_add_epi32(in1, in2); \
|
||||
out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \
|
||||
out = _mm_xor_si128(out, _mm_srli_epi32(T, 32-s)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SALSA20_2ROUNDS \
|
||||
/* Operate on "columns". */ \
|
||||
ARX(X1, X0, X3, 7) \
|
||||
ARX(X2, X1, X0, 9) \
|
||||
ARX(X3, X2, X1, 13) \
|
||||
ARX(X0, X3, X2, 18) \
|
||||
\
|
||||
/* Rearrange data. */ \
|
||||
X1 = _mm_shuffle_epi32(X1, 0x93); \
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E); \
|
||||
X3 = _mm_shuffle_epi32(X3, 0x39); \
|
||||
\
|
||||
/* Operate on "rows". */ \
|
||||
ARX(X3, X0, X1, 7) \
|
||||
ARX(X2, X3, X0, 9) \
|
||||
ARX(X1, X2, X3, 13) \
|
||||
ARX(X0, X1, X2, 18) \
|
||||
\
|
||||
/* Rearrange data. */ \
|
||||
X1 = _mm_shuffle_epi32(X1, 0x39); \
|
||||
X2 = _mm_shuffle_epi32(X2, 0x4E); \
|
||||
X3 = _mm_shuffle_epi32(X3, 0x93);
|
||||
|
||||
/**
|
||||
* Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3).
|
||||
*/
|
||||
#define SALSA20_8_XOR(in, out) \
|
||||
{ \
|
||||
__m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \
|
||||
__m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \
|
||||
__m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \
|
||||
__m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \
|
||||
SALSA20_2ROUNDS \
|
||||
SALSA20_2ROUNDS \
|
||||
SALSA20_2ROUNDS \
|
||||
SALSA20_2ROUNDS \
|
||||
(out)[0] = X0 = _mm_add_epi32(X0, Y0); \
|
||||
(out)[1] = X1 = _mm_add_epi32(X1, Y1); \
|
||||
(out)[2] = X2 = _mm_add_epi32(X2, Y2); \
|
||||
(out)[3] = X3 = _mm_add_epi32(X3, Y3); \
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(Bin, Bout, r):
|
||||
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
|
||||
* bytes in length; the output Bout must also be the same size.
|
||||
*/
|
||||
static inline void
|
||||
blockmix_salsa8(const __m128i * Bin, __m128i * Bout, size_t r)
|
||||
{
|
||||
__m128i X0, X1, X2, X3;
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
X0 = Bin[8 * r - 4];
|
||||
X1 = Bin[8 * r - 3];
|
||||
X2 = Bin[8 * r - 2];
|
||||
X3 = Bin[8 * r - 1];
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
SALSA20_8_XOR(Bin, Bout)
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
r--;
|
||||
for (i = 0; i < r;) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
|
||||
|
||||
i++;
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4])
|
||||
}
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
|
||||
}
|
||||
|
||||
#define XOR4(in) \
|
||||
X0 = _mm_xor_si128(X0, (in)[0]); \
|
||||
X1 = _mm_xor_si128(X1, (in)[1]); \
|
||||
X2 = _mm_xor_si128(X2, (in)[2]); \
|
||||
X3 = _mm_xor_si128(X3, (in)[3]);
|
||||
|
||||
#define XOR4_2(in1, in2) \
|
||||
X0 = _mm_xor_si128((in1)[0], (in2)[0]); \
|
||||
X1 = _mm_xor_si128((in1)[1], (in2)[1]); \
|
||||
X2 = _mm_xor_si128((in1)[2], (in2)[2]); \
|
||||
X3 = _mm_xor_si128((in1)[3], (in2)[3]);
|
||||
|
||||
static inline uint32_t
|
||||
blockmix_salsa8_xor(const __m128i * Bin1, const __m128i * Bin2, __m128i * Bout,
|
||||
size_t r)
|
||||
{
|
||||
__m128i X0, X1, X2, X3;
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4])
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
XOR4(Bin1)
|
||||
SALSA20_8_XOR(Bin2, Bout)
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
r--;
|
||||
for (i = 0; i < r;) {
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
XOR4(&Bin1[i * 8 + 4])
|
||||
SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
|
||||
|
||||
i++;
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
XOR4(&Bin1[i * 8])
|
||||
SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4])
|
||||
}
|
||||
|
||||
/* 3: X <-- H(X \xor B_i) */
|
||||
/* 4: Y_i <-- X */
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
XOR4(&Bin1[i * 8 + 4])
|
||||
SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
|
||||
|
||||
return _mm_cvtsi128_si32(X0);
|
||||
}
|
||||
|
||||
#undef ARX
|
||||
#undef SALSA20_2ROUNDS
|
||||
#undef SALSA20_8_XOR
|
||||
#undef XOR4
|
||||
#undef XOR4_2
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
* Note that B's layout is permuted compared to the generic implementation.
|
||||
*/
|
||||
static inline uint32_t
|
||||
integerify(const void * B, size_t r)
|
||||
{
|
||||
return *(const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, V, XY):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
|
||||
* the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r + 64 bytes in length. The value N must be a
|
||||
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
|
||||
* multiple of 64 bytes.
|
||||
*/
|
||||
static void
|
||||
smix(uint8_t * B, size_t r, uint32_t N, void * V, void * XY)
|
||||
{
|
||||
size_t s = 128 * r;
|
||||
__m128i * X = (__m128i *) V, * Y;
|
||||
uint32_t * X32 = (uint32_t *) V;
|
||||
uint32_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
/* 3: V_i <-- X */
|
||||
for (k = 0; k < 2 * r; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
X32[k * 16 + i] =
|
||||
LOAD32_LE(&B[(k * 16 + (i * 5 % 16)) * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 1; i < N - 1; i += 2) {
|
||||
/* 4: X <-- H(X) */
|
||||
/* 3: V_i <-- X */
|
||||
Y = (__m128i *)((uintptr_t)(V) + i * s);
|
||||
blockmix_salsa8(X, Y, r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
/* 3: V_i <-- X */
|
||||
X = (__m128i *)((uintptr_t)(V) + (i + 1) * s);
|
||||
blockmix_salsa8(Y, X, r);
|
||||
}
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
/* 3: V_i <-- X */
|
||||
Y = (__m128i *)((uintptr_t)(V) + i * s);
|
||||
blockmix_salsa8(X, Y, r);
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
/* 3: V_i <-- X */
|
||||
X = (__m128i *) XY;
|
||||
blockmix_salsa8(Y, X, r);
|
||||
|
||||
X32 = (uint32_t *) XY;
|
||||
Y = (__m128i *)((uintptr_t)(XY) + s);
|
||||
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i += 2) {
|
||||
__m128i * V_j = (__m128i *)((uintptr_t)(V) + j * s);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1);
|
||||
V_j = (__m128i *)((uintptr_t)(V) + j * s);
|
||||
|
||||
/* 8: X <-- H(X \xor V_j) */
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
STORE32_LE(&B[(k * 16 + (i * 5 % 16)) * 4], X32[k * 16 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
|
||||
* N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
int
|
||||
escrypt_kdf_sse(escrypt_local_t * local,
|
||||
const uint8_t * passwd, size_t passwdlen,
|
||||
const uint8_t * salt, size_t saltlen,
|
||||
uint64_t N, uint32_t _r, uint32_t _p,
|
||||
uint8_t * buf, size_t buflen)
|
||||
{
|
||||
size_t B_size, V_size, XY_size, need;
|
||||
uint8_t * B;
|
||||
uint32_t * V, * XY;
|
||||
size_t r = _r, p = _p;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters. */
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if ((uint64_t)(r) * (uint64_t)(p) >= ((uint64_t) 1 << 30)) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (N > UINT32_MAX) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
if (((N & (N - 1)) != 0) || (N < 2)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (r == 0 || p == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if ((r > SIZE_MAX / 128 / p) ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
(r > SIZE_MAX / 256) ||
|
||||
#endif
|
||||
(N > SIZE_MAX / 128 / r)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate memory. */
|
||||
B_size = (size_t)128 * r * p;
|
||||
V_size = (size_t)128 * r * N;
|
||||
need = B_size + V_size;
|
||||
if (need < V_size) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
XY_size = (size_t)256 * r + 64;
|
||||
need += XY_size;
|
||||
if (need < XY_size) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (local->size < need) {
|
||||
if (free_region(local))
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
if (!alloc_region(local, need))
|
||||
return -1; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
B = (uint8_t *)local->aligned;
|
||||
V = (uint32_t *)((uint8_t *)B + B_size);
|
||||
XY = (uint32_t *)((uint8_t *)V + V_size);
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
|
||||
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[(size_t)128 * i * r], r, (uint32_t) N, V, XY);
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
|
||||
|
||||
/* Success! */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
#include "crypto_scalarmult.h"
|
||||
|
||||
const char *
|
||||
crypto_scalarmult_primitive(void)
|
||||
{
|
||||
return crypto_scalarmult_PRIMITIVE;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_scalarmult_base(unsigned char *q, const unsigned char *n)
|
||||
{
|
||||
return crypto_scalarmult_curve25519_base(q, n);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_scalarmult(unsigned char *q, const unsigned char *n,
|
||||
const unsigned char *p)
|
||||
{
|
||||
return crypto_scalarmult_curve25519(q, n, p);
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_scalarmult_bytes(void)
|
||||
{
|
||||
return crypto_scalarmult_BYTES;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_scalarmult_scalarbytes(void)
|
||||
{
|
||||
return crypto_scalarmult_SCALARBYTES;
|
||||
}
|
||||
Generated
+480
@@ -0,0 +1,480 @@
|
||||
/* Copyright 2008, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Code released into the public domain.
|
||||
*
|
||||
* curve25519-donna: Curve25519 elliptic curve, public key function
|
||||
*
|
||||
* http://code.google.com/p/curve25519-donna/
|
||||
*
|
||||
* Adam Langley <agl@imperialviolet.org>
|
||||
* Parts optimised by floodyberry
|
||||
* Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
|
||||
*
|
||||
* More information about curve25519 can be found here
|
||||
* http://cr.yp.to/ecdh.html
|
||||
*
|
||||
* djb's sample implementation of curve25519 is written in a special assembly
|
||||
* language called qhasm and uses the floating point registers.
|
||||
*
|
||||
* This is, almost, a clean room reimplementation from the curve25519 paper. It
|
||||
* uses many of the tricks described therein. Only the crecip function is taken
|
||||
* from the sample implementation.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_TI_MODE
|
||||
|
||||
#include "utils.h"
|
||||
#include "curve25519_donna_c64.h"
|
||||
#include "../scalarmult_curve25519.h"
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint64_t limb;
|
||||
typedef limb felem[5];
|
||||
/* Special gcc mode for 128-bit integers */
|
||||
typedef unsigned uint128_t __attribute__ ((mode(TI)));
|
||||
|
||||
/* Sum two numbers: output += in */
|
||||
static inline void
|
||||
fsum(limb *output, const limb *in) {
|
||||
output[0] += in[0];
|
||||
output[1] += in[1];
|
||||
output[2] += in[2];
|
||||
output[3] += in[3];
|
||||
output[4] += in[4];
|
||||
}
|
||||
|
||||
/* Find the difference of two numbers: output = in - output
|
||||
* (note the order of the arguments!)
|
||||
*
|
||||
* Assumes that out[i] < 2**52
|
||||
* On return, out[i] < 2**55
|
||||
*/
|
||||
static inline void
|
||||
fdifference_backwards(felem out, const felem in) {
|
||||
/* 152 is 19 << 3 */
|
||||
static const limb two54m152 = (((limb)1) << 54) - 152;
|
||||
static const limb two54m8 = (((limb)1) << 54) - 8;
|
||||
|
||||
out[0] = in[0] + two54m152 - out[0];
|
||||
out[1] = in[1] + two54m8 - out[1];
|
||||
out[2] = in[2] + two54m8 - out[2];
|
||||
out[3] = in[3] + two54m8 - out[3];
|
||||
out[4] = in[4] + two54m8 - out[4];
|
||||
}
|
||||
|
||||
/* Multiply a number by a scalar: output = in * scalar */
|
||||
static inline void
|
||||
fscalar_product(felem output, const felem in, const limb scalar) {
|
||||
uint128_t a;
|
||||
|
||||
a = ((uint128_t) in[0]) * scalar;
|
||||
output[0] = ((limb)a) & 0x7ffffffffffff;
|
||||
|
||||
a = ((uint128_t) in[1]) * scalar + ((limb) (a >> 51));
|
||||
output[1] = ((limb)a) & 0x7ffffffffffff;
|
||||
|
||||
a = ((uint128_t) in[2]) * scalar + ((limb) (a >> 51));
|
||||
output[2] = ((limb)a) & 0x7ffffffffffff;
|
||||
|
||||
a = ((uint128_t) in[3]) * scalar + ((limb) (a >> 51));
|
||||
output[3] = ((limb)a) & 0x7ffffffffffff;
|
||||
|
||||
a = ((uint128_t) in[4]) * scalar + ((limb) (a >> 51));
|
||||
output[4] = ((limb)a) & 0x7ffffffffffff;
|
||||
|
||||
output[0] += (a >> 51) * 19;
|
||||
}
|
||||
|
||||
/* Multiply two numbers: output = in2 * in
|
||||
*
|
||||
* output must be distinct to both inputs. The inputs are reduced coefficient
|
||||
* form, the output is not.
|
||||
*
|
||||
* Assumes that in[i] < 2**55 and likewise for in2.
|
||||
* On return, output[i] < 2**52
|
||||
*/
|
||||
static inline void
|
||||
fmul(felem output, const felem in2, const felem in) {
|
||||
uint128_t t[5];
|
||||
limb r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c;
|
||||
|
||||
r0 = in[0];
|
||||
r1 = in[1];
|
||||
r2 = in[2];
|
||||
r3 = in[3];
|
||||
r4 = in[4];
|
||||
|
||||
s0 = in2[0];
|
||||
s1 = in2[1];
|
||||
s2 = in2[2];
|
||||
s3 = in2[3];
|
||||
s4 = in2[4];
|
||||
|
||||
t[0] = ((uint128_t) r0) * s0;
|
||||
t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0;
|
||||
t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1;
|
||||
t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1;
|
||||
t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2;
|
||||
|
||||
r4 *= 19;
|
||||
r1 *= 19;
|
||||
r2 *= 19;
|
||||
r3 *= 19;
|
||||
|
||||
t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2;
|
||||
t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3;
|
||||
t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4;
|
||||
t[3] += ((uint128_t) r4) * s4;
|
||||
|
||||
r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51);
|
||||
t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51);
|
||||
t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51);
|
||||
t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51);
|
||||
t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51);
|
||||
r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff;
|
||||
r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff;
|
||||
r2 += c;
|
||||
|
||||
output[0] = r0;
|
||||
output[1] = r1;
|
||||
output[2] = r2;
|
||||
output[3] = r3;
|
||||
output[4] = r4;
|
||||
}
|
||||
|
||||
static inline void
|
||||
fsquare_times(felem output, const felem in, limb count) {
|
||||
uint128_t t[5];
|
||||
limb r0,r1,r2,r3,r4,c;
|
||||
limb d0,d1,d2,d4,d419;
|
||||
|
||||
r0 = in[0];
|
||||
r1 = in[1];
|
||||
r2 = in[2];
|
||||
r3 = in[3];
|
||||
r4 = in[4];
|
||||
|
||||
do {
|
||||
d0 = r0 * 2;
|
||||
d1 = r1 * 2;
|
||||
d2 = r2 * 2 * 19;
|
||||
d419 = r4 * 19;
|
||||
d4 = d419 * 2;
|
||||
|
||||
t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 ));
|
||||
t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19));
|
||||
t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 ));
|
||||
t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 ));
|
||||
t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 ));
|
||||
|
||||
r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51);
|
||||
t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51);
|
||||
t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51);
|
||||
t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51);
|
||||
t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51);
|
||||
r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff;
|
||||
r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff;
|
||||
r2 += c;
|
||||
} while(--count);
|
||||
|
||||
output[0] = r0;
|
||||
output[1] = r1;
|
||||
output[2] = r2;
|
||||
output[3] = r3;
|
||||
output[4] = r4;
|
||||
}
|
||||
|
||||
#ifdef NATIVE_LITTLE_ENDIAN
|
||||
static inline limb
|
||||
load_limb(const u8 *in) {
|
||||
limb out;
|
||||
memcpy(&out, in, sizeof (limb));
|
||||
return out;
|
||||
}
|
||||
static inline void
|
||||
store_limb(u8 *out, limb in) {
|
||||
memcpy(out, &in, sizeof (limb));
|
||||
}
|
||||
#else
|
||||
static inline limb
|
||||
load_limb(const u8 *in) {
|
||||
return
|
||||
((limb)in[0]) |
|
||||
(((limb)in[1]) << 8) |
|
||||
(((limb)in[2]) << 16) |
|
||||
(((limb)in[3]) << 24) |
|
||||
(((limb)in[4]) << 32) |
|
||||
(((limb)in[5]) << 40) |
|
||||
(((limb)in[6]) << 48) |
|
||||
(((limb)in[7]) << 56);
|
||||
}
|
||||
|
||||
static inline void
|
||||
store_limb(u8 *out, limb in) {
|
||||
out[0] = in & 0xff;
|
||||
out[1] = (in >> 8) & 0xff;
|
||||
out[2] = (in >> 16) & 0xff;
|
||||
out[3] = (in >> 24) & 0xff;
|
||||
out[4] = (in >> 32) & 0xff;
|
||||
out[5] = (in >> 40) & 0xff;
|
||||
out[6] = (in >> 48) & 0xff;
|
||||
out[7] = (in >> 56) & 0xff;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Take a little-endian, 32-byte number and expand it into polynomial form */
|
||||
static void
|
||||
fexpand(limb *output, const u8 *in) {
|
||||
output[0] = load_limb(in) & 0x7ffffffffffff;
|
||||
output[1] = (load_limb(in+6) >> 3) & 0x7ffffffffffff;
|
||||
output[2] = (load_limb(in+12) >> 6) & 0x7ffffffffffff;
|
||||
output[3] = (load_limb(in+19) >> 1) & 0x7ffffffffffff;
|
||||
output[4] = (load_limb(in+24) >> 12) & 0x7ffffffffffff;
|
||||
}
|
||||
|
||||
/* Take a fully reduced polynomial form number and contract it into a
|
||||
* little-endian, 32-byte array
|
||||
*/
|
||||
static void
|
||||
fcontract(u8 *output, const felem input) {
|
||||
uint128_t t[5];
|
||||
|
||||
t[0] = input[0];
|
||||
t[1] = input[1];
|
||||
t[2] = input[2];
|
||||
t[3] = input[3];
|
||||
t[4] = input[4];
|
||||
|
||||
t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;
|
||||
t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;
|
||||
t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;
|
||||
t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;
|
||||
t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff;
|
||||
|
||||
t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;
|
||||
t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;
|
||||
t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;
|
||||
t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;
|
||||
t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff;
|
||||
|
||||
/* now t is between 0 and 2^255-1, properly carried. */
|
||||
/* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
|
||||
|
||||
t[0] += 19;
|
||||
|
||||
t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;
|
||||
t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;
|
||||
t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;
|
||||
t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;
|
||||
t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff;
|
||||
|
||||
/* now between 19 and 2^255-1 in both cases, and offset by 19. */
|
||||
|
||||
t[0] += 0x8000000000000 - 19;
|
||||
t[1] += 0x8000000000000 - 1;
|
||||
t[2] += 0x8000000000000 - 1;
|
||||
t[3] += 0x8000000000000 - 1;
|
||||
t[4] += 0x8000000000000 - 1;
|
||||
|
||||
/* now between 2^255 and 2^256-20, and offset by 2^255. */
|
||||
|
||||
t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff;
|
||||
t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff;
|
||||
t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff;
|
||||
t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff;
|
||||
t[4] &= 0x7ffffffffffff;
|
||||
|
||||
store_limb(output, t[0] | (t[1] << 51));
|
||||
store_limb(output + 8, (t[1] >> 13) | (t[2] << 38));
|
||||
store_limb(output + 16, (t[2] >> 26) | (t[3] << 25));
|
||||
store_limb(output + 24, (t[3] >> 39) | (t[4] << 12));
|
||||
}
|
||||
|
||||
/* Input: Q, Q', Q-Q'
|
||||
* Output: 2Q, Q+Q'
|
||||
*
|
||||
* x2 z2: long form
|
||||
* x3 z3: long form
|
||||
* x z: short form, destroyed
|
||||
* xprime zprime: short form, destroyed
|
||||
* qmqp: short form, preserved
|
||||
*/
|
||||
static void
|
||||
fmonty(limb *x2, limb *z2, /* output 2Q */
|
||||
limb *x3, limb *z3, /* output Q + Q' */
|
||||
limb *x, limb *z, /* input Q */
|
||||
limb *xprime, limb *zprime, /* input Q' */
|
||||
const limb *qmqp /* input Q - Q' */) {
|
||||
limb origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5],
|
||||
zzprime[5], zzzprime[5];
|
||||
|
||||
memcpy(origx, x, 5 * sizeof(limb));
|
||||
fsum(x, z);
|
||||
fdifference_backwards(z, origx); /* does x - z */
|
||||
|
||||
memcpy(origxprime, xprime, sizeof(limb) * 5);
|
||||
fsum(xprime, zprime);
|
||||
fdifference_backwards(zprime, origxprime);
|
||||
fmul(xxprime, xprime, z);
|
||||
fmul(zzprime, x, zprime);
|
||||
memcpy(origxprime, xxprime, sizeof(limb) * 5);
|
||||
fsum(xxprime, zzprime);
|
||||
fdifference_backwards(zzprime, origxprime);
|
||||
fsquare_times(x3, xxprime, 1);
|
||||
fsquare_times(zzzprime, zzprime, 1);
|
||||
fmul(z3, zzzprime, qmqp);
|
||||
|
||||
fsquare_times(xx, x, 1);
|
||||
fsquare_times(zz, z, 1);
|
||||
fmul(x2, xx, zz);
|
||||
fdifference_backwards(zz, xx); /* does zz = xx - zz */
|
||||
fscalar_product(zzz, zz, 121665);
|
||||
fsum(zzz, xx);
|
||||
fmul(z2, zz, zzz);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Maybe swap the contents of two limb arrays (@a and @b), each @len elements
|
||||
long. Perform the swap iff @swap is non-zero.
|
||||
|
||||
This function performs the swap without leaking any side-channel
|
||||
information.
|
||||
----------------------------------------------------------------------------- */
|
||||
static void
|
||||
swap_conditional(limb a[5], limb b[5], limb iswap) {
|
||||
unsigned i;
|
||||
const limb swap = -iswap;
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
const limb x = swap & (a[i] ^ b[i]);
|
||||
a[i] ^= x;
|
||||
b[i] ^= x;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculates nQ where Q is the x-coordinate of a point on the curve
|
||||
*
|
||||
* resultx/resultz: the x coordinate of the resulting curve point (short form)
|
||||
* n: a little endian, 32-byte number
|
||||
* q: a point of the curve (short form)
|
||||
*/
|
||||
static void
|
||||
cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
|
||||
limb a[5] = {0}, b[5] = {1}, c[5] = {1}, d[5] = {0};
|
||||
limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
|
||||
limb e[5] = {0}, f[5] = {1}, g[5] = {0}, h[5] = {1};
|
||||
limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
|
||||
|
||||
unsigned i, j;
|
||||
|
||||
memcpy(nqpqx, q, sizeof(limb) * 5);
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
u8 byte = n[31 - i];
|
||||
for (j = 0; j < 8; ++j) {
|
||||
const limb bit = byte >> 7;
|
||||
|
||||
swap_conditional(nqx, nqpqx, bit);
|
||||
swap_conditional(nqz, nqpqz, bit);
|
||||
fmonty(nqx2, nqz2,
|
||||
nqpqx2, nqpqz2,
|
||||
nqx, nqz,
|
||||
nqpqx, nqpqz,
|
||||
q);
|
||||
swap_conditional(nqx2, nqpqx2, bit);
|
||||
swap_conditional(nqz2, nqpqz2, bit);
|
||||
|
||||
t = nqx;
|
||||
nqx = nqx2;
|
||||
nqx2 = t;
|
||||
t = nqz;
|
||||
nqz = nqz2;
|
||||
nqz2 = t;
|
||||
t = nqpqx;
|
||||
nqpqx = nqpqx2;
|
||||
nqpqx2 = t;
|
||||
t = nqpqz;
|
||||
nqpqz = nqpqz2;
|
||||
nqpqz2 = t;
|
||||
|
||||
byte <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(resultx, nqx, sizeof(limb) * 5);
|
||||
memcpy(resultz, nqz, sizeof(limb) * 5);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Shamelessly copied from djb's code, tightened a little
|
||||
----------------------------------------------------------------------------- */
|
||||
static void
|
||||
crecip(felem out, const felem z) {
|
||||
felem a,t0,b,c;
|
||||
|
||||
/* 2 */ fsquare_times(a, z, 1); /* a = 2 */
|
||||
/* 8 */ fsquare_times(t0, a, 2);
|
||||
/* 9 */ fmul(b, t0, z); /* b = 9 */
|
||||
/* 11 */ fmul(a, b, a); /* a = 11 */
|
||||
/* 22 */ fsquare_times(t0, a, 1);
|
||||
/* 2^5 - 2^0 = 31 */ fmul(b, t0, b);
|
||||
/* 2^10 - 2^5 */ fsquare_times(t0, b, 5);
|
||||
/* 2^10 - 2^0 */ fmul(b, t0, b);
|
||||
/* 2^20 - 2^10 */ fsquare_times(t0, b, 10);
|
||||
/* 2^20 - 2^0 */ fmul(c, t0, b);
|
||||
/* 2^40 - 2^20 */ fsquare_times(t0, c, 20);
|
||||
/* 2^40 - 2^0 */ fmul(t0, t0, c);
|
||||
/* 2^50 - 2^10 */ fsquare_times(t0, t0, 10);
|
||||
/* 2^50 - 2^0 */ fmul(b, t0, b);
|
||||
/* 2^100 - 2^50 */ fsquare_times(t0, b, 50);
|
||||
/* 2^100 - 2^0 */ fmul(c, t0, b);
|
||||
/* 2^200 - 2^100 */ fsquare_times(t0, c, 100);
|
||||
/* 2^200 - 2^0 */ fmul(t0, t0, c);
|
||||
/* 2^250 - 2^50 */ fsquare_times(t0, t0, 50);
|
||||
/* 2^250 - 2^0 */ fmul(t0, t0, b);
|
||||
/* 2^255 - 2^5 */ fsquare_times(t0, t0, 5);
|
||||
/* 2^255 - 21 */ fmul(out, t0, a);
|
||||
}
|
||||
|
||||
static const unsigned char basepoint[32] = {9};
|
||||
|
||||
static int
|
||||
crypto_scalarmult_curve25519_donna_c64(unsigned char *mypublic,
|
||||
const unsigned char *secret,
|
||||
const unsigned char *basepoint) {
|
||||
limb bp[5], x[5], z[5], zmone[5];
|
||||
uint8_t e[32];
|
||||
int i;
|
||||
|
||||
for (i = 0;i < 32;++i) e[i] = secret[i];
|
||||
e[0] &= 248;
|
||||
e[31] &= 127;
|
||||
e[31] |= 64;
|
||||
|
||||
fexpand(bp, basepoint);
|
||||
cmult(x, z, e, bp);
|
||||
crecip(zmone, z);
|
||||
fmul(z, x, zmone);
|
||||
fcontract(mypublic, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_scalarmult_curve25519_donna_c64_base(unsigned char *q,
|
||||
const unsigned char *n)
|
||||
{
|
||||
return crypto_scalarmult_curve25519_donna_c64(q, n, basepoint);
|
||||
}
|
||||
|
||||
struct crypto_scalarmult_curve25519_implementation
|
||||
crypto_scalarmult_curve25519_donna_c64_implementation = {
|
||||
SODIUM_C99(.mult = ) crypto_scalarmult_curve25519_donna_c64,
|
||||
SODIUM_C99(.mult_base = ) crypto_scalarmult_curve25519_donna_c64_base
|
||||
};
|
||||
|
||||
#endif
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
#ifndef curve25519_donna_c64_H
|
||||
#define curve25519_donna_c64_H
|
||||
|
||||
#include "crypto_scalarmult_curve25519.h"
|
||||
#include "../scalarmult_curve25519.h"
|
||||
|
||||
extern struct crypto_scalarmult_curve25519_implementation
|
||||
crypto_scalarmult_curve25519_donna_c64_implementation;
|
||||
|
||||
#endif
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef HAVE_TI_MODE
|
||||
|
||||
#include "utils.h"
|
||||
#include "x25519_ref10.h"
|
||||
#include "../scalarmult_curve25519.h"
|
||||
#include "private/curve25519_ref10.h"
|
||||
|
||||
/*
|
||||
Replace (f,g) with (g,f) if b == 1;
|
||||
replace (f,g) with (f,g) if b == 0.
|
||||
|
||||
Preconditions: b in {0,1}.
|
||||
*/
|
||||
|
||||
static void
|
||||
fe_cswap(fe f,fe g,unsigned int b)
|
||||
{
|
||||
int32_t f0 = f[0];
|
||||
int32_t f1 = f[1];
|
||||
int32_t f2 = f[2];
|
||||
int32_t f3 = f[3];
|
||||
int32_t f4 = f[4];
|
||||
int32_t f5 = f[5];
|
||||
int32_t f6 = f[6];
|
||||
int32_t f7 = f[7];
|
||||
int32_t f8 = f[8];
|
||||
int32_t f9 = f[9];
|
||||
int32_t g0 = g[0];
|
||||
int32_t g1 = g[1];
|
||||
int32_t g2 = g[2];
|
||||
int32_t g3 = g[3];
|
||||
int32_t g4 = g[4];
|
||||
int32_t g5 = g[5];
|
||||
int32_t g6 = g[6];
|
||||
int32_t g7 = g[7];
|
||||
int32_t g8 = g[8];
|
||||
int32_t g9 = g[9];
|
||||
int32_t x0 = f0 ^ g0;
|
||||
int32_t x1 = f1 ^ g1;
|
||||
int32_t x2 = f2 ^ g2;
|
||||
int32_t x3 = f3 ^ g3;
|
||||
int32_t x4 = f4 ^ g4;
|
||||
int32_t x5 = f5 ^ g5;
|
||||
int32_t x6 = f6 ^ g6;
|
||||
int32_t x7 = f7 ^ g7;
|
||||
int32_t x8 = f8 ^ g8;
|
||||
int32_t x9 = f9 ^ g9;
|
||||
b = (unsigned int) (- (int) b);
|
||||
x0 &= b;
|
||||
x1 &= b;
|
||||
x2 &= b;
|
||||
x3 &= b;
|
||||
x4 &= b;
|
||||
x5 &= b;
|
||||
x6 &= b;
|
||||
x7 &= b;
|
||||
x8 &= b;
|
||||
x9 &= b;
|
||||
f[0] = f0 ^ x0;
|
||||
f[1] = f1 ^ x1;
|
||||
f[2] = f2 ^ x2;
|
||||
f[3] = f3 ^ x3;
|
||||
f[4] = f4 ^ x4;
|
||||
f[5] = f5 ^ x5;
|
||||
f[6] = f6 ^ x6;
|
||||
f[7] = f7 ^ x7;
|
||||
f[8] = f8 ^ x8;
|
||||
f[9] = f9 ^ x9;
|
||||
g[0] = g0 ^ x0;
|
||||
g[1] = g1 ^ x1;
|
||||
g[2] = g2 ^ x2;
|
||||
g[3] = g3 ^ x3;
|
||||
g[4] = g4 ^ x4;
|
||||
g[5] = g5 ^ x5;
|
||||
g[6] = g6 ^ x6;
|
||||
g[7] = g7 ^ x7;
|
||||
g[8] = g8 ^ x8;
|
||||
g[9] = g9 ^ x9;
|
||||
}
|
||||
|
||||
/*
|
||||
h = f * 121666
|
||||
Can overlap h with f.
|
||||
|
||||
Preconditions:
|
||||
|f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
|
||||
|
||||
Postconditions:
|
||||
|h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
|
||||
*/
|
||||
|
||||
static void
|
||||
fe_mul121666(fe h,const fe f)
|
||||
{
|
||||
int32_t f0 = f[0];
|
||||
int32_t f1 = f[1];
|
||||
int32_t f2 = f[2];
|
||||
int32_t f3 = f[3];
|
||||
int32_t f4 = f[4];
|
||||
int32_t f5 = f[5];
|
||||
int32_t f6 = f[6];
|
||||
int32_t f7 = f[7];
|
||||
int32_t f8 = f[8];
|
||||
int32_t f9 = f[9];
|
||||
int64_t h0 = f0 * (int64_t) 121666;
|
||||
int64_t h1 = f1 * (int64_t) 121666;
|
||||
int64_t h2 = f2 * (int64_t) 121666;
|
||||
int64_t h3 = f3 * (int64_t) 121666;
|
||||
int64_t h4 = f4 * (int64_t) 121666;
|
||||
int64_t h5 = f5 * (int64_t) 121666;
|
||||
int64_t h6 = f6 * (int64_t) 121666;
|
||||
int64_t h7 = f7 * (int64_t) 121666;
|
||||
int64_t h8 = f8 * (int64_t) 121666;
|
||||
int64_t h9 = f9 * (int64_t) 121666;
|
||||
int64_t carry0;
|
||||
int64_t carry1;
|
||||
int64_t carry2;
|
||||
int64_t carry3;
|
||||
int64_t carry4;
|
||||
int64_t carry5;
|
||||
int64_t carry6;
|
||||
int64_t carry7;
|
||||
int64_t carry8;
|
||||
int64_t carry9;
|
||||
|
||||
carry9 = (h9 + ((int64_t) 1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 * ((int64_t) 1 << 25);
|
||||
carry1 = (h1 + ((int64_t) 1 << 24)) >> 25; h2 += carry1; h1 -= carry1 * ((int64_t) 1 << 25);
|
||||
carry3 = (h3 + ((int64_t) 1 << 24)) >> 25; h4 += carry3; h3 -= carry3 * ((int64_t) 1 << 25);
|
||||
carry5 = (h5 + ((int64_t) 1 << 24)) >> 25; h6 += carry5; h5 -= carry5 * ((int64_t) 1 << 25);
|
||||
carry7 = (h7 + ((int64_t) 1 << 24)) >> 25; h8 += carry7; h7 -= carry7 * ((int64_t) 1 << 25);
|
||||
|
||||
carry0 = (h0 + ((int64_t) 1 << 25)) >> 26; h1 += carry0; h0 -= carry0 * ((int64_t) 1 << 26);
|
||||
carry2 = (h2 + ((int64_t) 1 << 25)) >> 26; h3 += carry2; h2 -= carry2 * ((int64_t) 1 << 26);
|
||||
carry4 = (h4 + ((int64_t) 1 << 25)) >> 26; h5 += carry4; h4 -= carry4 * ((int64_t) 1 << 26);
|
||||
carry6 = (h6 + ((int64_t) 1 << 25)) >> 26; h7 += carry6; h6 -= carry6 * ((int64_t) 1 << 26);
|
||||
carry8 = (h8 + ((int64_t) 1 << 25)) >> 26; h9 += carry8; h8 -= carry8 * ((int64_t) 1 << 26);
|
||||
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
h[2] = h2;
|
||||
h[3] = h3;
|
||||
h[4] = h4;
|
||||
h[5] = h5;
|
||||
h[6] = h6;
|
||||
h[7] = h7;
|
||||
h[8] = h8;
|
||||
h[9] = h9;
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_scalarmult_curve25519_ref10(unsigned char *q,
|
||||
const unsigned char *n,
|
||||
const unsigned char *p)
|
||||
{
|
||||
unsigned char e[32];
|
||||
unsigned int i;
|
||||
fe x1;
|
||||
fe x2;
|
||||
fe z2;
|
||||
fe x3;
|
||||
fe z3;
|
||||
fe tmp0;
|
||||
fe tmp1;
|
||||
int pos;
|
||||
unsigned int swap;
|
||||
unsigned int b;
|
||||
|
||||
for (i = 0;i < 32;++i) e[i] = n[i];
|
||||
e[0] &= 248;
|
||||
e[31] &= 127;
|
||||
e[31] |= 64;
|
||||
fe_frombytes(x1,p);
|
||||
fe_1(x2);
|
||||
fe_0(z2);
|
||||
fe_copy(x3,x1);
|
||||
fe_1(z3);
|
||||
|
||||
swap = 0;
|
||||
for (pos = 254;pos >= 0;--pos) {
|
||||
b = e[pos / 8] >> (pos & 7);
|
||||
b &= 1;
|
||||
swap ^= b;
|
||||
fe_cswap(x2,x3,swap);
|
||||
fe_cswap(z2,z3,swap);
|
||||
swap = b;
|
||||
fe_sub(tmp0,x3,z3);
|
||||
fe_sub(tmp1,x2,z2);
|
||||
fe_add(x2,x2,z2);
|
||||
fe_add(z2,x3,z3);
|
||||
fe_mul(z3,tmp0,x2);
|
||||
fe_mul(z2,z2,tmp1);
|
||||
fe_sq(tmp0,tmp1);
|
||||
fe_sq(tmp1,x2);
|
||||
fe_add(x3,z3,z2);
|
||||
fe_sub(z2,z3,z2);
|
||||
fe_mul(x2,tmp1,tmp0);
|
||||
fe_sub(tmp1,tmp1,tmp0);
|
||||
fe_sq(z2,z2);
|
||||
fe_mul121666(z3,tmp1);
|
||||
fe_sq(x3,x3);
|
||||
fe_add(tmp0,tmp0,z3);
|
||||
fe_mul(z3,x1,z2);
|
||||
fe_mul(z2,tmp1,tmp0);
|
||||
}
|
||||
fe_cswap(x2,x3,swap);
|
||||
fe_cswap(z2,z3,swap);
|
||||
|
||||
fe_invert(z2,z2);
|
||||
fe_mul(x2,x2,z2);
|
||||
fe_tobytes(q,x2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
edwards_to_montgomery(fe montgomeryX, const fe edwardsY, const fe edwardsZ)
|
||||
{
|
||||
fe tempX;
|
||||
fe tempZ;
|
||||
|
||||
fe_add(tempX, edwardsZ, edwardsY);
|
||||
fe_sub(tempZ, edwardsZ, edwardsY);
|
||||
fe_invert(tempZ, tempZ);
|
||||
fe_mul(montgomeryX, tempX, tempZ);
|
||||
}
|
||||
|
||||
static int
|
||||
crypto_scalarmult_curve25519_ref10_base(unsigned char *q,
|
||||
const unsigned char *n)
|
||||
{
|
||||
unsigned char e[32];
|
||||
ge_p3 A;
|
||||
fe pk;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0;i < 32;++i) e[i] = n[i];
|
||||
e[0] &= 248;
|
||||
e[31] &= 127;
|
||||
e[31] |= 64;
|
||||
ge_scalarmult_base(&A, e);
|
||||
edwards_to_montgomery(pk, A.Y, A.Z);
|
||||
fe_tobytes(q, pk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct crypto_scalarmult_curve25519_implementation
|
||||
crypto_scalarmult_curve25519_ref10_implementation = {
|
||||
SODIUM_C99(.mult = ) crypto_scalarmult_curve25519_ref10,
|
||||
SODIUM_C99(.mult_base = ) crypto_scalarmult_curve25519_ref10_base
|
||||
};
|
||||
|
||||
#endif
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
#ifndef x25519_ref10_H
|
||||
#define x25519_ref10_H
|
||||
|
||||
#include "crypto_scalarmult_curve25519.h"
|
||||
#include "../scalarmult_curve25519.h"
|
||||
|
||||
extern struct crypto_scalarmult_curve25519_implementation
|
||||
crypto_scalarmult_curve25519_ref10_implementation;
|
||||
|
||||
#endif
|
||||
Generated
+20
@@ -0,0 +1,20 @@
|
||||
#ifndef consts_namespace_H
|
||||
#define consts_namespace_H
|
||||
|
||||
#define v0_0 crypto_scalarmult_curve25519_sandy2x_v0_0
|
||||
#define v1_0 crypto_scalarmult_curve25519_sandy2x_v1_0
|
||||
#define v2_1 crypto_scalarmult_curve25519_sandy2x_v2_1
|
||||
#define v9_0 crypto_scalarmult_curve25519_sandy2x_v9_0
|
||||
#define v9_9 crypto_scalarmult_curve25519_sandy2x_v9_9
|
||||
#define v19_19 crypto_scalarmult_curve25519_sandy2x_v19_19
|
||||
#define v38_1 crypto_scalarmult_curve25519_sandy2x_v38_1
|
||||
#define v38_38 crypto_scalarmult_curve25519_sandy2x_v38_38
|
||||
#define v121666_121666 crypto_scalarmult_curve25519_sandy2x_v121666_121666
|
||||
#define m25 crypto_scalarmult_curve25519_sandy2x_m25
|
||||
#define m26 crypto_scalarmult_curve25519_sandy2x_m26
|
||||
#define subc0 crypto_scalarmult_curve25519_sandy2x_subc0
|
||||
#define subc2 crypto_scalarmult_curve25519_sandy2x_subc2
|
||||
#define REDMASK51 crypto_scalarmult_curve25519_sandy2x_REDMASK51
|
||||
|
||||
#endif /* ifndef consts_namespace_H */
|
||||
|
||||
Generated
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
This file is adapted from ref10/scalarmult.c:
|
||||
The code for Mongomery ladder is replace by the ladder assembly function;
|
||||
Inversion is done in the same way as amd64-51/.
|
||||
(fe is first converted into fe51 after Mongomery ladder)
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef HAVE_AVX_ASM
|
||||
|
||||
#include "utils.h"
|
||||
#include "curve25519_sandy2x.h"
|
||||
#include "../scalarmult_curve25519.h"
|
||||
#include "fe.h"
|
||||
#include "fe51.h"
|
||||
#include "ladder.h"
|
||||
#include "ladder_base.h"
|
||||
|
||||
#define x1 var[0]
|
||||
#define x2 var[1]
|
||||
#define z2 var[2]
|
||||
|
||||
static int
|
||||
crypto_scalarmult_curve25519_sandy2x(unsigned char *q, const unsigned char *n,
|
||||
const unsigned char *p)
|
||||
{
|
||||
unsigned char e[32];
|
||||
unsigned int i;
|
||||
|
||||
fe var[3];
|
||||
|
||||
fe51 x_51;
|
||||
fe51 z_51;
|
||||
|
||||
for (i = 0;i < 32;++i) e[i] = n[i];
|
||||
e[0] &= 248;
|
||||
e[31] &= 127;
|
||||
e[31] |= 64;
|
||||
|
||||
fe_frombytes(x1, p);
|
||||
|
||||
ladder(var, e);
|
||||
|
||||
z_51.v[0] = (z2[1] << 26) + z2[0];
|
||||
z_51.v[1] = (z2[3] << 26) + z2[2];
|
||||
z_51.v[2] = (z2[5] << 26) + z2[4];
|
||||
z_51.v[3] = (z2[7] << 26) + z2[6];
|
||||
z_51.v[4] = (z2[9] << 26) + z2[8];
|
||||
|
||||
x_51.v[0] = (x2[1] << 26) + x2[0];
|
||||
x_51.v[1] = (x2[3] << 26) + x2[2];
|
||||
x_51.v[2] = (x2[5] << 26) + x2[4];
|
||||
x_51.v[3] = (x2[7] << 26) + x2[6];
|
||||
x_51.v[4] = (x2[9] << 26) + x2[8];
|
||||
|
||||
fe51_invert(&z_51, &z_51);
|
||||
fe51_mul(&x_51, &x_51, &z_51);
|
||||
fe51_pack(q, &x_51);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef x2
|
||||
#undef z2
|
||||
|
||||
#define x2 var[0]
|
||||
#define z2 var[1]
|
||||
|
||||
static int
|
||||
crypto_scalarmult_curve25519_sandy2x_base(unsigned char *q,
|
||||
const unsigned char *n)
|
||||
{
|
||||
unsigned char e[32];
|
||||
unsigned int i;
|
||||
|
||||
fe var[3];
|
||||
|
||||
fe51 x_51;
|
||||
fe51 z_51;
|
||||
|
||||
for (i = 0;i < 32;++i) e[i] = n[i];
|
||||
e[0] &= 248;
|
||||
e[31] &= 127;
|
||||
e[31] |= 64;
|
||||
|
||||
ladder_base(var, e);
|
||||
|
||||
z_51.v[0] = (z2[1] << 26) + z2[0];
|
||||
z_51.v[1] = (z2[3] << 26) + z2[2];
|
||||
z_51.v[2] = (z2[5] << 26) + z2[4];
|
||||
z_51.v[3] = (z2[7] << 26) + z2[6];
|
||||
z_51.v[4] = (z2[9] << 26) + z2[8];
|
||||
|
||||
x_51.v[0] = (x2[1] << 26) + x2[0];
|
||||
x_51.v[1] = (x2[3] << 26) + x2[2];
|
||||
x_51.v[2] = (x2[5] << 26) + x2[4];
|
||||
x_51.v[3] = (x2[7] << 26) + x2[6];
|
||||
x_51.v[4] = (x2[9] << 26) + x2[8];
|
||||
|
||||
fe51_invert(&z_51, &z_51);
|
||||
fe51_mul(&x_51, &x_51, &z_51);
|
||||
fe51_pack(q, &x_51);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct crypto_scalarmult_curve25519_implementation
|
||||
crypto_scalarmult_curve25519_sandy2x_implementation = {
|
||||
SODIUM_C99(.mult = ) crypto_scalarmult_curve25519_sandy2x,
|
||||
SODIUM_C99(.mult_base = ) crypto_scalarmult_curve25519_sandy2x_base
|
||||
};
|
||||
|
||||
#endif
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
#ifndef curve25519_sandy2x_H
|
||||
#define curve25519_sandy2x_H
|
||||
|
||||
#include "crypto_scalarmult_curve25519.h"
|
||||
|
||||
extern struct crypto_scalarmult_curve25519_implementation
|
||||
crypto_scalarmult_curve25519_sandy2x_implementation;
|
||||
|
||||
#endif
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
This file is adapted from ref10/fe.h:
|
||||
All the redundant functions are removed.
|
||||
*/
|
||||
|
||||
#ifndef fe_H
|
||||
#define fe_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef uint64_t fe[10];
|
||||
|
||||
/*
|
||||
fe means field element.
|
||||
Here the field is \Z/(2^255-19).
|
||||
An element t, entries t[0]...t[9], represents the integer
|
||||
t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
|
||||
Bounds on each t[i] vary depending on context.
|
||||
*/
|
||||
|
||||
#define fe_frombytes crypto_scalarmult_curve25519_sandy2x_fe_frombytes
|
||||
|
||||
extern void fe_frombytes(fe, const unsigned char *);
|
||||
|
||||
#endif
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
This file is adapted from amd64-51/fe25519.h:
|
||||
'fe25519' is renamed as 'fe51';
|
||||
All the redundant functions are removed;
|
||||
New function fe51_nsquare is introduced.
|
||||
*/
|
||||
|
||||
#ifndef fe51_H
|
||||
#define fe51_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fe51_namespace.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t v[5];
|
||||
}
|
||||
fe51;
|
||||
|
||||
extern void fe51_pack(unsigned char *, const fe51 *);
|
||||
extern void fe51_mul(fe51 *, const fe51 *, const fe51 *);
|
||||
extern void fe51_nsquare(fe51 *, const fe51 *, int);
|
||||
extern void fe51_invert(fe51 *, const fe51 *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
This file is adapted from amd64-51/fe25519_invert.c:
|
||||
Loops of squares are replaced by nsquares for better performance.
|
||||
*/
|
||||
|
||||
#include "fe51.h"
|
||||
|
||||
#ifdef HAVE_AVX_ASM
|
||||
|
||||
#define fe51_square(x, y) fe51_nsquare(x, y, 1)
|
||||
|
||||
void fe51_invert(fe51 *r, const fe51 *x)
|
||||
{
|
||||
fe51 z2;
|
||||
fe51 z9;
|
||||
fe51 z11;
|
||||
fe51 z2_5_0;
|
||||
fe51 z2_10_0;
|
||||
fe51 z2_20_0;
|
||||
fe51 z2_50_0;
|
||||
fe51 z2_100_0;
|
||||
fe51 t;
|
||||
|
||||
/* 2 */ fe51_square(&z2,x);
|
||||
/* 4 */ fe51_square(&t,&z2);
|
||||
/* 8 */ fe51_square(&t,&t);
|
||||
/* 9 */ fe51_mul(&z9,&t,x);
|
||||
/* 11 */ fe51_mul(&z11,&z9,&z2);
|
||||
/* 22 */ fe51_square(&t,&z11);
|
||||
/* 2^5 - 2^0 = 31 */ fe51_mul(&z2_5_0,&t,&z9);
|
||||
|
||||
/* 2^10 - 2^5 */ fe51_nsquare(&t,&z2_5_0, 5);
|
||||
/* 2^10 - 2^0 */ fe51_mul(&z2_10_0,&t,&z2_5_0);
|
||||
|
||||
/* 2^20 - 2^10 */ fe51_nsquare(&t,&z2_10_0, 10);
|
||||
/* 2^20 - 2^0 */ fe51_mul(&z2_20_0,&t,&z2_10_0);
|
||||
|
||||
/* 2^40 - 2^20 */ fe51_nsquare(&t,&z2_20_0, 20);
|
||||
/* 2^40 - 2^0 */ fe51_mul(&t,&t,&z2_20_0);
|
||||
|
||||
/* 2^50 - 2^10 */ fe51_nsquare(&t,&t,10);
|
||||
/* 2^50 - 2^0 */ fe51_mul(&z2_50_0,&t,&z2_10_0);
|
||||
|
||||
/* 2^100 - 2^50 */ fe51_nsquare(&t,&z2_50_0, 50);
|
||||
/* 2^100 - 2^0 */ fe51_mul(&z2_100_0,&t,&z2_50_0);
|
||||
|
||||
/* 2^200 - 2^100 */ fe51_nsquare(&t,&z2_100_0, 100);
|
||||
/* 2^200 - 2^0 */ fe51_mul(&t,&t,&z2_100_0);
|
||||
|
||||
/* 2^250 - 2^50 */ fe51_nsquare(&t,&t, 50);
|
||||
/* 2^250 - 2^0 */ fe51_mul(&t,&t,&z2_50_0);
|
||||
|
||||
/* 2^255 - 2^5 */ fe51_nsquare(&t,&t,5);
|
||||
/* 2^255 - 21 */ fe51_mul(r,&t,&z11);
|
||||
}
|
||||
|
||||
#endif
|
||||
Generated
+16
@@ -0,0 +1,16 @@
|
||||
#ifndef fe51_namespace_H
|
||||
#define fe51_namespace_H
|
||||
|
||||
#define fe51 crypto_scalarmult_curve25519_sandy2x_fe51
|
||||
#define _fe51 _crypto_scalarmult_curve25519_sandy2x_fe51
|
||||
#define fe51_pack crypto_scalarmult_curve25519_sandy2x_fe51_pack
|
||||
#define _fe51_pack _crypto_scalarmult_curve25519_sandy2x_fe51_pack
|
||||
#define fe51_mul crypto_scalarmult_curve25519_sandy2x_fe51_mul
|
||||
#define _fe51_mul _crypto_scalarmult_curve25519_sandy2x_fe51_mul
|
||||
#define fe51_nsquare crypto_scalarmult_curve25519_sandy2x_fe51_nsquare
|
||||
#define _fe51_nsquare _crypto_scalarmult_curve25519_sandy2x_fe51_nsquare
|
||||
|
||||
#define fe51_invert crypto_scalarmult_curve25519_sandy2x_fe51_invert
|
||||
|
||||
#endif /* ifndef fe51_namespace_H */
|
||||
|
||||
Loaded 100 of 452 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user