18 Commits

Author SHA1 Message Date
ben
b654db4e41 Makefile improvement using LLM 2025-11-15 12:15:29 +01:00
ben
c37566ad85 Review markdown syntax. 2025-11-14 23:27:08 +01:00
ben
7d16fe4519 Update of the warning. 2025-11-14 23:20:22 +01:00
ben
cb4ba1cb3e Update externals with latest versions. 2025-11-14 23:04:39 +01:00
ben
5db7304983 Cleanup and improve Makefile 2025-11-14 23:04:39 +01:00
ben
1b56f81768 Fix linking option for release 2025-11-14 23:04:39 +01:00
ben
9cb9b2058d Fix identation 2025-11-14 23:04:39 +01:00
ben
7ecdc0bb91 Remove rand compilation message 2025-11-14 23:04:39 +01:00
ben
69f43babec Fix missing linking option 2025-11-14 23:04:39 +01:00
ben
1d85325bb3 Add algo version 2025-11-14 23:04:39 +01:00
ben
63c4842bce Update Copyright 2025-09-01 20:53:55 +02:00
ben
f138622b1d Add License file 2025-09-01 20:53:39 +02:00
Ben
e4a63422f2 Update date 2022-06-13 22:08:12 +02:00
Ben
85c0cb6cc2 Update argtable3 and fix warnings 2022-06-13 22:05:19 +02:00
Ben
ede16c77ae Fix typos 2021-08-29 23:37:12 +02:00
ben
e0f4163c7e [FIX] Windows and Mac OS X compatibility. 2019-05-28 17:08:37 +02:00
ben
c814f3c1c2 [FIX] Improve code security by prevent buffer overflow. 2019-05-28 15:19:37 +02:00
ben
1cad5dfaab [security] Fix buffer overflow. 2019-05-28 09:29:11 +02:00
15 changed files with 5338 additions and 5008 deletions

121
LICENSE Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

123
Makefile
View File

@@ -1,64 +1,77 @@
CC=gcc # Directories
CFLAGS=-Wall -Werror -pthread -O3 SRC_DIR := src
LDFLAGS= OBJ_DIR := objs
# Common flags
CFLAGS_COMMON := -Wall -Werror -pthread
CFLAGS_RELEASE := -O3 -g0
CFLAGS_DEBUG := -O0 -g
DEFINES := -DGETRANDOM -DARG_REPLACE_GETOPT=0
LDFLAGS_COMMON := -lm
LDFLAGS_RELEASE := -s
# Default build flags (can be overridden from the command line)
CFLAGS ?= $(CFLAGS_COMMON) $(CFLAGS_RELEASE) $(DEFINES)
LDFLAGS ?= $(LDFLAGS_COMMON) $(LDFLAGS_RELEASE)
# Source lists
LIB_SOURCES := \
argtable3.c \
base64.c \
binhex.c \
curve25519.c \
inexact.c \
norx_inexact.c \
sha3.c \
tests.c \
readpassphrase.c \
randombytes.c \
chacha20_drng.c \
blake2.c
ARGON2_SOURCES := \
argon2.c \
argon2-core.c \
argon2-thread.c \
argon2-encoding.c \
argon2-impl-select.c \
argon2-arch.c
MAIN_SOURCE := main.c
# Derived paths
LIB_SRCS := $(addprefix $(SRC_DIR)/,$(LIB_SOURCES))
LIB_OBJS := $(addprefix $(OBJ_DIR)/,$(LIB_SOURCES:.c=.o))
ARGON2_SRCS := $(addprefix $(SRC_DIR)/,$(ARGON2_SOURCES))
MAIN_SRC := $(addprefix $(SRC_DIR)/,$(MAIN_SOURCE))
# Phony targets
.PHONY: all default release debug clean
# Default target
all: inexact
default: inexact default: inexact
release: inexact
windows: CC=x86_64-w64-mingw32-gcc # Debug build: override flags for this target only
windows: CFLAGS=-Wall -Werror -pthread -O3 debug: CFLAGS := $(CFLAGS_COMMON) $(CFLAGS_DEBUG) $(DEFINES)
windows: LDFLAGS= debug: LDFLAGS := $(LDFLAGS_COMMON)
windows: inexact
windows-debug: CC=x86_64-w64-mingw32-gcc
windows-debug: CFLAGS=-Wall -Werror -pthread -O3 -g
windows-debug: LDFLAGS=
windows-debug: inexact
debug: CFLAGS=-Wall -Werror -pthread -O3 -g
debug: LDFLAGS=
debug: inexact debug: inexact
argtable3.o: src/argtable3.c # Link final binary
mkdir -p objs inexact: $(LIB_OBJS) $(ARGON2_SRCS) $(MAIN_SRC)
$(CC) $(CFLAGS) -c src/argtable3.c -o objs/argtable3.o $(CC) $(CFLAGS) $(ARGON2_SRCS) $(MAIN_SRC) $(LIB_OBJS) -o $@ $(LDFLAGS)
base64.o: src/base64.c # Ensure object directory exists
$(CC) $(CFLAGS) -c src/base64.c -o objs/base64.o $(OBJ_DIR):
mkdir -p $(OBJ_DIR)
binhex.o: src/binhex.c # Generic rule to build objects from src/*.c into objs/*.o
$(CC) $(CFLAGS) -c src/binhex.c -o objs/binhex.o $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $@
curve25519.o: src/curve25519.c
$(CC) $(CFLAGS) -c src/curve25519.c -o objs/curve25519.o
inexact.o: src/inexact.c
$(CC) $(CFLAGS) -c src/inexact.c -o objs/inexact.o
norx_inexact.o: src/norx_inexact.c
$(CC) $(CFLAGS) -c src/norx_inexact.c -o objs/norx_inexact.o
sha3.o: src/sha3.c
$(CC) $(CFLAGS) -c src/sha3.c -o objs/sha3.o
tests.o: src/tests.c
$(CC) $(CFLAGS) -c src/tests.c -o objs/tests.o
readpassphrase.o: src/readpassphrase.c
$(CC) $(CFLAGS) -c src/readpassphrase.c -o objs/readpassphrase.o
randombytes.o: src/randombytes.c
$(CC) $(CFLAGS) -c src/randombytes.c -o objs/randombytes.o
chacha20_drng.o: src/chacha20_drng.c
$(CC) $(CFLAGS) -c src/chacha20_drng.c -o objs/chacha20_drng.o
blake2.o: src/blake2.c
$(CC) $(CFLAGS) -c src/blake2.c -o objs/blake2.o
inexact: src/main.c argtable3.o base64.o binhex.o curve25519.o inexact.o norx_inexact.o sha3.o tests.o readpassphrase.o chacha20_drng.o randombytes.o blake2.o
$(CC) $(CFLAGS) src/argon2.c src/argon2-core.c src/argon2-thread.c src/argon2-encoding.c src/argon2-impl-select.c src/argon2-arch.c src/main.c objs/argtable3.o objs/base64.o objs/binhex.o objs/curve25519.o objs/inexact.o objs/norx_inexact.o objs/sha3.o objs/tests.o objs/readpassphrase.o objs/randombytes.o objs/chacha20_drng.o objs/blake2.o -o inexact $(LDFLAGS)
# Cleanup
clean: clean:
-rm objs/*.o -$(RM) $(LIB_OBJS)
-rm -f inexact inexact.exe -$(RM) inexact inexact.exe

View File

@@ -1,9 +1,9 @@
# INadvisable EXperimental Asymmetric Crypto Tool # # INadvisable EXperimental Asymmetric Crypto Tool #
Inexact is an experimental cryptographic tools, multi-platform, scriptable Inexact is an experimental cryptographic tool, multi-platform, scriptable
complying with the KISS principle (Keep it simple and stupid). complying with the KISS principle (Keep It Simple and Stupid).
The main features are as follow: The main features are as follows:
- Asymmetric encryption. - Asymmetric encryption.
- Symmetric encryption. - Symmetric encryption.
@@ -13,15 +13,15 @@ The main features are as follow:
- Base64 or modified base64 encoding output compatible with a URL path, DNS entry, or file name. - Base64 or modified base64 encoding output compatible with a URL path, DNS entry, or file name.
** WARNING : Inexact uses recent algorithms not approved nor by NIST or NSA ! ** **WARNING : Inexact uses experimental algorithms that are not certified.**
** Don't use for anything other than experiments. ** **Don't use this to secure sensitive things.**
## Encryption principles ## Encryption principles
Inexact implements the following algorithms: Inexact implements the following algorithms:
- Norx 256bits - Norx 3.0 256bits
- Diffie-Hellman X25219 - Diffie-Hellman X25219
- SHA3-256 - SHA3-256
- DRNG chacha20 - DRNG chacha20
@@ -43,7 +43,7 @@ Rest of protocol:
- The nonce for the Norx function of the second part is a SHA3-256 hash of - The nonce for the Norx function of the second part is a SHA3-256 hash of
parameters of the first part and rand1 buffer. parameters of the first part and rand1 buffer.
- Argon2 is used as a challenge for the password of the private key. - Argon2 is used as a challenge for the password of the private key.
- The symmetric encryption is based on ian asymmetric encryption by adding argon2 - The symmetric encryption is based on the asymmetric encryption by adding argon2
challenge nonce and public key in the encrypted message. challenge nonce and public key in the encrypted message.
Schematic: Schematic:
@@ -62,20 +62,13 @@ Schematic:
## How to build ## How to build
For GNU/Linux and Mac OS X: For GNU/Linux and macOS, you must have GCC or Clang installed. For Windows, w64-mingw32-gcc is required.
``` ```
cd inexact cd inexact
make make
``` ```
For Microsoft Windows using cross compilation on GNU/Linux:
```
cd inexact
make windows
```
## Usage ## Usage
Asymmetric encryption: Asymmetric encryption:
@@ -126,7 +119,7 @@ Variable encrypted message size (400 chars):
## Credits ## Credits
Copyright © 2019 <ben@hackade.org> Copyright © 2019-2025 <ben@hackade.org>
Inexact is released under CC0 licence, except for this externals libraries: Inexact is released under CC0 licence, except for this externals libraries:
@@ -139,4 +132,3 @@ Inexact is released under CC0 licence, except for this externals libraries:
- https://nachtimwald.com/2017/09/24/hex-encode-and-decode-in-c/ - https://nachtimwald.com/2017/09/24/hex-encode-and-decode-in-c/
- https://github.com/argtable/argtable3 - https://github.com/argtable/argtable3
- https://github.com/dsprenkels/randombytes - https://github.com/dsprenkels/randombytes

View File

@@ -26,6 +26,8 @@
#define CONST_CAST(x) (x)(uintptr_t) #define CONST_CAST(x) (x)(uintptr_t)
#define rotr64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
/**********************Argon2 internal constants*******************************/ /**********************Argon2 internal constants*******************************/
enum argon2_core_constants { enum argon2_core_constants {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

257
src/argtable3_private.h Normal file
View File

@@ -0,0 +1,257 @@
/*******************************************************************************
* argtable3_private: Declares private types, constants, and interfaces
*
* This file is part of the argtable3 library.
*
* Copyright (C) 2013-2019 Tom G. Huang
* <tomghuang@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of STEWART HEITMANN nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 STEWART HEITMANN 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 ARG_UTILS_H
#define ARG_UTILS_H
#include <stdlib.h>
#ifndef ARG_ENABLE_TRACE
#define ARG_ENABLE_TRACE 0
#endif /* ARG_ENABLE_TRACE */
#ifndef ARG_ENABLE_LOG
#define ARG_ENABLE_LOG 1
#endif /* ARG_ENABLE_LOG */
/* Use the embedded getopt as the system getopt(3) */
#ifndef ARG_REPLACE_GETOPT
#define ARG_REPLACE_GETOPT 1
#endif /* ARG_REPLACE_GETOPT */
/* Size of the buffer pre-allocated for dynamic strings.
* If the length exceeds this size, the buffer will be dynamically allocated.
*/
#ifndef ARG_DSTR_SIZE
#define ARG_DSTR_SIZE 200
#endif /* ARG_DSTR_SIZE */
#ifdef __cplusplus
extern "C" {
#endif
enum { ARG_ERR_MINCOUNT = 1, ARG_ERR_MAXCOUNT, ARG_ERR_BADINT, ARG_ERR_OVERFLOW, ARG_ERR_BADDOUBLE, ARG_ERR_BADDATE, ARG_ERR_REGNOMATCH };
typedef void(arg_panicfn)(const char* fmt, ...);
#if defined(_MSC_VER)
#define ARG_TRACE(x) \
__pragma(warning(push)) __pragma(warning(disable : 4127)) do { \
if (ARG_ENABLE_TRACE) \
dbg_printf x; \
} \
while (0) \
__pragma(warning(pop))
#define ARG_LOG(x) \
__pragma(warning(push)) __pragma(warning(disable : 4127)) do { \
if (ARG_ENABLE_LOG) \
dbg_printf x; \
} \
while (0) \
__pragma(warning(pop))
#else
#define ARG_TRACE(x) \
do { \
if (ARG_ENABLE_TRACE) \
dbg_printf x; \
} while (0)
#define ARG_LOG(x) \
do { \
if (ARG_ENABLE_LOG) \
dbg_printf x; \
} while (0)
#endif
/*
* Rename a few generic names to unique names.
* They can be a problem for the platforms like NuttX, where
* the namespace is flat for everything including apps and libraries.
*/
#define xmalloc malloc
#define xcalloc calloc
#define xrealloc realloc
#define xfree free
extern void dbg_printf(const char* fmt, ...);
extern void arg_set_panic(arg_panicfn* proc);
extern void* xmalloc(size_t size);
extern void* xcalloc(size_t count, size_t size);
extern void* xrealloc(void* ptr, size_t size);
extern void xfree(void* ptr);
struct arg_hashtable_entry {
void *k, *v;
unsigned int h;
struct arg_hashtable_entry* next;
};
typedef struct arg_hashtable {
unsigned int tablelength;
struct arg_hashtable_entry** table;
unsigned int entrycount;
unsigned int loadlimit;
unsigned int primeindex;
unsigned int (*hashfn)(const void* k);
int (*eqfn)(const void* k1, const void* k2);
} arg_hashtable_t;
/**
* @brief Create a hash table.
*
* @param minsize minimum initial size of hash table
* @param hashfn function for hashing keys
* @param eqfn function for determining key equality
* @return newly created hash table or NULL on failure
*/
arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*));
/**
* @brief This function will cause the table to expand if the insertion would take
* the ratio of entries to table size over the maximum load factor.
*
* This function does not check for repeated insertions with a duplicate key.
* The value returned when using a duplicate key is undefined -- when
* the hash table changes size, the order of retrieval of duplicate key
* entries is reversed.
* If in doubt, remove before insert.
*
* @param h the hash table to insert into
* @param k the key - hash table claims ownership and will free on removal
* @param v the value - does not claim ownership
* @return non-zero for successful insertion
*/
void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v);
#define ARG_DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
int fnname(arg_hashtable_t* h, keytype* k, valuetype* v) { return arg_hashtable_insert(h, k, v); }
/**
* @brief Search the specified key in the hash table.
*
* @param h the hash table to search
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
void* arg_hashtable_search(arg_hashtable_t* h, const void* k);
#define ARG_DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_search(h, k)); }
/**
* @brief Remove the specified key from the hash table.
*
* @param h the hash table to remove the item from
* @param k the key to search for - does not claim ownership
*/
void arg_hashtable_remove(arg_hashtable_t* h, const void* k);
#define ARG_DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
void fnname(arg_hashtable_t* h, keytype* k) { arg_hashtable_remove(h, k); }
/**
* @brief Return the number of keys in the hash table.
*
* @param h the hash table
* @return the number of items stored in the hash table
*/
unsigned int arg_hashtable_count(arg_hashtable_t* h);
/**
* @brief Change the value associated with the key.
*
* function to change the value associated with a key, where there already
* exists a value bound to the key in the hash table.
* Source due to Holger Schemel.
*
* @name hashtable_change
* @param h the hash table
* @param key
* @param value
*/
int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v);
/**
* @brief Free the hash table and the memory allocated for each key-value pair.
*
* @param h the hash table
* @param free_values whether to call 'free' on the remaining values
*/
void arg_hashtable_destroy(arg_hashtable_t* h, int free_values);
typedef struct arg_hashtable_itr {
arg_hashtable_t* h;
struct arg_hashtable_entry* e;
struct arg_hashtable_entry* parent;
unsigned int index;
} arg_hashtable_itr_t;
arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h);
void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr);
/**
* @brief Return the value of the (key,value) pair at the current position.
*/
extern void* arg_hashtable_itr_key(arg_hashtable_itr_t* i);
/**
* @brief Return the value of the (key,value) pair at the current position.
*/
extern void* arg_hashtable_itr_value(arg_hashtable_itr_t* i);
/**
* @brief Advance the iterator to the next element. Returns zero if advanced to end of table.
*/
int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr);
/**
* @brief Remove current element and advance the iterator to the next element.
*/
int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr);
/**
* @brief Search and overwrite the supplied iterator, to point to the entry matching the supplied key.
*
* @return Zero if not found.
*/
int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k);
#define ARG_DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
int fnname(arg_hashtable_itr_t* i, arg_hashtable_t* h, keytype* k) { return (arg_hashtable_iterator_search(i, h, k)); }
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -177,6 +177,7 @@ unsigned char * b64t_encode(const unsigned char *src, size_t len,
new_index ++; new_index ++;
} }
} }
if(new_index)
out[new_index] = 0; out[new_index] = 0;
*out_len = new_index; *out_len = new_index;

View File

@@ -17,22 +17,17 @@
* DAMAGE. * DAMAGE.
*/ */
#define _GNU_SOURCE
#include <unistd.h> #include <unistd.h>
#include <sys/syscall.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h> #include <sys/mman.h>
#endif
#include "chacha20_drng.h" #include "chacha20_drng.h"
#include "randombytes.h"
#define MAJVERSION 1 /* API / ABI incompatible changes, #define MAJVERSION 1 /* API / ABI incompatible changes,
* functional changes that require consumer * functional changes that require consumer
@@ -58,9 +53,7 @@
/*********************************** Helper ***********************************/ /*********************************** Helper ***********************************/
#ifndef _WIN32
#define min(x, y) ((x < y) ? x : y) #define min(x, y) ((x < y) ? x : y)
#endif
#define __aligned(x) __attribute__((aligned(x))) #define __aligned(x) __attribute__((aligned(x)))
static inline void memset_secure(void *s, int c, uint32_t n) static inline void memset_secure(void *s, int c, uint32_t n)
@@ -71,23 +64,14 @@ static inline void memset_secure(void *s, int c, uint32_t n)
static inline void get_time(time_t *sec, uint32_t *nsec) static inline void get_time(time_t *sec, uint32_t *nsec)
{ {
#ifdef _WIN32
SYSTEMTIME SystemTime;
GetSystemTime(&SystemTime);
if(sec)
*sec = SystemTime.wSecond;
if(nsec)
*nsec = SystemTime.wMilliseconds;
#else
struct timespec time; struct timespec time;
if (clock_gettime(CLOCK_REALTIME, &time) == 0) { if (clock_gettime(CLOCK_REALTIME, &time) == 0) {
if (sec) if (sec)
*sec = time.tv_sec; *sec = time.tv_sec;
if (nsec) if (nsec)
*nsec = time.tv_nsec; *nsec = time.tv_nsec;
} }
#endif
} }
static inline uint32_t rol32(uint32_t x, int n) static inline uint32_t rol32(uint32_t x, int n)
@@ -95,25 +79,36 @@ static inline uint32_t rol32(uint32_t x, int n)
return ( (x << (n&(32-1))) | (x >> ((32-n)&(32-1))) ); return ( (x << (n&(32-1))) | (x >> ((32-n)&(32-1))) );
} }
/* Endian dependent byte swap operations. */ /* Endian dependent byte swap operations. */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* Byte swap for 32-bit and 64-bit integers. */ # define le_bswap32(x) _bswap32(x)
static inline uint32_t ror32(uint32_t x, int n) static inline uint32_t ror32(uint32_t x, int n)
{ {
return ( (x >> (n&(32-1))) | (x << ((32-n)&(32-1))) ); return ( (x >> (n&(32-1))) | (x << ((32-n)&(32-1))) );
} }
/* Byte swap for 32-bit and 64-bit integers. */
static inline uint32_t _bswap32(uint32_t x) static inline uint32_t _bswap32(uint32_t x)
{ {
return ((rol32(x, 8) & 0x00ff00ffL) | (ror32(x, 8) & 0xff00ff00L)); return ((rol32(x, 8) & 0x00ff00ffL) | (ror32(x, 8) & 0xff00ff00L));
} }
# define le_bswap32(x) _bswap32(x)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define le_bswap32(x) ((uint32_t)(x)) # define le_bswap32(x) ((uint32_t)(x))
#else #else
#error "Endianess not defined" #error "Endianess not defined"
#endif #endif
static inline void drng_chacha20_bswap32(uint32_t *ptr, uint32_t words)
{
uint32_t i;
/* Byte-swap data which is an LE representation */
for (i = 0; i < words; i++) {
*ptr = le_bswap32(*ptr);
ptr++;
}
}
/******************************* ChaCha20 Block *******************************/ /******************************* ChaCha20 Block *******************************/
#define CHACHA20_KEY_SIZE 32 #define CHACHA20_KEY_SIZE 32
@@ -203,6 +198,7 @@ static inline int drng_chacha20_selftest_one(struct chacha20_state *state,
uint32_t result[CHACHA20_BLOCK_SIZE_WORDS]; uint32_t result[CHACHA20_BLOCK_SIZE_WORDS];
chacha20_block(&state->constants[0], result); chacha20_block(&state->constants[0], result);
return memcmp(expected, result, CHACHA20_BLOCK_SIZE); return memcmp(expected, result, CHACHA20_BLOCK_SIZE);
} }
@@ -230,24 +226,186 @@ static int drng_chacha20_selftest(void)
expected[12] = 0xd19c12b5; expected[13] = 0xb94e16de; expected[12] = 0xd19c12b5; expected[13] = 0xb94e16de;
expected[14] = 0xe883d0cb; expected[15] = 0x4e3c50a2; expected[14] = 0xe883d0cb; expected[15] = 0x4e3c50a2;
drng_chacha20_bswap32(expected, CHACHA20_BLOCK_SIZE_WORDS);
return drng_chacha20_selftest_one(&chacha20, &expected[0]); return drng_chacha20_selftest_one(&chacha20, &expected[0]);
} }
/********************* getrandom system call seed source *********************/
#ifdef GETRANDOM
#include <limits.h>
static int drng_getrandom_get(uint8_t *buf, uint32_t buflen)
{
uint32_t len = 0;
ssize_t ret;
if (buflen > INT_MAX)
return 0;
do {
ret = syscall(__NR_getrandom, (buf + len), (buflen - len), 0);
if (0 < ret)
len += ret;
} while ((0 < ret || EINTR == errno || ERESTART == errno)
&& buflen > len);
return len;
}
#else
static int drng_getrandom_get(uint8_t *buf, uint32_t buflen)
{
(void)buf;
(void)buflen;
return 0;
}
#endif
/*************************** Jitter RNG seed source ***************************/
#ifdef JENT
#include "jitterentropy.h"
struct jent_noise_source {
struct rand_data *ec;
int initialized;
};
static struct jent_noise_source jent_noise_source = {
NULL,
0,
};
static int drng_jent_alloc()
{
int ret = jent_entropy_init();
if (ret) {
jent_noise_source.initialized = -1;
return -EFAULT;
}
jent_noise_source.ec = jent_entropy_collector_alloc(0, 0);
if (!jent_noise_source.ec)
return -ENOMEM;
return 0;
}
static void drng_jent_dealloc(void)
{
if (jent_noise_source.initialized != 1)
return;
jent_entropy_collector_free(jent_noise_source.ec);
jent_noise_source.ec = NULL;
jent_noise_source.initialized = 0;
}
static int drng_jent_get(uint8_t *buf, uint32_t buflen)
{
if (!jent_noise_source.initialized) {
int ret = drng_jent_alloc();
if (ret)
return ret;
jent_noise_source.initialized = 1;
}
if (jent_noise_source.initialized > 0)
return jent_read_entropy(jent_noise_source.ec,
(char *)buf, buflen);
return 0;
}
#else
static int drng_jent_get(uint8_t *buf, uint32_t buflen)
{
(void)buf;
(void)buflen;
return 0;
}
static void drng_jent_dealloc(void)
{
return;
}
#endif
/************************** /dev/random seed source **************************/
#ifdef DEVRANDOM
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
static int random_fd = -1;
static int drng_random_alloc(void)
{
random_fd = open("/dev/random", O_RDONLY|O_CLOEXEC);
if (0 > random_fd)
return -EBADFD;
return 0;
}
static int drng_random_get(uint8_t *buf, uint32_t buflen) static int drng_random_get(uint8_t *buf, uint32_t buflen)
{ {
int ret = randombytes(buf, buflen); uint32_t len = 0;
if( ret != 0) { ssize_t ret;
if (random_fd == -1) {
int ret = drng_random_alloc();
if (ret)
return ret;
}
if (buflen > INT_MAX)
return 0; return 0;
} else {
return buflen; do {
ret = read(random_fd, (buf + len), (buflen - len));
if (0 < ret)
len += ret;
} while ((0 < ret || EINTR == errno || ERESTART == errno)
&& buflen > len);
return len;
} }
static void drng_random_dealloc(void)
{
if (random_fd < 0)
return;
close(random_fd);
random_fd = -1;
} }
#else
static int drng_random_get(uint8_t *buf, uint32_t buflen)
{
(void)buf;
(void)buflen;
return 0;
}
static void drng_random_dealloc(void)
{
return;
}
#endif
/******************************* ChaCha20 DRNG *******************************/ /******************************* ChaCha20 DRNG *******************************/
struct chacha20_drng { struct chacha20_drng {
@@ -267,22 +425,23 @@ static inline void drng_chacha20_update(struct chacha20_state *chacha20,
{ {
uint32_t i, tmp[CHACHA20_BLOCK_SIZE_WORDS]; uint32_t i, tmp[CHACHA20_BLOCK_SIZE_WORDS];
if (used_words > CHACHA20_KEY_SIZE_WORDS) { if (CHACHA20_BLOCK_SIZE_WORDS - used_words < CHACHA20_KEY_SIZE_WORDS) {
chacha20_block(&chacha20->constants[0], tmp); chacha20_block(&chacha20->constants[0], tmp);
for (i = 0; i < CHACHA20_KEY_SIZE_WORDS; i++) for (i = 0; i < CHACHA20_KEY_SIZE_WORDS; i++)
chacha20->key.u[i] ^= tmp[i]; chacha20->key.u[i] ^= le_bswap32(tmp[i]);
memset_secure(tmp, 0, sizeof(tmp)); memset_secure(tmp, 0, sizeof(tmp));
} else { } else {
for (i = 0; i < CHACHA20_KEY_SIZE_WORDS; i++) for (i = 0; i < CHACHA20_KEY_SIZE_WORDS; i++)
chacha20->key.u[i] ^= buf[i + used_words]; chacha20->key.u[i] ^= le_bswap32(buf[i + used_words]);
} }
/* Deterministic increment of nonce as required in RFC 7539 chapter 4 */ /* Deterministic increment of nonce as required in RFC 7539 chapter 4 */
chacha20->nonce[0]++; chacha20->nonce[0]++;
if (chacha20->nonce[0] == 0) if (chacha20->nonce[0] == 0){
chacha20->nonce[1]++; chacha20->nonce[1]++;
if (chacha20->nonce[1] == 0) if (chacha20->nonce[1] == 0)
chacha20->nonce[2]++; chacha20->nonce[2]++;
}
/* Leave counter untouched as it is start value is undefined in RFC */ /* Leave counter untouched as it is start value is undefined in RFC */
} }
@@ -338,7 +497,7 @@ static int drng_chacha20_generate(struct chacha20_state *chacha20,
int zeroize_buf = 0; int zeroize_buf = 0;
while (outbuflen >= CHACHA20_BLOCK_SIZE) { while (outbuflen >= CHACHA20_BLOCK_SIZE) {
if ((uintptr_t)outbuf & (sizeof(aligned_buf[0]) - 1)) { if ((unsigned long)outbuf & (sizeof(aligned_buf[0]) - 1)) {
chacha20_block(&chacha20->constants[0], aligned_buf); chacha20_block(&chacha20->constants[0], aligned_buf);
memcpy(outbuf, aligned_buf, CHACHA20_BLOCK_SIZE); memcpy(outbuf, aligned_buf, CHACHA20_BLOCK_SIZE);
zeroize_buf = 1; zeroize_buf = 1;
@@ -388,7 +547,7 @@ static int drng_chacha20_rng_selftest(struct chacha20_drng *drng)
* * remaining state is 0 * * remaining state is 0
* and pulling one ChaCha20 DRNG block. * and pulling one ChaCha20 DRNG block.
*/ */
uint8_t expected_block[CHACHA20_KEY_SIZE] = { static const uint8_t expected_block[CHACHA20_KEY_SIZE] = {
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
@@ -409,15 +568,15 @@ static int drng_chacha20_rng_selftest(struct chacha20_drng *drng)
* 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f * 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
* and pulling two ChaCha20 DRNG blocks. * and pulling two ChaCha20 DRNG blocks.
*/ */
uint8_t expected_twoblocks[CHACHA20_KEY_SIZE * 2] = { static const uint8_t expected_twoblocks[CHACHA20_KEY_SIZE * 2] = {
0xf5, 0xb4, 0xb6, 0x5a, 0xec, 0xcd, 0x5a, 0x65, 0xe3, 0xb0, 0x8a, 0xcc, 0x34, 0xc3, 0x17, 0x0e,
0x87, 0x56, 0xe3, 0x86, 0x51, 0x54, 0xfc, 0x90, 0xc3, 0xd8, 0xc3, 0x40, 0xe7, 0x73, 0xe9, 0x0d,
0x56, 0xff, 0x5e, 0xae, 0x58, 0xf2, 0x01, 0x88, 0xd1, 0x62, 0xa3, 0x5d, 0x7d, 0xf2, 0xf1, 0x4a,
0xb1, 0x7e, 0xb8, 0x2e, 0x17, 0x9a, 0x27, 0xe6, 0x24, 0x42, 0xb7, 0x1e, 0xb0, 0x05, 0x17, 0x07,
0x86, 0xb3, 0xed, 0x33, 0xf7, 0xb9, 0x06, 0x05, 0xb9, 0x35, 0x10, 0x69, 0x8b, 0x46, 0xfb, 0x51,
0x8a, 0x2d, 0x1a, 0x93, 0xc9, 0x0b, 0x80, 0x04, 0xe9, 0x91, 0x3f, 0x46, 0xf2, 0x4d, 0xea, 0xd0,
0x03, 0xaa, 0x60, 0xaf, 0xd5, 0x36, 0x40, 0x11, 0x81, 0xc1, 0x1b, 0xa9, 0x5d, 0x52, 0x91, 0x5f,
0x67, 0x89, 0xb1, 0x66, 0xd5, 0x88, 0x62, 0x6d }; 0xcd, 0xdc, 0xc6, 0xd6, 0xc3, 0x7c, 0x50, 0x23 };
/* /*
* Expected result when ChaCha20 DRNG state is zero: * Expected result when ChaCha20 DRNG state is zero:
@@ -429,18 +588,22 @@ static int drng_chacha20_rng_selftest(struct chacha20_drng *drng)
* 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, * 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
* 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, * 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
* 0x20 * 0x20
* and pulling one ChaCha20 DRNG block plus one byte. * and pulling one ChaCha20 DRNG block plus four byte.
*/ */
uint8_t expected_block_and_byte[CHACHA20_KEY_SIZE + 1] = { static const uint8_t expected_block_nonaligned[CHACHA20_KEY_SIZE + 4] = {
0x3d, 0x13, 0x47, 0x1e, 0x7f, 0x7c, 0x99, 0x33, 0x9c, 0xfc, 0x5e, 0x31, 0x21, 0x62, 0x11, 0x85,
0xfc, 0x44, 0xa4, 0xdd, 0xf9, 0x3d, 0xe1, 0x9a, 0xd3, 0x77, 0xd3, 0x69, 0x0f, 0xa8, 0x16, 0x55,
0xd4, 0xe8, 0x7a, 0x7d, 0x42, 0xac, 0xd1, 0xcd, 0xb4, 0x4c, 0xf6, 0x52, 0xf3, 0xa8, 0x37, 0x99,
0x10, 0x69, 0xe7, 0xbf, 0xd4, 0xfd, 0x69, 0x4b, 0x38, 0x76, 0xa0, 0x66, 0xec, 0xbb, 0xce, 0xa9,
0xa7 }; 0x9c, 0x95, 0xa1, 0xfd };
drng_chacha20_bswap32((uint32_t *)seed,
sizeof(seed) / sizeof(uint32_t));
/* Generate with zero state */ /* Generate with zero state */
ret = drng_chacha20_generate(&drng->chacha20, outbuf, ret = drng_chacha20_generate(&drng->chacha20, outbuf,
sizeof(expected_block)); sizeof(expected_block));
if (ret) if (ret)
return ret; return ret;
if (memcmp(outbuf, expected_block, sizeof(expected_block))) if (memcmp(outbuf, expected_block, sizeof(expected_block)))
@@ -454,6 +617,7 @@ static int drng_chacha20_rng_selftest(struct chacha20_drng *drng)
sizeof(expected_twoblocks)); sizeof(expected_twoblocks));
if (ret) if (ret)
return ret; return ret;
ret = drng_chacha20_generate(&drng->chacha20, outbuf, ret = drng_chacha20_generate(&drng->chacha20, outbuf,
sizeof(expected_twoblocks)); sizeof(expected_twoblocks));
if (ret) if (ret)
@@ -466,15 +630,15 @@ static int drng_chacha20_rng_selftest(struct chacha20_drng *drng)
/* Reseed with 1 block and one byte */ /* Reseed with 1 block and one byte */
ret = drng_chacha20_seed(&drng->chacha20, seed, ret = drng_chacha20_seed(&drng->chacha20, seed,
sizeof(expected_block_and_byte)); sizeof(expected_block_nonaligned));
if (ret) if (ret)
return ret; return ret;
ret = drng_chacha20_generate(&drng->chacha20, outbuf, ret = drng_chacha20_generate(&drng->chacha20, outbuf,
sizeof(expected_block_and_byte)); sizeof(expected_block_nonaligned));
if (ret) if (ret)
return ret; return ret;
if (memcmp(outbuf, expected_block_and_byte, if (memcmp(outbuf, expected_block_nonaligned,
sizeof(expected_block_and_byte))) sizeof(expected_block_nonaligned)))
return -EFAULT; return -EFAULT;
return 0; return 0;
@@ -483,11 +647,7 @@ static int drng_chacha20_rng_selftest(struct chacha20_drng *drng)
static void drng_chacha20_dealloc(struct chacha20_drng *drng) static void drng_chacha20_dealloc(struct chacha20_drng *drng)
{ {
memset_secure(drng, 0, sizeof(*drng)); memset_secure(drng, 0, sizeof(*drng));
#ifdef _WIN32
_aligned_free(drng);
#else
free(drng); free(drng);
#endif
} }
/** /**
@@ -503,31 +663,26 @@ static int drng_chacha20_alloc(struct chacha20_drng **out)
return -EFAULT; return -EFAULT;
} }
#ifdef _WIN32 ret = posix_memalign((void *)&drng, CHACHA20_DRNG_ALIGNMENT,
drng = _aligned_malloc(sizeof(*drng), CHACHA20_DRNG_ALIGNMENT); sizeof(*drng));
#endif if (ret) {
return -ret;
#ifndef aligned_alloc
drng = malloc(sizeof(*drng));
#else
drng = aligned_alloc(CHACHA20_DRNG_ALIGNMENT, sizeof(*drng));
#endif
if (drng == NULL) {
return -1;
} }
#ifndef _WIN32
/* prevent paging out of the memory state to swap space */ /* prevent paging out of the memory state to swap space */
ret = mlock(drng, sizeof(*drng)); ret = mlock(drng, sizeof(*drng));
if (ret && errno != EPERM && errno != EAGAIN) { if (ret && errno != EPERM && errno != EAGAIN) {
ret = -errno; ret = -errno;
goto err; goto err;
} }
#endif
memset(drng, 0, sizeof(*drng)); memset(drng, 0, sizeof(*drng));
memcpy(&drng->chacha20.constants[0], "expand 32-byte k", 16); /* String "expand 32-byte k" */
drng->chacha20.constants[0] = 0x61707865;
drng->chacha20.constants[1] = 0x3320646e;
drng->chacha20.constants[2] = 0x79622d32;
drng->chacha20.constants[3] = 0x6b206574;
ret = drng_chacha20_rng_selftest(drng); ret = drng_chacha20_rng_selftest(drng);
if (ret) if (ret)
@@ -563,6 +718,33 @@ int drng_chacha20_reseed(struct chacha20_drng *drng, const uint8_t *inbuf,
int ret; int ret;
uint32_t collected = 0; uint32_t collected = 0;
/* Entropy assumption: 1 data bit delivers one bit of entropy */
ret = drng_getrandom_get(seed, CHACHA20_KEY_SIZE);
if (ret < 0)
return ret;
if (ret) {
collected = ret;
ret = drng_chacha20_seed(&drng->chacha20, seed,
CHACHA20_KEY_SIZE);
if (ret)
return ret;
}
/* Entropy assumption: 2 data bits deliver one bit of entropy */
ret = drng_jent_get(seed, sizeof(seed));
if (ret < 0)
return ret;
if (ret) {
collected += ret;
ret = drng_chacha20_seed(&drng->chacha20, seed, sizeof(seed));
if (ret)
return ret;
}
/* Entropy assumption: 1 data bit delivers one bit of entropy */ /* Entropy assumption: 1 data bit delivers one bit of entropy */
ret = drng_random_get(seed, CHACHA20_KEY_SIZE); ret = drng_random_get(seed, CHACHA20_KEY_SIZE);
if (ret < 0) if (ret < 0)
@@ -595,6 +777,8 @@ int drng_chacha20_reseed(struct chacha20_drng *drng, const uint8_t *inbuf,
DSO_PUBLIC DSO_PUBLIC
void drng_chacha20_destroy(struct chacha20_drng *drng) void drng_chacha20_destroy(struct chacha20_drng *drng)
{ {
drng_jent_dealloc();
drng_random_dealloc();
drng_chacha20_dealloc(drng); drng_chacha20_dealloc(drng);
} }

View File

@@ -6,8 +6,9 @@
* and related and neighboring rights to this software to the public domain * and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty. * worldwide. This software is distributed without any warranty.
* *
* You should have received a copy of the CC0 Public Domain Dedication along with * You should have received a copy of the CC0 Public Domain Dedication along
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. * with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/ */
#include "inexact.h" #include "inexact.h"
@@ -37,12 +38,15 @@ int generate_keys(const char *seckey_filename, const char *pubkey_filename,
unsigned char *publickey_b64 = NULL; unsigned char *publickey_b64 = NULL;
unsigned char *privatekey_b64t = NULL; unsigned char *privatekey_b64t = NULL;
unsigned char *publickey_b64t = NULL; unsigned char *publickey_b64t = NULL;
unsigned char salt[32] = {0}; unsigned char *salt = NULL;
unsigned char privatekey_buffer[64] = {0}; const size_t salt_len = 32;
unsigned char *privatekey_buffer = NULL;
const size_t privatekey_buffer_len = 64;
char password[256] = {0}; char *password = NULL;
const size_t password_maxlen = 256;
char *password_out = NULL; char *password_out = NULL;
char password_verif[256] = {0}; char *password_verif = NULL;
char *password_verif_out = NULL; char *password_verif_out = NULL;
size_t password_len = 0; size_t password_len = 0;
size_t password_verif_len = 0; size_t password_verif_len = 0;
@@ -66,6 +70,17 @@ int generate_keys(const char *seckey_filename, const char *pubkey_filename,
curve25519_key privatekey; curve25519_key privatekey;
curve25519_key publickey; curve25519_key publickey;
salt = malloc(salt_len);
privatekey_buffer = malloc(privatekey_buffer_len);
password = malloc(password_maxlen);
password_verif = malloc(password_maxlen);
if (salt == NULL || privatekey_buffer == NULL || password == NULL ||
password_verif == NULL) {
printf("Malloc failed\n");
goto exit;
}
/* Secret (or private) key */ /* Secret (or private) key */
if (no_password) { if (no_password) {
@@ -85,33 +100,32 @@ int generate_keys(const char *seckey_filename, const char *pubkey_filename,
memcpy(privatekey_buffer + sizeof(curve25519_key), publickey, memcpy(privatekey_buffer + sizeof(curve25519_key), publickey,
sizeof(curve25519_key)); sizeof(curve25519_key));
} else { } else {
struct chacha20_drng *drng;
int ret = drng_chacha20_init(&drng); int ret = drng_chacha20_init(&drng);
if (ret) { if (ret) {
printf("Chacha20 allocation failed: %d\n", ret); printf("Chacha20 allocation failed: %d\n", ret);
goto exit; goto exit;
} }
if (drng_chacha20_get(drng, salt, sizeof(salt))) { if (drng_chacha20_get(drng, salt, salt_len)) {
printf("Getting random numbers failed\n"); printf("Getting random numbers failed\n");
goto exit; goto exit;
} }
password_out = password_out =
readpassphrase("Password : ", password, sizeof(password), 0); readpassphrase("Password : ", password, password_maxlen, 0);
if (password_out != password) { if (password_out != password) {
printf("password input failed.\n"); printf("password input failed.\n");
goto exit; goto exit;
} }
password_len = strlen(password); password_len = strnlen(password, password_maxlen);
password_verif_out = password_verif_out =
readpassphrase("Verifying, please re-enter : ", password_verif, readpassphrase("Verifying, please re-enter : ", password_verif,
sizeof(password_verif), 0); password_maxlen, 0);
if (password_verif_out != password_verif) { if (password_verif_out != password_verif) {
printf("password input failed.\n"); printf("password input failed.\n");
goto exit; goto exit;
} }
password_verif_len = strlen(password_verif); password_verif_len = strnlen(password_verif, password_maxlen);
if (password_len != password_verif_len) { if (password_len != password_verif_len) {
printf("Mismatch.\n"); printf("Mismatch.\n");
@@ -124,20 +138,19 @@ int generate_keys(const char *seckey_filename, const char *pubkey_filename,
} }
int a2res = argon2id_hash_raw(t_cost, m_cost, parallelism, password, int a2res = argon2id_hash_raw(t_cost, m_cost, parallelism, password,
password_len, salt, sizeof(salt), password_len, salt, salt_len, privatekey,
privatekey, sizeof(curve25519_key)); sizeof(curve25519_key));
if (a2res != ARGON2_OK) { if (a2res != ARGON2_OK) {
printf("argon2 failed."); printf("argon2 failed.");
goto exit; goto exit;
} }
curve25519_donna_basepoint(publickey, privatekey); curve25519_donna_basepoint(publickey, privatekey);
memcpy(privatekey_buffer, salt, sizeof(salt)); memcpy(privatekey_buffer, salt, salt_len);
memcpy(privatekey_buffer + sizeof(salt), publickey, memcpy(privatekey_buffer + salt_len, publickey, sizeof(curve25519_key));
sizeof(curve25519_key));
} }
privatekey_b64 = base64_encode(privatekey_buffer, sizeof(privatekey_buffer), privatekey_b64 = base64_encode(privatekey_buffer, privatekey_buffer_len,
&private_base64_len); &private_base64_len);
if (privatekey_b64 == NULL) { if (privatekey_b64 == NULL) {
printf("base64 encoding failed.\n"); printf("base64 encoding failed.\n");
@@ -218,15 +231,19 @@ exit:
memset(publickey_b64, 0, public_base64_len); memset(publickey_b64, 0, public_base64_len);
memset(publickey_b64t, 0, public_b64t_len); memset(publickey_b64t, 0, public_b64t_len);
memset(publickey, 0, sizeof(curve25519_key)); memset(publickey, 0, sizeof(curve25519_key));
memset(salt, 0, sizeof(salt)); memset(salt, 0, salt_len);
memset(privatekey_buffer, 0, sizeof(privatekey_buffer)); memset(privatekey_buffer, 0, privatekey_buffer_len);
memset(password, 0, sizeof(password)); memset(password, 0, password_maxlen);
memset(password_verif, 0, sizeof(password_verif)); memset(password_verif, 0, password_maxlen);
free(privatekey_b64); free(privatekey_b64);
free(publickey_b64); free(publickey_b64);
free(privatekey_b64t); free(privatekey_b64t);
free(publickey_b64t); free(publickey_b64t);
free(salt);
free(privatekey_buffer);
free(password);
free(password_verif);
if (fs != NULL) { if (fs != NULL) {
fclose(fs); fclose(fs);
@@ -252,8 +269,10 @@ int get_seckey(const char *keyfile, unsigned char *skey, unsigned char *pkey) {
FILE *fs = NULL; FILE *fs = NULL;
unsigned char salt[32] = {0}; unsigned char *salt = NULL;
char password[256] = {0}; const size_t salt_len = 32;
char *password = NULL;
const size_t password_maxlen = 256;
char *password_out = NULL; char *password_out = NULL;
curve25519_key pubkey; curve25519_key pubkey;
curve25519_key pubkey_from_secret; curve25519_key pubkey_from_secret;
@@ -263,8 +282,21 @@ int get_seckey(const char *keyfile, unsigned char *skey, unsigned char *pkey) {
const uint32_t m_cost = (1 << 12); const uint32_t m_cost = (1 << 12);
const uint32_t parallelism = 1; const uint32_t parallelism = 1;
/* max_size = base64(sizeof(curve25519_key)) = 64 * 4 / 3 + 1 -> 86 */
const size_t file_data_len = 87;
unsigned char *file_data = NULL;
int exitcode = 1; int exitcode = 1;
file_data = malloc(file_data_len);
salt = malloc(salt_len);
password = malloc(password_maxlen);
if (salt == NULL || password == NULL || file_data == NULL) {
printf("Malloc failed\n");
goto exit;
}
fs = fopen(keyfile, "rb"); fs = fopen(keyfile, "rb");
if (fs == NULL) { if (fs == NULL) {
printf("key file opening failed: %s.\n", strerror(errno)); printf("key file opening failed: %s.\n", strerror(errno));
@@ -290,10 +322,12 @@ int get_seckey(const char *keyfile, unsigned char *skey, unsigned char *pkey) {
goto exit; goto exit;
} }
/* max_size = base64(sizeof(curve25519_key)) = 64 * 4 / 3 + 1 -> 86 */ if (sz > file_data_len) {
unsigned char file_data[87] = {0}; printf("Bad key size\n");
goto exit;
}
size_t readed = fread(&file_data, 1, sz, fs); size_t readed = fread(file_data, 1, sz, fs);
if (readed != sz) { if (readed != sz) {
printf("read file '%s' failed: %s.\n", keyfile, strerror(errno)); printf("read file '%s' failed: %s.\n", keyfile, strerror(errno));
goto exit; goto exit;
@@ -325,17 +359,17 @@ int get_seckey(const char *keyfile, unsigned char *skey, unsigned char *pkey) {
int password_protected_flag = int password_protected_flag =
(memcmp(pubkey, pubkey_from_secret, sizeof(curve25519_key)) != 0); (memcmp(pubkey, pubkey_from_secret, sizeof(curve25519_key)) != 0);
if (password_protected_flag) { if (password_protected_flag) {
memcpy(salt, base64_decoded, sizeof(salt)); memcpy(salt, base64_decoded, salt_len);
password_out = password_out =
readpassphrase("Password : ", password, sizeof(password), 0); readpassphrase("Password : ", password, password_maxlen, 0);
if (password_out != password) { if (password_out != password) {
printf("password input failed.\n"); printf("password input failed.\n");
goto exit; goto exit;
} }
password_len = strlen(password); password_len = strnlen(password, password_maxlen);
int a2res = argon2id_hash_raw(t_cost, m_cost, parallelism, password, int a2res = argon2id_hash_raw(t_cost, m_cost, parallelism, password,
password_len, salt, sizeof(salt), seckey, password_len, salt, salt_len, seckey,
sizeof(curve25519_key)); sizeof(curve25519_key));
if (a2res != ARGON2_OK) { if (a2res != ARGON2_OK) {
printf("argon2 failed."); printf("argon2 failed.");
@@ -355,11 +389,11 @@ int get_seckey(const char *keyfile, unsigned char *skey, unsigned char *pkey) {
exitcode = 0; exitcode = 0;
exit: exit:
memset(file_data, 0, sizeof(file_data)); memset(file_data, 0, file_data_len);
memset(base64_decoded, 0, base64_decoded_len); memset(base64_decoded, 0, base64_decoded_len);
memset(b64t_decoded, 0, b64t_decoded_len); memset(b64t_decoded, 0, b64t_decoded_len);
memset(salt, 0, sizeof(salt)); memset(salt, 0, salt_len);
memset(password, 0, sizeof(password)); memset(password, 0, password_maxlen);
memset(seckey, 0, sizeof(curve25519_key)); memset(seckey, 0, sizeof(curve25519_key));
memset(pubkey, 0, sizeof(curve25519_key)); memset(pubkey, 0, sizeof(curve25519_key));
memset(pubkey_from_secret, 0, sizeof(curve25519_key)); memset(pubkey_from_secret, 0, sizeof(curve25519_key));
@@ -370,6 +404,9 @@ exit:
free(base64_decoded); free(base64_decoded);
free(b64t_decoded); free(b64t_decoded);
free(salt);
free(password);
free(file_data);
return exitcode; return exitcode;
} }
@@ -389,8 +426,17 @@ int get_pubkey(const char *keyfile, unsigned char *pkey) {
curve25519_key pubkey; curve25519_key pubkey;
/* max_size = base64(sizeof(curve25519_key)) = 32 * 4 / 3 + 1 -> 44 */
const size_t file_data_len = 45;
unsigned char *file_data = malloc(file_data_len);
int exitcode = 1; int exitcode = 1;
if (file_data == NULL) {
printf("Malloc failed\n");
goto exit;
}
fs = fopen(keyfile, "rb"); fs = fopen(keyfile, "rb");
if (fs == NULL) { if (fs == NULL) {
printf("key file opening failed: %s.\n", strerror(errno)); printf("key file opening failed: %s.\n", strerror(errno));
@@ -416,9 +462,12 @@ int get_pubkey(const char *keyfile, unsigned char *pkey) {
goto exit; goto exit;
} }
/* max_size = base64(sizeof(curve25519_key)) = 32 * 4 / 3 + 1 -> 44 */ if (sz > file_data_len) {
unsigned char file_data[44] = {0}; printf("Bad key size\n");
size_t readed = fread(&file_data, 1, sz, fs); goto exit;
}
size_t readed = fread(file_data, 1, sz, fs);
if (readed != sz) { if (readed != sz) {
printf("read file '%s' failed: %s.\n", keyfile, strerror(errno)); printf("read file '%s' failed: %s.\n", keyfile, strerror(errno));
goto exit; goto exit;
@@ -447,7 +496,7 @@ int get_pubkey(const char *keyfile, unsigned char *pkey) {
exitcode = 0; exitcode = 0;
exit: exit:
memset(file_data, 0, sizeof(file_data)); memset(file_data, 0, file_data_len);
memset(b64t_decoded, 0, b64t_decoded_len); memset(b64t_decoded, 0, b64t_decoded_len);
memset(base64_decoded, 0, base64_decoded_len); memset(base64_decoded, 0, base64_decoded_len);
memset(pubkey, 0, sizeof(curve25519_key)); memset(pubkey, 0, sizeof(curve25519_key));
@@ -458,6 +507,7 @@ exit:
free(b64t_decoded); free(b64t_decoded);
free(base64_decoded); free(base64_decoded);
free(file_data);
return exitcode; return exitcode;
} }
@@ -494,7 +544,7 @@ unsigned char *encrypt_data(const unsigned char *seckey,
size_t encrypted_len = 0; size_t encrypted_len = 0;
const size_t shared_secret_len = 32; const size_t shared_secret_len = 32;
unsigned char shared_secret[32] = {0}; unsigned char *shared_secret = NULL;
const size_t nonce1_len = 32; const size_t nonce1_len = 32;
const size_t tag0_len = 4; const size_t tag0_len = 4;
@@ -504,29 +554,35 @@ unsigned char *encrypt_data(const unsigned char *seckey,
const size_t nonce0_len = 32; const size_t nonce0_len = 32;
const size_t header0_len = 4; const size_t header0_len = 4;
const size_t encrypted_len_expected = data_len + tag1_len; const size_t encrypted_len_expected = data_len + tag1_len;
const size_t salt_len = 32;
const uint8_t *key1 = 0; const uint8_t *key1 = 0;
const uint8_t *nonce1 = 0; const uint8_t *nonce1 = 0;
unsigned char params[5] = {0}; unsigned char *params = NULL;
unsigned char params_encrypted[9] = {0}; unsigned char *params_encrypted = NULL;
const uint8_t *key0 = 0; const uint8_t *key0 = 0;
const uint8_t *nonce0 = 0; const uint8_t *nonce0 = 0;
unsigned char header0[4] = {0}; unsigned char *header0 = NULL;
struct chacha20_drng *drng = NULL; struct chacha20_drng *drng = NULL;
*out_encrypted_len = 0; *out_encrypted_len = 0;
// generate shared secret from DH X25519 shared_secret = malloc(shared_secret_len);
curve25519_donna(shared_secret, seckey, pubkey); params = malloc(params_len);
params_encrypted = malloc(params_encrypted_len);
header0 = malloc(header0_len);
rand = malloc(rand_len); // generate part 1 random data
// generate part 1 random data if (shared_secret == NULL || params == NULL || params_encrypted == NULL ||
rand = malloc(rand_len); header0 == NULL || rand == NULL) {
if (rand == NULL) {
printf("malloc failed.\n"); printf("malloc failed.\n");
goto exit; goto exit;
} }
// generate shared secret from DH X25519
curve25519_donna(shared_secret, seckey, pubkey);
int ret = drng_chacha20_init(&drng); int ret = drng_chacha20_init(&drng);
if (ret) { if (ret) {
printf("Chacha20 allocation failed: %d\n", ret); printf("Chacha20 allocation failed: %d\n", ret);
@@ -631,10 +687,13 @@ unsigned char *encrypt_data(const unsigned char *seckey,
} }
if (salt) { if (salt) {
memcpy(encrypted, salt, 32); memcpy(encrypted, salt, salt_len);
memcpy(32 + encrypted, pubkey, 32); memcpy(salt_len + encrypted, pubkey, sizeof(curve25519_key));
memcpy(64 + encrypted, params_encrypted, params_encrypted_len); memcpy(salt_len + sizeof(curve25519_key) + encrypted, params_encrypted,
memcpy(64 + encrypted + params_encrypted_len, part1, part1_len); params_encrypted_len);
memcpy(salt_len + sizeof(curve25519_key) + encrypted +
params_encrypted_len,
part1, part1_len);
} else { } else {
memcpy(encrypted, params_encrypted, params_encrypted_len); memcpy(encrypted, params_encrypted, params_encrypted_len);
memcpy(encrypted + params_encrypted_len, part1, part1_len); memcpy(encrypted + params_encrypted_len, part1, part1_len);
@@ -687,6 +746,10 @@ exit:
free(encrypted1); free(encrypted1);
free(part1); free(part1);
free(encrypted); free(encrypted);
free(header0);
free(shared_secret);
free(params);
free(params_encrypted);
return out; return out;
} }
@@ -699,12 +762,14 @@ int get_symmetrickeys(unsigned char *salt_out, unsigned char *seckey_out,
const uint32_t m_cost = (1 << 12); const uint32_t m_cost = (1 << 12);
const uint32_t parallelism = 1; const uint32_t parallelism = 1;
char password[256] = {0}; char *password = NULL;
char *password_out = NULL; char *password_out = NULL;
char password_verif[256] = {0}; char *password_verif = NULL;
char *password_verif_out = NULL; char *password_verif_out = NULL;
size_t password_len = 0; size_t password_len = 0;
size_t password_verif_len = 0; size_t password_verif_len = 0;
const size_t password_maxlen = 256;
const size_t salt_len = 32;
int exitcode = 1; int exitcode = 1;
@@ -718,21 +783,28 @@ int get_symmetrickeys(unsigned char *salt_out, unsigned char *seckey_out,
goto exit; goto exit;
} }
password_out = readpassphrase("Password : ", password, sizeof(password), 0); password = malloc(password_maxlen);
password_verif = malloc(password_maxlen);
if (password == NULL || password_verif == NULL) {
printf("Malloc failed\n");
goto exit;
}
password_out = readpassphrase("Password : ", password, password_maxlen, 0);
if (password_out != password) { if (password_out != password) {
printf("password input failed.\n"); printf("password input failed.\n");
goto exit; goto exit;
} }
password_len = strlen(password); password_len = strnlen(password, password_maxlen);
password_verif_out = password_verif_out = readpassphrase(
readpassphrase("Verifying, please re-enter : ", password_verif, "Verifying, please re-enter : ", password_verif, password_maxlen, 0);
sizeof(password_verif), 0);
if (password_verif_out != password_verif) { if (password_verif_out != password_verif) {
printf("password input failed.\n"); printf("password input failed.\n");
goto exit; goto exit;
} }
password_verif_len = strlen(password_verif); password_verif_len = strnlen(password_verif, password_maxlen);
if (password_len != password_verif_len) { if (password_len != password_verif_len) {
printf("Mismatch.\n"); printf("Mismatch.\n");
@@ -744,9 +816,9 @@ int get_symmetrickeys(unsigned char *salt_out, unsigned char *seckey_out,
goto exit; goto exit;
} }
int a2res = int a2res = argon2id_hash_raw(t_cost, m_cost, parallelism, password,
argon2id_hash_raw(t_cost, m_cost, parallelism, password, password_len, password_len, salt_out, salt_len, seckey_out,
salt_out, 32, seckey_out, sizeof(curve25519_key)); sizeof(curve25519_key));
if (a2res != ARGON2_OK) { if (a2res != ARGON2_OK) {
printf("argon2 failed."); printf("argon2 failed.");
goto exit; goto exit;
@@ -758,8 +830,10 @@ int get_symmetrickeys(unsigned char *salt_out, unsigned char *seckey_out,
exit: exit:
drng_chacha20_destroy(drng); drng_chacha20_destroy(drng);
memset(password, 0, sizeof(password)); memset(password, 0, password_maxlen);
memset(password_verif, 0, sizeof(password_verif)); memset(password_verif, 0, password_maxlen);
free(password);
free(password_verif);
return exitcode; return exitcode;
} }
@@ -771,7 +845,7 @@ int check_get_symmetrickeys(const unsigned char *data, const size_t data_len,
const uint32_t m_cost = (1 << 12); const uint32_t m_cost = (1 << 12);
const uint32_t parallelism = 1; const uint32_t parallelism = 1;
char password[256] = {0}; char *password = NULL;
char *password_out = NULL; char *password_out = NULL;
size_t password_len = 0; size_t password_len = 0;
@@ -780,11 +854,21 @@ int check_get_symmetrickeys(const unsigned char *data, const size_t data_len,
size_t data_b64t_decoded_len = 0; size_t data_b64t_decoded_len = 0;
size_t encrypted_len = 0; size_t encrypted_len = 0;
unsigned char salt[32] = {0}; unsigned char *salt = NULL;
const size_t salt_len = 32;
const size_t password_maxlen = 256;
curve25519_key pubkey_from_secret; curve25519_key pubkey_from_secret;
int exitcode = 1; int exitcode = 1;
password = malloc(password_maxlen);
salt = malloc(salt_len);
if (password == NULL || salt == NULL) {
printf("Malloc failed\n");
goto exit;
}
data_b64t_decoded = b64t_decode(data, data_len, &data_b64t_decoded_len); data_b64t_decoded = b64t_decode(data, data_len, &data_b64t_decoded_len);
encrypted = encrypted =
@@ -794,19 +878,19 @@ int check_get_symmetrickeys(const unsigned char *data, const size_t data_len,
goto exit; goto exit;
} }
memcpy(salt, encrypted, 32); memcpy(salt, encrypted, salt_len);
memcpy(pubkey_from_secret, encrypted + 32, 32); memcpy(pubkey_from_secret, encrypted + 32, sizeof(curve25519_key));
password_out = readpassphrase("Password : ", password, sizeof(password), 0); password_out = readpassphrase("Password : ", password, password_maxlen, 0);
if (password_out != password) { if (password_out != password) {
printf("password input failed.\n"); printf("password input failed.\n");
goto exit; goto exit;
} }
password_len = strlen(password); password_len = strnlen(password, password_maxlen);
int a2res = int a2res =
argon2id_hash_raw(t_cost, m_cost, parallelism, password, password_len, argon2id_hash_raw(t_cost, m_cost, parallelism, password, password_len,
salt, 32, seckey_out, sizeof(curve25519_key)); salt, salt_len, seckey_out, sizeof(curve25519_key));
if (a2res != ARGON2_OK) { if (a2res != ARGON2_OK) {
printf("argon2 failed."); printf("argon2 failed.");
goto exit; goto exit;
@@ -816,7 +900,7 @@ int check_get_symmetrickeys(const unsigned char *data, const size_t data_len,
if (memcmp(pubkey_out, pubkey_from_secret, sizeof(curve25519_key)) != 0) { if (memcmp(pubkey_out, pubkey_from_secret, sizeof(curve25519_key)) != 0) {
printf("Wrong password\n"); printf("Wrong password\n");
memset(seckey_out, 0, sizeof(curve25519_key)); memset(seckey_out, 0, sizeof(curve25519_key));
memset(salt, 0, 32); memset(salt, 0, salt_len);
memset(pubkey_out, 0, sizeof(curve25519_key)); memset(pubkey_out, 0, sizeof(curve25519_key));
goto exit; goto exit;
} }
@@ -824,12 +908,15 @@ int check_get_symmetrickeys(const unsigned char *data, const size_t data_len,
exitcode = 0; exitcode = 0;
exit: exit:
memset(password, 0, sizeof(password)); memset(password, 0, password_maxlen);
memset(encrypted, 0, encrypted_len); memset(encrypted, 0, encrypted_len);
memset(data_b64t_decoded, 0, data_b64t_decoded_len); memset(data_b64t_decoded, 0, data_b64t_decoded_len);
memset(salt, 0, salt_len);
free(encrypted); free(encrypted);
free(data_b64t_decoded); free(data_b64t_decoded);
free(password);
free(salt);
return exitcode; return exitcode;
} }
@@ -849,8 +936,8 @@ unsigned char *decrypt_data(const unsigned char *seckey,
unsigned char *message = NULL; unsigned char *message = NULL;
unsigned char *encrypted1 = NULL; unsigned char *encrypted1 = NULL;
size_t shared_secret_len = 32; const size_t shared_secret_len = 32;
unsigned char shared_secret[32] = {0}; unsigned char *shared_secret = NULL;
size_t encrypted_len = 0; size_t encrypted_len = 0;
size_t data_b64t_decoded_len = 0; size_t data_b64t_decoded_len = 0;
@@ -872,15 +959,27 @@ unsigned char *decrypt_data(const unsigned char *seckey,
const uint8_t *nonce0 = 0; const uint8_t *nonce0 = 0;
const size_t header0_len = 4; const size_t header0_len = 4;
unsigned char header0[4] = {0}; unsigned char *header0 = NULL;
const uint8_t *key0 = 0; const uint8_t *key0 = 0;
unsigned char encrypted0[9] = {0}; unsigned char *encrypted0 = NULL;
const size_t encrypted0_len = 9;
const size_t params_len = 5; const size_t params_len = 5;
unsigned char params[5]; unsigned char *params = NULL;
size_t norx_params_len = 0; size_t norx_params_len = 0;
const uint8_t *nonce1 = 0; const uint8_t *nonce1 = 0;
const uint8_t *key1 = 0; const uint8_t *key1 = 0;
shared_secret = malloc(shared_secret_len);
encrypted0 = malloc(encrypted0_len);
params = malloc(params_len);
header0 = malloc(header0_len);
if (shared_secret == NULL || encrypted0 == NULL || params == NULL ||
header0 == NULL) {
printf("Malloc failed\n");
goto exit;
}
// shared secret DH X25519 // shared secret DH X25519
curve25519_donna(shared_secret, seckey, pubkey); curve25519_donna(shared_secret, seckey, pubkey);
@@ -1019,6 +1118,11 @@ exit:
memset(&nc0, 0, sizeof(sha3_context)); memset(&nc0, 0, sizeof(sha3_context));
memset(&nc1, 0, sizeof(sha3_context)); memset(&nc1, 0, sizeof(sha3_context));
free(shared_secret);
free(encrypted0);
free(params);
free(header0);
free(data_b64t_decoded); free(data_b64t_decoded);
if (symmetric_flag) if (symmetric_flag)
free(encrypted - 64); free(encrypted - 64);
@@ -1030,4 +1134,3 @@ exit:
return message; return message;
return NULL; return NULL;
} }

View File

@@ -28,6 +28,8 @@ struct arg_file *seckey, *pubkey, *infile, *outfile;
struct arg_end *end; struct arg_end *end;
struct arg_int *taglen, *noncelen, *cipherlen; struct arg_int *taglen, *noncelen, *cipherlen;
int file_exist (const char *filename);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
/* the global arg_xxx structs are initialised within the argtable */ /* the global arg_xxx structs are initialised within the argtable */
void *argtable[] = { void *argtable[] = {
@@ -53,7 +55,7 @@ int main(int argc, char *argv[]) {
int exitcode = 0; int exitcode = 0;
const char progname[] = "inexact"; const char progname[] = "inexact";
const char ver[] = "beta 1.0"; const char ver[] = "beta 1.02";
FILE *fo = NULL; FILE *fo = NULL;
int nerrors; int nerrors;
@@ -186,7 +188,7 @@ int main(int argc, char *argv[]) {
exitcode = 1; exitcode = 1;
goto exit; goto exit;
} }
if (access(seckey->filename[0], F_OK) != -1) { if (file_exist(seckey->filename[0]) == 1) {
char ch; char ch;
printf("Overwrite '%s' ? ", seckey->filename[0]); printf("Overwrite '%s' ? ", seckey->filename[0]);
int res = scanf("%c", &ch); int res = scanf("%c", &ch);
@@ -195,7 +197,7 @@ int main(int argc, char *argv[]) {
goto exit; goto exit;
} }
} }
if (access(pubkey->filename[0], F_OK) != -1) { if (file_exist(pubkey->filename[0]) == 1) {
char ch; char ch;
printf("Overwrite '%s' ? ", pubkey->filename[0]); printf("Overwrite '%s' ? ", pubkey->filename[0]);
int res = scanf(" %c", &ch); int res = scanf(" %c", &ch);
@@ -245,7 +247,7 @@ int main(int argc, char *argv[]) {
} }
data[len - 1] = '\0'; data[len - 1] = '\0';
data_len = len - 1; data_len = len - 1;
} else if (access(infile->filename[0], F_OK) == -1) { } else if (file_exist(infile->filename[0]) == 0) {
printf("Input file '%s' not found.\n", infile->filename[0]); printf("Input file '%s' not found.\n", infile->filename[0]);
exitcode = 1; exitcode = 1;
goto exit; goto exit;
@@ -379,7 +381,8 @@ int main(int argc, char *argv[]) {
int base64_transformation = (base64->count == 0); int base64_transformation = (base64->count == 0);
if (cipherlen->count == 1) { if (cipherlen->count == 1) {
if (dencrypt->count == 0 || noncelen->count == 1 || base64->count == 1) { if (dencrypt->count == 0 || noncelen->count == 1 ||
base64->count == 1) {
printf("Invalid options.\n"); printf("Invalid options.\n");
printf("Try '%s --help' for more information.\n", progname); printf("Try '%s --help' for more information.\n", progname);
exitcode = 1; exitcode = 1;
@@ -417,8 +420,8 @@ int main(int argc, char *argv[]) {
} }
if (weak->count == 1) { if (weak->count == 1) {
if (dencrypt->count == 0 || noncelen->count == 1 || taglen->count == 1 || if (dencrypt->count == 0 || noncelen->count == 1 ||
cipherlen->count == 1) { taglen->count == 1 || cipherlen->count == 1) {
printf("Invalid options.\n"); printf("Invalid options.\n");
printf("Try '%s --help' for more information.\n", progname); printf("Try '%s --help' for more information.\n", progname);
exitcode = 1; exitcode = 1;
@@ -428,10 +431,17 @@ int main(int argc, char *argv[]) {
auth_tag_len = 4; auth_tag_len = 4;
} }
unsigned char *secretkey = malloc(32);
unsigned char *publickey = malloc(32);
unsigned char *salt = malloc(32);
if (secretkey == NULL || publickey == NULL || salt == NULL) {
printf("Malloc failed\n");
exitcode = 1;
goto exit;
}
if (dencrypt->count == 1) { if (dencrypt->count == 1) {
unsigned char secretkey[32] = {0};
unsigned char publickey[32] = {0};
unsigned char salt[32] = {0};
unsigned char *psalt = NULL; unsigned char *psalt = NULL;
if (symmetric->count == 1) { if (symmetric->count == 1) {
@@ -442,7 +452,7 @@ int main(int argc, char *argv[]) {
} }
psalt = &salt[0]; psalt = &salt[0];
} else { } else {
if (access(seckey->filename[0], F_OK) == -1) { if (file_exist(seckey->filename[0]) == 0) {
printf("Secret key file '%s' not found.\n", printf("Secret key file '%s' not found.\n",
seckey->filename[0]); seckey->filename[0]);
exitcode = 1; exitcode = 1;
@@ -453,7 +463,7 @@ int main(int argc, char *argv[]) {
exitcode = 1; exitcode = 1;
goto exit; goto exit;
} }
if (access(pubkey->filename[0], F_OK) == -1) { if (file_exist(pubkey->filename[0]) == 0) {
printf("Public key file '%s' not found.\n", printf("Public key file '%s' not found.\n",
pubkey->filename[0]); pubkey->filename[0]);
exitcode = 1; exitcode = 1;
@@ -487,9 +497,6 @@ int main(int argc, char *argv[]) {
} }
if (ddecrypt->count == 1) { if (ddecrypt->count == 1) {
unsigned char secretkey[32] = {0};
unsigned char publickey[32] = {0};
if (base64->count == 1) { if (base64->count == 1) {
printf("Invalid options.\n"); printf("Invalid options.\n");
printf("Try '%s --help' for more information.\n", progname); printf("Try '%s --help' for more information.\n", progname);
@@ -503,7 +510,7 @@ int main(int argc, char *argv[]) {
goto exit; goto exit;
} }
} else { } else {
if (access(seckey->filename[0], F_OK) == -1) { if (file_exist(seckey->filename[0]) == 0) {
printf("Secret key file '%s' not found.\n", printf("Secret key file '%s' not found.\n",
seckey->filename[0]); seckey->filename[0]);
exitcode = 1; exitcode = 1;
@@ -514,7 +521,7 @@ int main(int argc, char *argv[]) {
exitcode = 1; exitcode = 1;
goto exit; goto exit;
} }
if (access(pubkey->filename[0], F_OK) == -1) { if (file_exist(pubkey->filename[0]) == 0) {
printf("Public key file '%s' not found.\n", printf("Public key file '%s' not found.\n",
pubkey->filename[0]); pubkey->filename[0]);
exitcode = 1; exitcode = 1;
@@ -542,8 +549,12 @@ int main(int argc, char *argv[]) {
memset(decrypted, 0, decrypted_len); memset(decrypted, 0, decrypted_len);
memset(secretkey, 0, 32); memset(secretkey, 0, 32);
memset(publickey, 0, 32); memset(publickey, 0, 32);
memset(salt, 0, 32);
memset(data, 0, data_len); memset(data, 0, data_len);
free(decrypted); free(decrypted);
free(secretkey);
free(salt);
free(publickey);
} }
exit: exit:
@@ -553,3 +564,18 @@ exit:
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return exitcode; return exitcode;
} }
int file_exist(const char *filename) {
int exist = 0;
FILE *file;
if ((file = fopen(filename, "r")) == NULL) {
if (errno != ENOENT) {
printf("Some other error occured");
}
} else {
exist = 1;
fclose(file);
}
return exist;
}

View File

@@ -236,24 +236,24 @@ static int randombytes_js_randombytes_nodejs(void *buf, size_t n) {
int randombytes(void *buf, size_t n) int randombytes(void *buf, size_t n)
{ {
#if defined(__EMSCRIPTEN__) #if defined(__EMSCRIPTEN__)
# pragma message("Using crypto api from NodeJS") //# pragma message("Using crypto api from NodeJS")
return randombytes_js_randombytes_nodejs(buf, n); return randombytes_js_randombytes_nodejs(buf, n);
#elif defined(__linux__) #elif defined(__linux__)
# if defined(SYS_getrandom) # if defined(SYS_getrandom)
# pragma message("Using getrandom system call") //# pragma message("Using getrandom system call")
/* Use getrandom system call */ /* Use getrandom system call */
return randombytes_linux_randombytes_getrandom(buf, n); return randombytes_linux_randombytes_getrandom(buf, n);
# else # else
# pragma message("Using /dev/urandom device") //# pragma message("Using /dev/urandom device")
/* When we have enough entropy, we can read from /dev/urandom */ /* When we have enough entropy, we can read from /dev/urandom */
return randombytes_linux_randombytes_urandom(buf, n); return randombytes_linux_randombytes_urandom(buf, n);
# endif # endif
#elif defined(BSD) #elif defined(BSD)
# pragma message("Using arc4random system call") //# pragma message("Using arc4random system call")
/* Use arc4random system call */ /* Use arc4random system call */
return randombytes_bsd_randombytes(buf, n); return randombytes_bsd_randombytes(buf, n);
#elif defined(_WIN32) #elif defined(_WIN32)
# pragma message("Using Windows cryptographic API") //# pragma message("Using Windows cryptographic API")
/* Use windows API */ /* Use windows API */
return randombytes_win32_randombytes(buf, n); return randombytes_win32_randombytes(buf, n);
#else #else

View File

@@ -133,15 +133,15 @@ restart:
/* /*
* Fix strange behaviour: a file must be open to prevent echo * Fix strange behaviour: a file must be open to prevent echo
*/ */
if (!(flags & RPP_ECHO_ON)) if (!(flags & RPP_ECHO_ON)) {
open(_PATH_TTY, O_RDONLY); open(_PATH_TTY, O_RDONLY);
}
/* /*
* Read and write to /dev/tty if available. If not, read from * Read and write to /dev/tty if available. If not, read from
* stdin and write to stderr unless a tty is required. * stdin and write to stderr unless a tty is required.
*/ */
if ((flags & RPP_STDIN) || if ((flags & RPP_STDIN) || (input = output = open(_PATH_TTY, O_RDWR)) == -1) {
(input = output = open(_PATH_TTY, O_RDWR)) == -1) {
if (flags & RPP_REQUIRE_TTY) { if (flags & RPP_REQUIRE_TTY) {
errno = ENOTTY; errno = ENOTTY;
return(NULL); return(NULL);

View File

@@ -23,22 +23,15 @@
#include "sha3.h" #include "sha3.h"
#define SHA3_ASSERT( x ) #define SHA3_ASSERT( x )
#if defined(_MSC_VER)
#define SHA3_TRACE( format, ...) #define SHA3_TRACE( format, ...)
#define SHA3_TRACE_BUF( format, buf, l, ...) #define SHA3_TRACE_BUF(format, buf, l)
#else
#define SHA3_TRACE(format, args...)
#define SHA3_TRACE_BUF(format, buf, l, args...)
#endif
//#define SHA3_USE_KECCAK
/* /*
* Define SHA3_USE_KECCAK to run "pure" Keccak, as opposed to SHA3. * This flag is used to configure "pure" Keccak, as opposed to NIST SHA3.
* The tests that this macro enables use the input and output from [Keccak]
* (see the reference below). The used test vectors aren't correct for SHA3,
* however, they are helpful to verify the implementation.
* SHA3_USE_KECCAK only changes one line of code in Finalize.
*/ */
#define SHA3_USE_KECCAK_FLAG 0x80000000
#define SHA3_CW(x) ((x) & (~SHA3_USE_KECCAK_FLAG))
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define SHA3_CONST(x) x #define SHA3_CONST(x) x
@@ -123,30 +116,44 @@ keccakf(uint64_t s[25])
/* *************************** Public Inteface ************************ */ /* *************************** Public Inteface ************************ */
/* For Init or Reset call these: */ /* For Init or Reset call these: */
sha3_return_t
sha3_Init(void *priv, unsigned bitSize) {
sha3_context *ctx = (sha3_context *) priv;
if( bitSize != 256 && bitSize != 384 && bitSize != 512 )
return SHA3_RETURN_BAD_PARAMS;
memset(ctx, 0, sizeof(*ctx));
ctx->capacityWords = 2 * bitSize / (8 * sizeof(uint64_t));
return SHA3_RETURN_OK;
}
void void
sha3_Init256(void *priv) sha3_Init256(void *priv)
{ {
sha3_context *ctx = (sha3_context *) priv; sha3_Init(priv, 256);
memset(ctx, 0, sizeof(*ctx));
ctx->capacityWords = 2 * 256 / (8 * sizeof(uint64_t));
} }
void void
sha3_Init384(void *priv) sha3_Init384(void *priv)
{ {
sha3_context *ctx = (sha3_context *) priv; sha3_Init(priv, 384);
memset(ctx, 0, sizeof(*ctx));
ctx->capacityWords = 2 * 384 / (8 * sizeof(uint64_t));
} }
void void
sha3_Init512(void *priv) sha3_Init512(void *priv)
{ {
sha3_context *ctx = (sha3_context *) priv; sha3_Init(priv, 512);
memset(ctx, 0, sizeof(*ctx));
ctx->capacityWords = 2 * 512 / (8 * sizeof(uint64_t));
} }
enum SHA3_FLAGS
sha3_SetFlags(void *priv, enum SHA3_FLAGS flags)
{
sha3_context *ctx = (sha3_context *) priv;
flags &= SHA3_FLAGS_KECCAK;
ctx->capacityWords |= (flags == SHA3_FLAGS_KECCAK ? SHA3_USE_KECCAK_FLAG : 0);
return flags;
}
void void
sha3_Update(void *priv, void const *bufIn, size_t len) sha3_Update(void *priv, void const *bufIn, size_t len)
{ {
@@ -164,7 +171,7 @@ sha3_Update(void *priv, void const *bufIn, size_t len)
SHA3_TRACE_BUF("called to update with:", buf, len); SHA3_TRACE_BUF("called to update with:", buf, len);
SHA3_ASSERT(ctx->byteIndex < 8); SHA3_ASSERT(ctx->byteIndex < 8);
SHA3_ASSERT(ctx->wordIndex < sizeof(ctx->s) / sizeof(ctx->s[0])); SHA3_ASSERT(ctx->wordIndex < sizeof(ctx->u.s) / sizeof(ctx->u.s[0]));
if(len < old_tail) { /* have no complete word or haven't started if(len < old_tail) { /* have no complete word or haven't started
* the word yet */ * the word yet */
@@ -185,13 +192,13 @@ sha3_Update(void *priv, void const *bufIn, size_t len)
ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8); ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
/* now ready to add saved to the sponge */ /* now ready to add saved to the sponge */
ctx->s[ctx->wordIndex] ^= ctx->saved; ctx->u.s[ctx->wordIndex] ^= ctx->saved;
SHA3_ASSERT(ctx->byteIndex == 8); SHA3_ASSERT(ctx->byteIndex == 8);
ctx->byteIndex = 0; ctx->byteIndex = 0;
ctx->saved = 0; ctx->saved = 0;
if(++ctx->wordIndex == if(++ctx->wordIndex ==
(SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords)) { (SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
keccakf(ctx->s); keccakf(ctx->u.s);
ctx->wordIndex = 0; ctx->wordIndex = 0;
} }
} }
@@ -217,10 +224,10 @@ sha3_Update(void *priv, void const *bufIn, size_t len)
#if defined(__x86_64__ ) || defined(__i386__) #if defined(__x86_64__ ) || defined(__i386__)
SHA3_ASSERT(memcmp(&t, buf, 8) == 0); SHA3_ASSERT(memcmp(&t, buf, 8) == 0);
#endif #endif
ctx->s[ctx->wordIndex] ^= t; ctx->u.s[ctx->wordIndex] ^= t;
if(++ctx->wordIndex == if(++ctx->wordIndex ==
(SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords)) { (SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
keccakf(ctx->s); keccakf(ctx->u.s);
ctx->wordIndex = 0; ctx->wordIndex = 0;
} }
} }
@@ -253,21 +260,22 @@ sha3_Finalize(void *priv)
* Overall, we feed 0, then 1, and finally 1 to start padding. Without * Overall, we feed 0, then 1, and finally 1 to start padding. Without
* M || 01, we would simply use 1 to start padding. */ * M || 01, we would simply use 1 to start padding. */
#ifndef SHA3_USE_KECCAK uint64_t t;
/* SHA3 version */
ctx->s[ctx->wordIndex] ^=
(ctx->saved ^ ((uint64_t) ((uint64_t) (0x02 | (1 << 2)) <<
((ctx->byteIndex) * 8))));
#else
/* For testing the "pure" Keccak version */
ctx->s[ctx->wordIndex] ^=
(ctx->saved ^ ((uint64_t) ((uint64_t) 1 << (ctx->byteIndex *
8))));
#endif
ctx->s[SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords - 1] ^= if( ctx->capacityWords & SHA3_USE_KECCAK_FLAG ) {
/* Keccak version */
t = (uint64_t)(((uint64_t) 1) << (ctx->byteIndex * 8));
}
else {
/* SHA3 version */
t = (uint64_t)(((uint64_t)(0x02 | (1 << 2))) << ((ctx->byteIndex) * 8));
}
ctx->u.s[ctx->wordIndex] ^= ctx->saved ^ t;
ctx->u.s[SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords) - 1] ^=
SHA3_CONST(0x8000000000000000UL); SHA3_CONST(0x8000000000000000UL);
keccakf(ctx->s); keccakf(ctx->u.s);
/* Return first bytes of the ctx->s. This conversion is not needed for /* Return first bytes of the ctx->s. This conversion is not needed for
* little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__) * little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__)
@@ -277,20 +285,39 @@ sha3_Finalize(void *priv)
{ {
unsigned i; unsigned i;
for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
const unsigned t1 = (uint32_t) ctx->s[i]; const unsigned t1 = (uint32_t) ctx->u.s[i];
const unsigned t2 = (uint32_t) ((ctx->s[i] >> 16) >> 16); const unsigned t2 = (uint32_t) ((ctx->u.s[i] >> 16) >> 16);
ctx->sb[i * 8 + 0] = (uint8_t) (t1); ctx->u.sb[i * 8 + 0] = (uint8_t) (t1);
ctx->sb[i * 8 + 1] = (uint8_t) (t1 >> 8); ctx->u.sb[i * 8 + 1] = (uint8_t) (t1 >> 8);
ctx->sb[i * 8 + 2] = (uint8_t) (t1 >> 16); ctx->u.sb[i * 8 + 2] = (uint8_t) (t1 >> 16);
ctx->sb[i * 8 + 3] = (uint8_t) (t1 >> 24); ctx->u.sb[i * 8 + 3] = (uint8_t) (t1 >> 24);
ctx->sb[i * 8 + 4] = (uint8_t) (t2); ctx->u.sb[i * 8 + 4] = (uint8_t) (t2);
ctx->sb[i * 8 + 5] = (uint8_t) (t2 >> 8); ctx->u.sb[i * 8 + 5] = (uint8_t) (t2 >> 8);
ctx->sb[i * 8 + 6] = (uint8_t) (t2 >> 16); ctx->u.sb[i * 8 + 6] = (uint8_t) (t2 >> 16);
ctx->sb[i * 8 + 7] = (uint8_t) (t2 >> 24); ctx->u.sb[i * 8 + 7] = (uint8_t) (t2 >> 24);
} }
} }
SHA3_TRACE_BUF("Hash: (first 32 bytes)", ctx->sb, 256 / 8); SHA3_TRACE_BUF("Hash: (first 32 bytes)", ctx->u.sb, 256 / 8);
return (ctx->sb); return (ctx->u.sb);
}
sha3_return_t sha3_HashBuffer( unsigned bitSize, enum SHA3_FLAGS flags, const void *in, unsigned inBytes, void *out, unsigned outBytes ) {
sha3_return_t err;
sha3_context c;
err = sha3_Init(&c, bitSize);
if( err != SHA3_RETURN_OK )
return err;
if( sha3_SetFlags(&c, flags) != flags ) {
return SHA3_RETURN_BAD_PARAMS;
}
sha3_Update(&c, in, inBytes);
const void *h = sha3_Finalize(&c);
if(outBytes > bitSize/8)
outBytes = bitSize/8;
memcpy(out, h, outBytes);
return SHA3_RETURN_OK;
} }

View File

@@ -1,6 +1,8 @@
#ifndef SHA3_H #ifndef SHA3_H
#define SHA3_H #define SHA3_H
#include <stdint.h>
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* Works when compiled for either 32-bit or 64-bit targets, optimized for * Works when compiled for either 32-bit or 64-bit targets, optimized for
* 64 bit. * 64 bit.
@@ -28,7 +30,7 @@ typedef struct sha3_context_ {
union { /* Keccak's state */ union { /* Keccak's state */
uint64_t s[SHA3_KECCAK_SPONGE_WORDS]; uint64_t s[SHA3_KECCAK_SPONGE_WORDS];
uint8_t sb[SHA3_KECCAK_SPONGE_WORDS * 8]; uint8_t sb[SHA3_KECCAK_SPONGE_WORDS * 8];
}; } u;
unsigned byteIndex; /* 0..7--the next byte after the set one unsigned byteIndex; /* 0..7--the next byte after the set one
* (starts from 0; 0--none are buffered) */ * (starts from 0; 0--none are buffered) */
unsigned wordIndex; /* 0..24--the next word to integrate input unsigned wordIndex; /* 0..24--the next word to integrate input
@@ -37,14 +39,35 @@ typedef struct sha3_context_ {
* words (e.g. 16 for Keccak 512) */ * words (e.g. 16 for Keccak 512) */
} sha3_context; } sha3_context;
enum SHA3_FLAGS {
SHA3_FLAGS_NONE=0,
SHA3_FLAGS_KECCAK=1
};
enum SHA3_RETURN {
SHA3_RETURN_OK=0,
SHA3_RETURN_BAD_PARAMS=1
};
typedef enum SHA3_RETURN sha3_return_t;
/* For Init or Reset call these: */ /* For Init or Reset call these: */
sha3_return_t sha3_Init(void *priv, unsigned bitSize);
void sha3_Init256(void *priv); void sha3_Init256(void *priv);
void sha3_Init384(void *priv); void sha3_Init384(void *priv);
void sha3_Init512(void *priv); void sha3_Init512(void *priv);
enum SHA3_FLAGS sha3_SetFlags(void *priv, enum SHA3_FLAGS);
void sha3_Update(void *priv, void const *bufIn, size_t len); void sha3_Update(void *priv, void const *bufIn, size_t len);
void const *sha3_Finalize(void *priv); void const *sha3_Finalize(void *priv);
/* Single-call hashing */
sha3_return_t sha3_HashBuffer(
unsigned bitSize, /* 256, 384, 512 */
enum SHA3_FLAGS flags, /* SHA3_FLAGS_NONE or SHA3_FLAGS_KECCAK */
const void *in, unsigned inBytes,
void *out, unsigned outBytes ); /* up to bitSize/8; truncation OK */
#endif #endif