- Upgrade to 1.0

This commit is contained in:
giuseppenuc committed 2016-12-28 18:49:02 +01:00
1 parent 4e66c377fd
commit 0c2b3f1c25
452 files changed
+33888 -16806

No files matched your search

+18
View File
@@ -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.
*/
+46
View File
@@ -0,0 +1,46 @@
[![Build Status](https://travis-ci.org/jedisct1/libsodium.svg?branch=master)](https://travis-ci.org/jedisct1/libsodium?branch=master)
[![Windows build status](https://ci.appveyor.com/api/projects/status/fu8s2elx25il98hj?svg=true)](https://ci.appveyor.com/project/jedisct1/libsodium)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/2397/badge.svg)](https://scan.coverity.com/projects/2397)
![libsodium](https://raw.github.com/jedisct1/libsodium/master/logo.png)
============
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).
File diff suppressed because it is too large. Load diff
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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 },
},
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
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
}
@@ -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();
}
@@ -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);
}
@@ -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;
}
@@ -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
};
@@ -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 */
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
}
@@ -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
@@ -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
@@ -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;
}
@@ -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;
}
@@ -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_ */
@@ -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;
}
@@ -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);
}
@@ -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_ */
@@ -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;
}
@@ -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);
}
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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