move to meson and ninja: build of lib and binary

This commit is contained in:
2025-11-24 13:44:53 +01:00
parent 48e87fd605
commit fdfbdb7061
48 changed files with 1384 additions and 1626 deletions

View File

@@ -0,0 +1,29 @@
PCPEXPORT = pcp.h \
pcp/crypto.h \
pcp/config.h \
pcp/defines.h \
pcp/getpass.h \
pcp/jenhash.h \
pcp/key.h \
pcp/keyhash.h \
pcp/mem.h \
pcp/platform.h \
pcp/plist.h \
pcp/randomart.h \
pcp/uthash.h \
pcp/vault.h \
pcp/version.h \
pcp/z85.h \
pcp/zmq_z85.h \
pcp/ed.h \
pcp/buffer.h \
pcp/mgmt.h \
pcp/pcpstream.h \
pcp/keysig.h \
pcp/context.h \
pcp/structs.h \
pcp/util.h \
pcp/readpass.h \
pcp/scrypt.h
nobase_include_HEADERS = $(PCPEXPORT)

39
libpcp/include/pcp.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef _HAVE_PCP
#define _HAVE_PCP
#ifdef __cplusplus
extern "C" {
#endif
#include "pcp/config.h"
#include "pcp/buffer.h"
#include "pcp/context.h"
#include "pcp/crypto.h"
#include "pcp/defines.h"
#include "pcp/ed.h"
#include "pcp/getpass.h"
#include "pcp/jenhash.h"
#include "pcp/key.h"
#include "pcp/keyhash.h"
#include "pcp/keysig.h"
#include "pcp/mem.h"
#include "pcp/mgmt.h"
#include "pcp/pcpstream.h"
#include "pcp/platform.h"
#include "pcp/plist.h"
#include "pcp/randomart.h"
#include "pcp/readpass.h"
#include "pcp/scrypt.h"
#include "pcp/structs.h"
#include "pcp/uthash.h"
#include "pcp/util.h"
#include "pcp/vault.h"
#include "pcp/version.h"
#include "pcp/z85.h"
#include "pcp/zmq_z85.h"
#ifdef __cplusplus
}
#endif
#endif

654
libpcp/include/pcp/buffer.h Normal file
View File

@@ -0,0 +1,654 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef HAVE_PCP_BUFFER_H
#define HAVE_PCP_BUFFER_H
#include <stdio.h>
#include <stdarg.h>
#include "mem.h"
#include "util.h"
#include "defines.h"
#include "structs.h"
#include "context.h"
/**
* \defgroup Buffer BUFFER
* @{
Flexible buffer management, idea from openssh/buffer.c.
This class allows us to dissect buffers into parts at will
whithout the hassle of boundary checking in each and every
line. Therefore it is more secure, since this system wraps
all this stuff from us, so in case we're attemt to overflow
a buffer or the like, the buffer functions will catch this,
warn us and die.
*/
/** Create a new buffer.
Create a new buffer, initially alloc'd to blocksize and zero-filled.
\param[in] blocksize Initial blocksize. The smaller the more often
the buffer will be resized. Choose with care.
\param[in] name A name for the Buffer. Just used for debugging purposes or in error messages.
\return Returns a new Buffer object.
*/
Buffer *buffer_new(size_t blocksize, char *name);
/** Create a new string buffer.
Create a new buffer, initially alloc'd to a blocksize of 32 bytes and zero-filled.
The buffer will be a string buffer. See buffer_get_str().
\param[in] name A name for the Buffer. Just used for debugging purposes or in error messages.
\return Returns a new Buffer object.
*/
Buffer *buffer_new_str(char *name);
/** Create a new buffer from existing data.
Create a new buffer, but don't allocate memory nor copy data.
Instead the provided data pointer will be used as internal
storage directly.
This kind of buffer can be used to put the Buffer API into
use with existing data from other sources. In most cases you'll
use it for reading. However, please be aware, that it can be
used for writing as well and in this case the data pointer
maybe resized (by calling realloc()).
When calling buffer_free() on this Buffer, the memory pointed to
by the given data pointer will not be free'd and remains accessible.
It's the responsibility of the caller to do so.
Example using mmap(2):
@code
#include <stdio.h>
#include <pcp.h>
#include <sys/mman.h>
FILE *RFD;
size_t rs;
Buffer *rb;
byte *chunk;
void *r;
if((RFD = fopen("README", "rb")) == NULL) {
fprintf(stderr, "oops, could not open README!\n");
return 1;
}
fseek(RFD, 0, SEEK_END);
rs = ftell(RFD);
fseek(RFD, 0, SEEK_SET);
void *r = mmap(NULL, rs, PROT_READ, 0, fileno(RFD), 0);
*rb = buffer_new_buf("r", r, rs);
size_t blocksize = 36;
void *chunk = malloc(blocksize);
while(buffer_done(rb) != 1) {
if(buffer_left(rb) < blocksize)
blocksize = buffer_left(rb);
buffer_get_chunk(rb, chunk, blocksize);
_dump("chunk", chunk, blocksize); // or do something else with it
}
buffer_free(rb);
munmap(r, rs);
fclose(RFD);
@endcode
\param[in] name A name for the Buffer. Just used for debugging purposes or in error messages.
\param[in] data The data pointer to use by the buffer.
\param[in] datasize The size of the data.
\return Returns a new Buffer object.
*/
Buffer *buffer_new_buf(char *name, void *data, size_t datasize);
/* initialize buffer vars */
void buffer_init(Buffer *b, size_t blocksize, char *name);
/** Clears and frees the Buffer.
This clears the buffer by filling it with zeroes and frees any
allocated memory, including the Buffer object itself. Use this
function instead of directly calling free(Buffer).
\param[in] b The Buffer object.
*/
void buffer_free(Buffer *b);
/** Clears the Buffer.
This clears the buffer by filling it with zeroes and resetting
all counters. Memory will not be free'd. Called from buffer_free()
before free'ing memory.
\param[in] b The Buffer object.
*/
void buffer_clear(Buffer *b);
/** Put read offset back to start.
This function sets the read offset counter back to 0 (start
of the buffer).
\param[in] b The Buffer object.
*/
void buffer_rewind(Buffer *b);
/** Add data to the buffer.
Adds data of the size len to the buffer and resizes the
buffer, if neccessary. The write position ('end' field)
will be updated accordingly.
Data will be copied, you can free() the given pointer after copying..
\param[in] b The Buffer object.
\param[out] data Arbitrary data to add to the Buffer.
\param[in] len The size of the data to add in Bytes.
*/
void buffer_add(Buffer *b, const void *data, size_t len);
/** Add data to the buffer.
Adds data from the given Buffer src to the buffer and resizes the
buffer, if neccessary. The write position ('end' field)
will be updated accordingly.
Data will be copied, you can buffer_free() the given src Buffer after the copying.
\param[out] dst The destination Buffer object to copy data into.
\param[in] src The source Buffer object to copy data from.
*/
void buffer_add_buf(Buffer *dst, Buffer *src);
/** Add a formated string to the buffer.
Use printf() like syntax to add a formatted string
to the buffer. Refer to the documentation of printf() for
details.
Data will be copied, you can free() the given format string and params after copying.
Example:
@code
Buffer *x = buffer_new_str("test");
buffer_add_str(x, "There are %d elements left in %s\n", 4, "list");
@endcode
\param[in] b The Buffer object.
\param[in] fmt The printf() compatible format description.
\param[in] ... A variable number of arguments for the format string.
*/
void buffer_add_str(Buffer *b, const char * fmt, ...);
/** Add data as hex string to the buffer.
Adds data of the size len to the buffer and resizes the
buffer, if neccessary. The write position ('end' field)
will be updated accordingly. Each byte will be put in its
HEX form into the buffer (%02x).
Data will be copied, you can free() the given pointer after copying..
\param[in] b The Buffer object.
\param[in] data Arbitrary data to add as hex into the Buffer.
\param[in] len The size of the data to add in Bytes.
*/
void buffer_add_hex(Buffer *b, void *data, size_t len);
/* resize the buffer if necessary, used internally only */
void buffer_resize(Buffer *b, size_t len);
/** Tell if there are no more bytes to read.
This functions tells if the EOF of the buffer is reached
during read operations (no more data to read left).
\param[in] b The Buffer object.
\return Returns 1 of EOF has been reached or 0 if there are more data left to read.
*/
int buffer_done(Buffer *b);
/** Read some chunk of data from the Buffer.
Read some chunk of data from the Buffer, starting from current read
offset til len.
Example: suppose you've got a buffer with the following content:
@code
AAAABBBBCCCC
@endcode
Then the following code would:
@code
byte g[4];
buffer_get_chunk(b, g, 4); // => g now contains 'AAAA'
buffer_get_chunk(b, g, 4); // => g now contains 'BBBB'
buffer_get_chunk(b, g, 4); // => g now contains 'CCCC'
@endcode
In order to catch buffer overflow, check the return value, which will
be 0 in case of errors. See also: fatals_ifany(), buffer_done() and buffer_left().
\param[in] b The Buffer object to read from.
\param[out] buf The destination pointer where the data will be copied to. This pointer must be allocated by the caller properly and it must have at least a size of len.
\param[in] len The number of bytes to read from the Buffer.
\return Returns the size of bytes read, 0 in case an error occurred.
*/
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len);
/** Read some chunk of data from the Buffer and add to another Buffer.
Works identical to buffer_get_chunk() but copies the requested
chunk directly into the Buffer \a dst, which will be resized
properly if needed.
\param[in] b The Buffer object to read from.
\param[out] dst The Buffer object to write to.
\param[in] len The number of bytes to read from the Buffer.
\return Returns the size of bytes read, 0 in case an error occurred.
*/
size_t buffer_get_chunk_tobuf(Buffer *b, Buffer *dst, size_t len);
/** Read the whole Buffer content.
This function returns the whole buffer contents as a pointer
to the internal data member (Buffer->buf). The returned pointer
is allocated and filled with data up to buffer_size(Buffer),
however, the allocated memory might be more than size, in fact
it will be a multitude of Buffer-blocksize.
Don't free() the pointer directly, use buffer_free() always.
\param[in] b The Buffer object to read from.
\return Pointer to the buffer data storage.
*/
byte *buffer_get(Buffer *b);
/** Read the whole Buffer content as string.
Access the Buffer content as string (char *).
The returned pointer
is allocated and filled with data up to buffer_size(Buffer),
however, the allocated memory might be more than size, in fact
it will be a multitude of Buffer-blocksize.
The byte after buffer_size(Buffer) will be a \0.
Don't free() the pointer directly, use buffer_free() always.
Sample usage:
@code
[..]
fprintf(stdout, "Our buffer content: %s\n", buffer_get_str(b));
@endcode
\param[in] b The Buffer object to read from.
\return Pointer to the buffer data storage.
*/
char *buffer_get_str(Buffer *b);
/** Read the remaining data after current read offset.
Fetch whatever is left in the buffer. This works like
buffer_get() but instead doesn't return everything,
but only the part of the buffer, which follows after
the current read offset.
The returned pointer will be allocated by buffer_get_remainder()
with a size of buffer_left(). It's up to the caller to free()
the returned pointer later on.
Example: suppose you've got a buffer with the following content:
@code
AAAABBBBCCCC
@endcode
Then:
@code
[..]
byte g[4];
byte *r = NULL;
buffer_get_chunk(b, g, 4); // => g now contains 'AAAA'
size_t rs = buffer_left(b); // => rs = 8
r = buffer_get_remainder(b); // => r now contains 'BBBBCCCC' and has a size of 8
memset(r, 0, rs); // zerofill r
free(r); // done with it
@endcode
\param[in] b The Buffer object to read from.
\return Pointer to the remaining chunk of data (copy).
*/
byte *buffer_get_remainder(Buffer *b);
/** Read some data inside the Buffer.
Same as buffer_get() but fetch some data chunk from somewhere
in the middle of the buffer.
The returned pointer has to be allocated by the caller to
at least a size of len bytes.
The read offset will be left untouched by this function.
Example: suppose you've got a buffer with the following content:
@code
AAAABBBBCCCC
@endcode
Then:
@code
[..]
byte g[4];
buffer_extract(b, g, 4, 4); // => g now contains 'BBBB'
@endcode
\param[in] b The Buffer object to read from.
\param[out] buf The buffer to copy data to.
\param[in] offset Where to start copying.
\param[in] len How mush data to copy.
\return Returns the size of bytes read. Returns 0 in case of
an overflow, which can be catched with fatals_ifany().
*/
size_t buffer_extract(Buffer *b, void *buf, size_t offset, size_t len);
/** Forward read offset of given buffer. Use to ignore a couple of bytes.
\param[in] b The Buffer object to read from.
\param[in] fwdby Bytes to forward read offset.
\return Returns the size of bytes forwarded. Returns 0 in case of
an overflow, which can be catched with fatals_ifany().
*/
size_t buffer_fwd_offset(Buffer *b, size_t fwdby);
/** Dump the Buffer contents to stderr in hex form.
\param[in] b The Buffer object to dump.
*/
void buffer_dump(const Buffer *b);
/** Print Buffer counters to stderr.
\param[in] b The Buffer object to print infos about.
*/
void buffer_info(const Buffer *b);
/** Tell how much data there is in the buffer available.
This function returns the number of bytes stored in the
buffer so far. Please note, that the actual allocation might
be bigger, because we always allocate memory blockwise.
\param[in] b The Buffer object to get the size from.
\return The number of bytes stored in the Buffer.
*/
size_t buffer_size(const Buffer *b);
/** Tell how much data is left to read in the Buffer.
Use this function to check if it's ok to read more
bytes from to buffer to avoid buffer overflows.
Example: suppose you've got a buffer with the following content:
@code
AAAABBBBCCCC
@endcode
Then:
@code
[..]
byte g[4];
byte x[16];
buffer_get_chunk(b, g, 4); // => g now contains 'BBBB'
if(buffer_left(b) >= 16) // => will return 8 and therefore fail
buffer_get_chunk(b, x, 16);
else
printf("not enough data"); // => will be printed
@endcode
\param[in] b The Buffer object to get the size from.
\return The number of bytes left to read from the Buffer.
*/
size_t buffer_left(const Buffer *b);
/** Read 1 byte (8 bit) number from a Buffer.
\param[in] b The Buffer object to read from.
\return a uint8_t.
*/
uint8_t buffer_get8(Buffer *b);
/** Read 2 bytes (16 bit) number from a Buffer.
\param[in] b The Buffer object to read from.
\return a uint16_t.
*/
uint16_t buffer_get16(Buffer *b);
/** Read 4 byte (32 bit) number from a Buffer.
\param[in] b The Buffer object to read from.
\return a uint32_t.
*/
uint32_t buffer_get32(Buffer *b);
/** Read 8 byte (64 bit) from a Buffer.
\param[in] b The Buffer object to read from.
\return a uint64_t.
*/
uint64_t buffer_get64(Buffer *b);
/** Read 2 bytes (16 bit) number from a Buffer, converted to host endian.
\param[in] b The Buffer object to read from.
\return a uint16_t.
*/
uint16_t buffer_get16na(Buffer *b);
/** Read 4 byte (32 bit) number from a Buffer, converted to host endian.
\param[in] b The Buffer object to read from.
\return a uint32_t.
*/
uint32_t buffer_get32na(Buffer *b);
/** Read 8 byte (64 bit) from a Buffer, converted to host endian.
\param[in] b The Buffer object to read from.
\return a uint64_t.
*/
uint64_t buffer_get64na(Buffer *b);
/** Read the last 1 byte (8 bit) number from a Buffer.
Doesn't increment offset.
\param[in] b The Buffer object to read from.
\return a uint8_t.
*/
uint8_t buffer_last8(Buffer *b);
/** Read the last 2 byte (16 bit) number from a Buffer.
Doesn't increment offset.
\param[in] b The Buffer object to read from.
\return a uint16_t.
*/
uint16_t buffer_last16(Buffer *b);
/** Read the last 4 byte (32 bit) number from a Buffer.
Doesn't increment offset.
\param[in] b The Buffer object to read from.
\return a uint32_t.
*/
uint32_t buffer_last32(Buffer *b);
/** Read the last 8 byte (64 bit) number from a Buffer.
Doesn't increment offset.
\param[in] b The Buffer object to read from.
\return a uint64_t.
*/
uint64_t buffer_last64(Buffer *b);
/** Read data from a file directly into a Buffer.
This function reads in len bytes from the FILE stream
'in' into the Buffer. The file must already be opened
by the caller.
\param[in,out] b The Buffer object to read from.
\param[in] in The FILE stream to read from.
\param[in] len The number of bytes to read.
\return Returns the number of bytes read or 0 in case of an error or EOF.
Use feof() and ferror() to check this afterwards.
*/
size_t buffer_fd_read(Buffer *b, FILE *in, size_t len);
/** Write a 1 byte (8 bit) number in binary form into the buffer.
\param[out] b The Buffer object to write to.
\param[in] v The uint8_t to write to the buffer.
*/
void buffer_add8(Buffer *b, uint8_t v);
/** Write a 2 byte (16 bit) number in binary form into the buffer.
\param[out] b The Buffer object to write to.
\param[in] v The uint16_t to write to the buffer.
*/
void buffer_add16(Buffer *b, uint16_t v);
/** Write a 4 byte (32 bit) number in binary form into the buffer.
\param[out] b The Buffer object to write to.
\param[in] v The uint32_t to write to the buffer.
*/
void buffer_add32(Buffer *b, uint32_t v);
/** Write a 8 byte (64 bit) number in binary form into the buffer.
\param[out] b The Buffer object to write to.
\param[in] v The uint64_t to write to the buffer.
*/
void buffer_add64(Buffer *b, uint64_t v);
/** Write a 2 byte (16 bit) number in binary form into the buffer, converted to big endian.
\param[out] b The Buffer object to write to.
\param[in] v The uint16_t to write to the buffer.
*/
void buffer_add16be(Buffer *b, uint16_t v);
/** Write a 4 byte (32 bit) number in binary form into the buffer, converted to big endian.
\param[out] b The Buffer object to write to.
\param[in] v The uint32_t to write to the buffer.
*/
void buffer_add32be(Buffer *b, uint32_t v);
/** Write a 8 byte (64 bit) number in binary form into the buffer, converted to big endian.
\param[out] b The Buffer object to write to.
\param[in] v The uint64_t to write to the buffer.
*/
void buffer_add64be(Buffer *b, uint64_t v);
#endif // HAVE_PCP_BUFFER_H
/**@}*/

View File

@@ -0,0 +1,182 @@
/* include/pcp/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the `arc4random' function. */
#undef HAVE_ARC4RANDOM
/* Define to 1 if you have the `arc4random_buf' function. */
#undef HAVE_ARC4RANDOM_BUF
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
/* Define to 1 if you have the `fopen' function. */
#undef HAVE_FOPEN
/* Define to 1 if you have the `fprintf' function. */
#undef HAVE_FPRINTF
/* Define to 1 if you have the `fread' function. */
#undef HAVE_FREAD
/* Define to 1 if you have the `free' function. */
#undef HAVE_FREE
/* Define to 1 if you have the `fseek' function. */
#undef HAVE_FSEEK
/* Define to 1 if you have the `ftruncate' function. */
#undef HAVE_FTRUNCATE
/* Define to 1 if you have the `fwrite' function. */
#undef HAVE_FWRITE
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getopt_long' function. */
#undef HAVE_GETOPT_LONG
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `isatty' function. */
#undef HAVE_ISATTY
/* Define to 1 if you have the `sodium' library (-lsodium). */
#undef HAVE_LIBSODIUM
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the `malloc' function. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the `perror' function. */
#undef HAVE_PERROR
/* Define to 1 if you have the `posix_memalign' function. */
#undef HAVE_POSIX_MEMALIGN
/* Define to 1 if you have the `setrlimit' function. */
#undef HAVE_SETRLIMIT
/* Define to 1 if you have the `sizeof' function. */
#undef HAVE_SIZEOF
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlen' function. */
#undef HAVE_STRLEN
/* Define to 1 if you have the `strnlen' function. */
#undef HAVE_STRNLEN
/* Define to 1 if you have the `strnstr' function. */
#undef HAVE_STRNSTR
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the `tcgetattr' function. */
#undef HAVE_TCGETATTR
/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define to 1 if you have the `towlower' function. */
#undef HAVE_TOWLOWER
/* Define to 1 if you have the `umask' function. */
#undef HAVE_UMASK
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the <wctype.h> header file. */
#undef HAVE_WCTYPE_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View File

@@ -0,0 +1,96 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_CONTEXT_H
#define _HAVE_PCP_CONTEXT_H
#include "defines.h"
#include "platform.h"
#include "uthash.h"
#include "structs.h"
#include "mem.h"
#include "keyhash.h"
/**
* \defgroup CONTEXT CONTEXT
* @{
A couple of context functions to catch errors and display them.
The context also holds the key hashes.
*/
/** Create a new PCP Context.
Sets all context pointers to NULL.
\return the context object.
*/
PCPCTX *ptx_new();
/** Frees the memory allocated by the context.
\param[in] ptx PCP Context object.
*/
void ptx_clean(PCPCTX *ptx);
/** Set an error message.
This function gets a printf() like error message,
which it stores in the global PCP_ERR variable
and sets PCP_ERRSET to 1.
\param[in] ptx PCP Context object.
\param[in] fmt printf() like format description.
\param[in] ... format parameters, if any.
*/
void fatal(PCPCTX *ptx, const char * fmt, ...);
/** Prints error messages to STDERR, if there are some.
FIXME: add something like this which returns the
message.
\param[in] ptx PCP Context object.
*/
void fatals_ifany(PCPCTX *ptx);
/** Reset the error variables.
This can be used to ignore previous errors.
Use with care.
\param[in] ptx PCP Context object.
*/
void fatals_reset(PCPCTX *ptx);
/* same as fatal() but dies immediately */
void final(const char * fmt, ...);
void ptx_dump(PCPCTX *ptx);
#endif // _HAVE_PCP_CONTEXT_H

354
libpcp/include/pcp/crypto.h Normal file
View File

@@ -0,0 +1,354 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2016 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_PCP_CRYPTO_H
#define _HAVE_PCP_CRYPTO_H
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <sodium.h>
#include <stdlib.h>
#include "defines.h"
#include "mem.h"
#include "key.h"
#include "keyhash.h"
#include "ed.h"
#include "pcpstream.h"
#include "context.h"
/**
\defgroup CRYPTO CRYPTO
@{
Functions for symmetrical or asymmetrical encryption using NaCL.
\section intro Introduction
Encryption is done 32k blockwise using an ephemeral key.
If using asymmetrical encryption the ephemeral key is encrypted
asymmetrically using Curve25519 for all recipients and added to
the output.
If sign+crypt is requested, a hash of the clear content plus
the recipient list will be made and signed. That signature
will be encrypted using the ephemeral key as well and appended
to the output.
For each encryption cycle (per block) a unique nonce will be
used.
\section format Encrypted Output Format
Encrypted output will always written as binary files. No armoring
supported yet. The encryption process works as this:
- generate a random symetric 32 byte key B<S>
- encrypt it asymetrically for each recipient using a unique nonce (B<R>)
- encrypt the input file 32k blockwise using the symetric key
Symmetric encryption works the very same with the recipient stuff
left out.
Formal format description, asymmetric encrypted files:
+---------------------------------------------------------+
| Field Size Description |
+-------------+--------+----------------------------------+
| Type | 1 | Filetype, 5=ASYM, 23=SYM |
+-------------|--------|----------------------------------+
| Len R | 4 | Number of recipients (*) |
+-------------|--------|----------------------------------+
| Recipients | R*72 | C(recipient)|C(recipient)... (*) |
+-------------|--------|----------------------------------+
| Encrypted | ~ | The actual encrypted data |
+-------------|--------|----------------------------------+
The following will be Left out when doing symetric encryption.
Recipient field format:
+---------------------------------------------------------+
| Field Size Description |
+-------------+--------+----------------------------------+
| Nonce | 24 | Random Nonce, one per R |
+-------------|--------|----------------------------------+
| Cipher | 48 | S encrypted with PK or R |
+-------------|--------|----------------------------------+
R is calculated using public key encryption using the senders
secret key, the recipients public key and a random nonce.
Pseudocode:
@code
R = foreach P: N | crypto_box(S, N, P, SK)
L = len(R)
T = 5
write (T | L | R)
foreach I: write (N | crypto_secret_box(I, N, S))
@endcode
where P is the public key of a recipient, SK is the senders
secret key, R is the recipient list, L is the number of recipients,
T is the filetype header, I is a block of input with a size
of 32k, N is a nonce (new per block) and S the symmetric key.
*/
/** Asymmetrically encrypt a message.
This function is used internally and normally a user doesn't
need to use it. However, from time to time there maybe the
requirement to work with raw NaCL crypto_box() output. This
function adds the neccessary padding and it uses PCP key structures.
\param[in] ptx pcp context.
\param[in] secret The secret key structure from the sender.
\param[in] pub The public key structure from the recipient.
\param[in] message The clear unencrypted message.
\param[in] messagesize The size in bytes of the message.
\param[out] csize A pointer which will be set to the size of the encrypted result if successful.
\return Returns an allocated byte array of the size csize which contains the encrypted result.
In case of an error, it returns NULL sets csize to 0. Use fatals_ifany() to check for errors.
*/
byte *pcp_box_encrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *message, size_t messagesize,
size_t *csize);
/** Asymmetrically decrypt a message.
This function is used internally and normally a user doesn't
need to use it. However, from time to time there maybe the
requirement to work with raw NaCL crypto_box() output. This
function adds the neccessary padding and it uses PCP key structures.
\param[in] ptx pcp context.
\param[in] secret The secret key structure from the sender.
\param[in] pub The public key structure from the recipient.
\param[in] cipher The encrypted message.
\param[in] ciphersize The size in bytes of the encrypted message.
\param[out] dsize A pointer which will be set to the size of the decrypted result if successful.
\return Returns an allocated byte array of the size csize which contains the encrypted result.
In case of an error, it returns NULL sets csize to 0. Use fatals_ifany() to check for errors.
*/
byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
byte *cipher, size_t ciphersize,
size_t *dsize);
/** Asymmetrically encrypt a file or a buffer stream.
This function encrypts a stream 32k-blockwise for
a number of recipients.
Calls pcp_encrypt_stream_sym() after assembling the encrypted recipient list.
\param[in] ptx pcp context.
\param[in] in Stream to read the data to encrypt from.
\param[out] out Stream to write encrypted result to.
\param[in] s Secret key structure of the sender for encryption.
\param[in] s Secret key structure of the sender for signing.
\param[in] p Public key hash containing a list of the recipients.
\param[in] signcrypt Flag to indicate sign+crypt. If 1 it adds a signature, otherwise not.
\param[in] anon Flag to indicate if using anonymous sender key. 0 retains std behaviour, not anon.
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s,
pcp_key_t *ss, pcp_pubkey_t *p, int signcrypt, int anon);
/** Symmetrically encrypt a file or a buffer stream.
This function encrypts a stream 32k-blockwise using
a given ephemeral key. Usually compute this key using the pcp_scrypt()
function.
Uses crypto_secret_box() for each 32k-block with a random nonce for each.
\param[in] ptx pcp context.
\param[in] in Stream to read the data to encrypt from.
\param[out] out Stream to write encrypted result to.
\param[in] symkey Ephemeral key to use for encryption.
\param[in] havehead Flag to indicate if the file header has already been written.
Set to 0 if you call this function directly in order to do symmetrical encryption.
\param recsign Recipient list, set this to NULL if you call this function directly.
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *symkey, int havehead, pcp_rec_t *recsign);
/** Asymmetrically decrypt a file or a buffer stream.
This function decrypts a stream 32k+16-blockwise for
a number of recipients.
Calls pcp_decrypt_stream_sym() after assembling the encrypted recipient list.
FIXME: should return the pcp_rec_t structure upon successfull verification somehow.
\param[in] ptx pcp context.
\param[in] in Stream to read the data to decrypt from.
\param[out] out Stream to write decrypted result to.
\param[in] s Secret key structure of the recipient.
\param[in] symkey Ephemeral key for symmetric decryption. Set to NULL if you call this function directly.
\param verify Flag to indicate sign+crypt. If 1 it tries to verify a signature, otherwise not.
\param[in] anon Flag to indicate if using anonymous sender key. 0 retains std behaviour, not anon.
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify, int anon);
/** Symmetrically decrypt a file or a buffer stream.
This function decrypts a stream 32k+16-blockwise using
a given ephemeral key. Usually compute this key using the pcp_scrypt()
function. If not called directly, the key have been extracted from
the recipient list.
Uses crypto_secret_box_open() for each 32k+16-block with a random nonce for each.
\param[in] ptx pcp context.
\param[in] in Stream to read the data to decrypt from.
\param[out] out Stream to write decrypted result to.
\param[in] symkey Ephemeral key to use for decryption.
\param recverify Flag to indicate sign+crypt. If 1 it tries to verify a signature, otherwise not.
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
size_t pcp_decrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *symkey, pcp_rec_t *recverify);
/** Symmetrically encrypt a message.
This function encrypts a message symmetrically
using crypto_secretbox() using the given Curve25519 raw
secret key and the nonce.
It allocates apropriate memory for the result,
which will be stored in \a cipher.
\param[out] cipher Encrypted result.
\param[in] cleartext Clear message.
\param[in] clearsize Size of message.
\param[in] nonce A random nonce (24 Bytes).
\param[in] key A Curve25519 key (32 Bytes).
\return Returns the size of \a cipher.
*/
size_t pcp_sodium_mac(byte **cipher,
byte *cleartext,
size_t clearsize,
byte *nonce,
byte *key);
/** Decrypt a symmetrically encrypted message.
This function decrypts a symmetrically encrypted message
using crypto_secretbox_open() using the given Curve25519 raw
secret key and the nonce.
It allocates apropriate memory for the result,
which will be stored in \a cleartext.
\param[out] cleartext The decrypted result.
\param[in] message The encrypted message.
\param[in] messagesize Size of message.
\param[in] nonce A random nonce (24 Bytes).
\param[in] key A Curve25519 key (32 Bytes).
\return Returns 0 in case of success of -1 in case of an error. Check fatals_if_any().
*/
int pcp_sodium_verify_mac(byte **cleartext,
byte* message,
size_t messagesize,
byte *nonce,
byte *key);
/** Create a blake2 checksum of an input stream.
\param[in] ptx pcp context.
\param[in] in stream to read data from.
\param[out] checksum output buffer containing resulting checksum.
\return Returns 0 on error.
*/
int pcp_checksum(PCPCTX *ptx, Pcpstream *in, byte *checksum, byte *key, size_t keylen);
pcp_rec_t *pcp_rec_new(byte *cipher, size_t clen, pcp_key_t *secret, pcp_pubkey_t *pub);
void pcp_rec_free(pcp_rec_t *r);
/* CTR mode helpers */
byte *_gen_ctr_nonce(uint64_t ctr);
uint64_t _get_nonce_ctr(byte *nonce);
#endif /* _HAVE_PCP_CRYPTO_H */
/**@}*/

View File

@@ -0,0 +1,185 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _DEFINES_H
#define _DEFINES_H
/** \mainpage
\section intro_sec Introduction
This is the API documentation of libpcp, the library behind
<a href="/PrettyCurvedPrivacy">Pretty Curved Privacy (pcp)</a>.
The library can be used independently
of pcp to manage keys and to encrypt or sign files or buffers.
For most actual crypto related things, libpcp uses
<a href="https://github.com/jedisct1/libsodium">libsodium, the portable NaCL library</a>.
\section sample_sec Sample usage
Example use of the libpcp library:
\include tests/sample.c
To compile the example, use the following commands:
@code
g++ -c sample.o `pkg-config --cflags libpcp1`
g++ sample.o `pkg-config --libs libpcp1` -o sample
@endcode
*/
#include "config.h"
typedef unsigned char byte; /* Single unsigned byte = 8 bits */
typedef unsigned short dbyte; /* Double byte = 16 bits */
typedef unsigned int qbyte; /* Quad byte = 32 bits */
/* key stuff, deprecated. */
#define PCP_ENFILE_HEADER "----- BEGIN PCP ENCRYPTED FILE -----\r\n"
#define PCP_ENFILE_FOOTER "\r\n----- END PCP ENCRYPTED FILE -----\r\n"
#define PCP_ZFILE_HEADER "----- BEGIN Z85 ENCODED FILE -----"
#define PCP_ZFILE_FOOTER "----- END Z85 ENCODED FILE -----"
#define PCP_SIG_HEADER "----- BEGIN ED25519 SIGNED MESSAGE -----"
#define PCP_SIG_START "----- BEGIN ED25519 SIGNATURE -----"
#define PCP_SIG_END "----- END ED25519 SIGNATURE -----"
#define PCP_SIGPREFIX "\nnacl-"
#define PCP_ME "Pretty Curved Privacy"
#define PCP_KEY_VERSION 6
typedef enum _ZBEGINS {
PCP_ENCRYPTED_FILE,
Z85_ENCODED_FILE,
ED25519_SIGNED_MESSAGE,
ED25519_SIGNATURE,
ED25519_CURVE29915_PUBLIC_KEY,
ED25519_CURVE29915_PRIVATE_KEY,
} ZBEGINS;
/**
\addtogroup KEYS
@{
*/
/** \enum _PCP_KEY_TYPES
Internal key types.
*/
typedef enum _PCP_KEY_TYPES {
PCP_KEY_TYPE_MAINSECRET = 1, /**< 1 - Primary secret */
PCP_KEY_TYPE_SECRET = 2, /**< 2 - Other secret */
PCP_KEY_TYPE_PUBLIC = 3, /**< 3 - Public */
PCP_KEYSIG_NATIVE = 4, /**< 4 - PCP native key signature */
PCP_KEYSIG_PBP = 5 /**< 5 - PBP key signature */
} PCP_KEY_TYPES;
/** @}
*/
/* shortcuts for key lengths and stuff to save typing */
#define LEDPUB crypto_sign_PUBLICKEYBYTES
#define LEDSEC crypto_sign_SECRETKEYBYTES
#define LBOXPUB crypto_box_PUBLICKEYBYTES
#define LBOXSEC crypto_box_SECRETKEYBYTES
#define LNONCE crypto_secretbox_NONCEBYTES
#define LMAC crypto_secretbox_MACBYTES
#define LSEC LBOXSEC + LEDSEC + LEDSEC + crypto_secretbox_MACBYTES
#define LSHA 32 /* sha256 hash length */
#define LHASH crypto_generichash_BYTES_MAX
#define LSIG crypto_sign_BYTES
/* vault id */
#define PCP_VAULT_ID 14
#define PCP_VAULT_VERSION 2
/* sigs */
#define PCP_SIG_VERSION 2
/* crypto file format stuff */
#define PCP_ASYM_CIPHER 5
#define PCP_ASYM_CIPHER_ANON 6
#define PCP_ASYM_CIPHER_ANON_SIG 7
#define PCP_SYM_CIPHER 23
#define PCP_ASYM_CIPHER_SIG 24
#define PCP_BLOCK_SIZE 32 * 1024
//#define PCP_CRYPTO_ADD (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
#define PCP_BLOCK_SIZE_IN (PCP_BLOCK_SIZE) + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES
#define PCP_ASYM_RECIPIENT_SIZE crypto_secretbox_KEYBYTES + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES
/* #define PCP_ASYM_ADD_SENDER_PUB */
/* used for self encryption only */
#define PBP_COMPAT_SALT "qa~t](84z<1t<1oz:ik.@IRNyhG=8q(on9}4#!/_h#a7wqK{Nt$T?W>,mt8NqYq&6U<GB1$,<$j>,rSYI2GRDd:Bcm"
#define PCP_RFC_CIPHER 0x21 /* curve25519+ed25519+poly1305+salsa20+blake2 */
/* defines for key management (mgmt.c) */
#define EXP_PK_CIPHER 0x21
#define EXP_PK_CIPHER_NAME "CURVE25519-ED25519-POLY1305-SALSA20"
#define EXP_HASH_CIPHER 0x22
#define EXP_HASH_NAME "BLAKE2"
#define EXP_SIG_CIPHER 0x23
#define EXP_SIG_CIPHER_NAME "ED25519"
#define EXP_SIG_VERSION 0x01
#define EXP_SIG_TYPE 0x1F /* self signed */
/* sig sub notiation we support */
#define EXP_SIG_SUB_CTIME 2
#define EXP_SIG_SUB_SIGEXPIRE 3
#define EXP_SIG_SUB_KEYEXPIRE 9
#define EXP_SIG_SUB_NOTATION 20
#define EXP_SIG_SUB_KEYFLAGS 27
/* in armored mode, we're using the usual head+foot */
#define EXP_PK_HEADER "----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----"
#define EXP_PK_FOOTER "----- END ED25519-CURVE29915 PUBLIC KEY -----"
#define EXP_SK_HEADER "----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----"
#define EXP_SK_FOOTER "----- END ED25519-CURVE29915 PRIVATE KEY -----"
/* pubkey export formats */
#define EXP_FORMAT_NATIVE 1
#define EXP_FORMAT_PBP 2
#endif /* _DEFINES_H */
/**@}*/

202
libpcp/include/pcp/ed.h Normal file
View File

@@ -0,0 +1,202 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_ED_H
#define _HAVE_PCP_ED_H
/** \defgroup ED SIGNING
@{
ED25519 signature functions.
*/
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include "defines.h"
#include "platform.h"
#include "mem.h"
#include "key.h"
#include "keyhash.h"
#include "util.h"
#include "pcpstream.h"
#include "context.h"
/** Sign a raw message.
Sign a message of messagesize using s->edsecret.
This is just a convenience wrapper around crypto_sign().
\param[in] message The message to sign.
\param[in] messagesize Size of the message.
\param[in] s Pointer to secret key structure.
\return Returns message+signature with size of messagesize + crypto_sign_BYTES,
or NULL in case of an error.
*/
byte *pcp_ed_sign(byte *message, size_t messagesize, pcp_key_t *s);
/** Sign a raw message using s->mastersecret.
The same as pcp_ed_sign() but uses the mastersecret for signing.
Usually used for key signing only.
\param[in] message The message to sign.
\param[in] messagesize Size of the message.
\param[in] s Pointer to secret key structure.
\return Returns message+signature with size of messagesize + crypto_sign_BYTES,
or NULL in case of an error.
*/byte *pcp_ed_sign_key(byte *message, size_t messagesize, pcp_key_t *s);
/** Verify a signature.
Verify a signature of size siglen using p->edpub.
The signature must contain the message+nacl signature (with size crypto_sign_BYTES).
\param[in] ptx pcp context.
\param[in] signature Message+signature.
\param[in] siglen Size of message+signature.
\param[in] p Pointer to public key structure.
\return If the signature verifies return the raw message with the signature removed (size: siglen - crypto_sign_BYTES),
returns NULL in case of errors. Check fatals_if_any().
*/
byte *pcp_ed_verify(PCPCTX *ptx, byte *signature, size_t siglen, pcp_pubkey_t *p);
/** Verify a signature using the mastersecret.
Verify a signature of size siglen using p->masterpub.
The signature must contain the message+nacl signature (with size crypto_sign_BYTES).
\param[in] ptx pcp context.
\param[in] signature Message+signature.
\param[in] siglen Size of message+signature.
\param[in] p Pointer to public key structure.
\return If the signature verifies return the raw message with the signature removed (size: siglen - crypto_sign_BYTES),
returns NULL in case of errors. Check fatals_if_any().
*/
byte *pcp_ed_verify_key(PCPCTX *ptx, byte *signature, size_t siglen, pcp_pubkey_t *p);
/** Sign a stream in 32k block mode.
This function reads blockwise from the stream \a in and generates a hash
of the contents of the stream. It outputs the stream to \a out, also blockwise
and appends the signature afterwards, which consists of the hash+nacl-signature.
\param[in] ptx pcp context.
\param[in] in Stream to read from.
\param[out] out Stream to write to.
\param[in] s Pointer to secret key.
\param[in] z85 Flag which indicates if to create an armored signature or not. 1=armored, 0=raw.
\return Returns the number of bytes written to the output stream.
*/
size_t pcp_ed_sign_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t *s, int z85);
/** Verify a signature from a stream in 32k block mode.
This function reads blockwise from the stream \a in and generates a hash
of the contents of the stream. While reading from the stream it extracts
the appended signature (hash+sig). It then verifies the signature using
p->edpub and compares the signature hash with the hash it calculated
from the signed content.
The parameter \a p can be NULL. In this case the function loops through
the global public key hash pcppubkey_hash to find a public key which is able to verify
the signature.
\param[in] ptx pcp context.
\param[in] in Stream to read from.
\param[in] p Pointer to public key structure.
\return Returns a pointer to a public key which were used to verify the signature or NULL if
an error occurred. Check fatals_if_any().
*/
pcp_pubkey_t *pcp_ed_verify_buffered(PCPCTX *ptx, Pcpstream *in, pcp_pubkey_t *p);
/** Generate a detached signature from a stream in 32k block mode.
This function reads blockwise from the stream \a in and generates a hash
of the contents of the stream. It then signs that hash and writes the
hash and the signature to the output stream \a out.
\param[in] in Stream to read from.
\param[out] out Stream to write to.
\param[in] s Pointer to secret key.
\return Returns the size of the detached signature written or 0 in case of errors. Check fatals_if_any().
*/
size_t pcp_ed_detachsign_buffered(Pcpstream *in, Pcpstream *out, pcp_key_t *s);
/** Verify a detached signature from a stream in 32k block mode.
This function reads blockwise from the stream \a in and generates a hash
of the contents of the stream. It then reads the signature from the stream
\a sigfd and verifies the signature from it using p->edpub and compares
the signature hash with the hash it calculated
from the signed content.
\param[in] ptx pcp context.
\param[in] in Stream to read from.
\param[in] sigfd Stream containing the detached signature.
\param[in] p Pointer to public key structure.
\return Returns a pointer to a public key which were used to verify the signature or NULL if
an error occurred. Check fatals_if_any().
*/
pcp_pubkey_t *pcp_ed_detachverify_buffered(PCPCTX *ptx, Pcpstream *in, Pcpstream *sigfd, pcp_pubkey_t *p);
#endif /* _HAVE_PCP_ED_H */
/**@}*/

View File

@@ -0,0 +1,22 @@
#ifndef _HAVE_PCP_GETPASS
#define _HAVE_PCP_GETPASS
/*
* (unportable) functions to turn on/off terminal echo
* using termios functions. might compile however on
* most unices, tested on FreeBSD only.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
void pcp_echo_off();
void pcp_echo_on();
char *pcp_get_stdin();
char *pcp_get_passphrase(char *prompt);
#endif /* _HAVE_PCP_GETPASS */

View File

@@ -0,0 +1,25 @@
#ifndef _HAVE_JENHASH_H
#define _HAVE_JENHASH_H
/* Bob Jenkins 32bit hash function */
/* via: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define jen_mix(a,b,c) \
{ \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
}
#define JEN_PSALT 0xD9A03
#define JEN_SSALT 0xC503B
unsigned jen_hash ( unsigned char *k, unsigned length, unsigned initval );
#endif /* _HAVE_JENHASH_H */

324
libpcp/include/pcp/key.h Normal file
View File

@@ -0,0 +1,324 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_KEYPAIR_H
#define _HAVE_PCP_KEYPAIR_H
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include "defines.h"
#include "platform.h"
#include "mem.h"
#include "crypto.h"
#include "randomart.h"
#include "version.h"
#include "uthash.h"
#include "jenhash.h"
#include "structs.h"
#include "buffer.h"
#include "keysig.h"
#include "scrypt.h"
/**
* \defgroup KEYS KEYS
* @{
PCP public and secret key functions.
Functions to generate PCP keypairs, de- and encrypt them
and various related helpers.
*/
#define PCP_RAW_KEYSIZE sizeof(pcp_key_t) - sizeof(UT_hash_handle)
#define PCP_RAW_PUBKEYSIZE sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle)
/** Generate a new key structure.
Owner and mail field must be filled by the caller.
Memory for the returned pointer will be allocated
by the function.
\return Returns pointer to new pcp_key_t structure.
*/
pcp_key_t *pcpkey_new ();
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk);
/** Generate an ASCII art image of the public key.
This functions originally appeared in OpenSSH rev 1.70,
comitted by Alexander von Gernler, published under the
BSD license.
Human beings are bad at memorizing numbers, especially
large numbers, but we are very good at recognizing images.
This function calculates an ascii art image of a public
key, which the user shall always see, when used. If the
image changes, the user would immediately recognize the
change, even unconsciously.
Sample random art image from the following public key:
@code
c308455ed4cf0c140bf48bfb0d87c4999c66e823bbe74ff16e2a9adc8e770747
+----------------+
| .o.ooo. |
| o . o |
| . . = |
| . o + |
| . + |
| . |
| |
| |
+----------------+
@endcode
\param[in] k The public key structure.
\return Returns an allocated char pointer containing the ASCII art image.
The caller is responsible to free() it.
*/
char *pcppubkey_get_art(pcp_pubkey_t *k);
/** Generate an ASCII art image of the public key part of a secret key.
see pcppubkey_get_art() for details.
\param[in] k The secret key structure.
\return Returns an allocated char pointer containing the ASCII art image.
The caller is responsible to free() it.
*/
char *pcpkey_get_art(pcp_key_t *k);
/** Encrypt a secret key structure.
The given passphrase will be used to calculate an encryption
key using the scrypt() function.
The secret keys will be concatenated and encrypted, the result
will be put into the 'encrypted' field. The first byte of each
secret key field will be set to 0 to indicate the key is encrypted.
The data structure will be modified directly, no new memory
will be allocated.
The caller is responsible to clear the passphrase right after
use and free() it as soon as possible.
\param[in] ptx pcp context.
\param[in,out] key The secret key structure.
\param[in] passphrase The passphrase used to encrypt the key.
\return Returns a pointer to the encrypted key structure or NULL
in case of an error. Use fatals_ifany() to catch them.
*/
pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase);
/** Decrypt a secret key structure.
The given passphrase will be used to calculate an encryption
key using the scrypt() function.
The encryption key will be used to decrypt the 'encrypted'
field of the structure. If it works, the result will be dissected
and put into the correspondig secret key fields.
The data structure will be modified directly, no new memory
will be allocated.
The caller is responsible to clear the passphrase right after
use and free() it as soon as possible.
\param[in] ptx pcp context.
\param[in,out] key The secret key structure.
\param[in] passphrase The passphrase used to decrypt the key.
\return Returns a pointer to the decrypted key structure or NULL
in case of an error. Use fatals_ifany() to catch them.
*/
pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase);
/** Generate a public key structure from a given secret key structure.
This function extracts all required fields and fills a newly
allocated pcp_pubkey_t structure.
The caller is responsible to clear and free() it after use.
\param[in] key The secret key structure.
\return Returns a new pcp_pubkey_t structure.
*/
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key);
/** Calculate a key-id from public key fields.
This function calculates 2 JEN Hashes: one from the 'pub'
field and one from the 'edpub' field. It the puts them
together into a newly allocated char pointer of 17 bytes
length as hex, terminated with a 0.
The key-id is supposed to be collision save, but there's
no guarantee. However, it's used locally only, it wont be
transmitted over the network and it's not part of any exported
packet.
\param[in] k The secret key structure.
\return Returns a char pointer containing the key-id string.
*/
char *pcp_getkeyid(pcp_key_t *k);
/** Calculate a key-id from public key fields.
This does the same as pcp_getkeyid() but uses a pcp_pubkey_t
as input.
\param[in] k The public key structure.
\return Returns a char pointer containing the key-id string.
*/
char *pcp_getpubkeyid(pcp_pubkey_t *k);
/** Calculate a checksum of a public key.
This function calculates a 32 byte checksum of the
encryption public key part of the given pcp_pubkey_t
structure using crypto_hash_sha256.
The returned pointer will be allocated and it is the
responsibility of the caller to free() ist after use.
\param[in] k The public key structure.
\return Returns a pointer to an 32 byte byte.
*/
byte *pcppubkey_getchecksum(pcp_pubkey_t *k);
/** Calculate a checksum of a public key part of the given secret key.
See pcppubkey_getchecksum().
\param[in] k The secret key structure.
\return Returns a pointer to an 32 byte byte.
*/
byte *pcpkey_getchecksum(pcp_key_t *k);
pcp_key_t * key2be(pcp_key_t *k);
pcp_key_t *key2native(pcp_key_t *k);
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k);
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k);
/** Generate a nonce.
This function generates a 24 byte nonce used for cryptographic
functions. It allocates the memory and the caller is responsible
to clear and free() it after use.
\return Returns a pointer to a 24 byte byte array.
*/
byte * pcp_gennonce();
/* use scrypt() to create a key from a passphrase and a nonce
this is a wrapper around pcp_scrypt()
*/
byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce);
/* convert the key struct into a binary blob */
void pcp_seckeyblob(Buffer *b, pcp_key_t *k);
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k);
Buffer *pcp_keyblob(void *k, int type); /* allocates blob */
/* reads key from blob */
pcp_key_t *pcp_blob2key(Buffer *b); /* allocates key */
pcp_pubkey_t *pcp_blob2pubkey(Buffer *b);
/** Make a sanity check of the given public key structure.
\param[in] ptx pcp context.
\param[in] key The public key structure.
\return Returns 1 if the sanity check succeeds, 0 otherwise.
Use fatals_ifany() to check why.
*/
int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key);
/** Make a sanity check of the given secret key structure.
\param[in] ptx pcp context.
\param[in] key The secret key structure.
\return Returns 1 if the sanity check succeeds, 0 otherwise.
Use fatals_ifany() to check why.
*/
int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key);
/** Dump a secret key structure to stderr.
\param[in] k Secret key to dump.
*/
void pcp_dumpkey(pcp_key_t *k);
/** Dump a public key structure to stderr.
\param[in] k Public key to dump.
*/
void pcp_dumppubkey(pcp_pubkey_t *k);
/** Set Owner and Mail.
\param[in] key The secret key structure.
\param[in] owner Owner string.
\param[in] mail Email string.
*/
void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail);
double pcp_getentropy(char *source);
#endif /* _HAVE_PCP_KEYPAIR_H */
/**@}*/

View File

@@ -0,0 +1,153 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2016 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_KEYHASH_H
#define _HAVE_KEYHASH_H
#include "structs.h"
/** \defgroup KEYHASH KEYHASH
@{
Uthashes of secret and public key structures.
Libpcp uses the <a href="http://troydhanson.github.io/uthash/">uthash</a>
system to maintain lists of keys. There's one hash per key type. The
hash has the same type as the key structure itself, and is stored in
the PCP Context object.
*/
/* wrapper for HASH_ITER */
/** Iterate over the list of secret keys.
Sample use:
@code
pcp_key_t k = NULL;
pcphash_iterate(ptx, k) {
pcp_dumpkey(k);
}
@endcode
Also, don't free() the keyhash or the temporary key pointer
yourself. Use pcphash_clean() instead when done.
*/
#define pcphash_iterate(ptx, key) \
pcp_key_t *__k = NULL; \
HASH_ITER(hh, ptx->pcpkey_hash, key, __k)
/** Iterate over the list of public keys.
Sample use:
@code
pcp_pubkey_t k = NULL;
pcphash_iteratepub(ptx, k) {
pcp_dumppubkey(k);
}
@endcode
Also, don't free() the keyhash or the temporary key pointer
yourself. Use pcphash_clean() instead when done.
*/
#define pcphash_iteratepub(ptx, key) \
pcp_pubkey_t *__p = NULL; \
HASH_ITER(hh, ptx->pcppubkey_hash, key, __p)
/** Delete an entry from a hash.
\param[in] ptx Pcp Context object.
\param[in] key A pointer to the key structure to delete.
\param[in] type An integer specifying the key type to delete. \see _PCP_KEY_TYPES.
*/
void pcphash_del(PCPCTX *ptx, void *key, int type);
/** Free memory used by key global ptx-attached hashes. */
void pcphash_clean(PCPCTX *ptx);
/** Free memory by local pubkey hash */
void pcphash_cleanpub(pcp_pubkey_t *pub);
/** Check if a secret key with a given key-id exists in the hash.
\param[in] ptx Pcp Context object.
\param[in] id A string with the key-id (max 17 chars incl 0).
\return Returns a pointer to the matching key or NULL if the id doesn't match.
*/
pcp_key_t *pcphash_keyexists(PCPCTX *ptx, char *id);
/** Check if a publickey with a given key-id exists in the hash.
\param[in] ptx Pcp Context object.
\param[in] id A string with the key-id (max 17 chars incl 0).
\return Returns a pointer to the matching key or NULL if the id doesn't match.
*/
pcp_pubkey_t *pcphash_pubkeyexists(PCPCTX *ptx, char *id);
/** Add a key structure to the hash list.
\param[in] ptx Pcp Context object.
\param[in] key A pointer to the key structure to delete.
\param[in] type An integer specifying the key type to delete. \see _PCP_KEY_TYPES.
*/
void pcphash_add(PCPCTX *ptx, void *key, int type);
/** Returns the number of secret keys in the hash.
\param[in] ptx Pcp Context object.
\return Number of keys.
*/
int pcphash_count(PCPCTX *ptx);
/** Returns the number of public keys in the hash.
\param[in] ptx Pcp Context object.
\return Number of keys.
*/
int pcphash_countpub(PCPCTX *ptx);
#define pcphash_iteratekeysig(ptx, key) \
pcp_keysig_t *__s = NULL; \
HASH_ITER(hh, ptx->pcpkeysig_hash, key, __s)
pcp_keysig_t *pcphash_keysigexists(PCPCTX *ptx, char *id);
#endif /* _HAVE_KEYHASH_H */
/**@}*/

View File

@@ -0,0 +1,50 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_KEYSIG_H
#define _HAVE_PCP_KEYSIG_H
#include <string.h>
#include <stdio.h>
#include "defines.h"
#include "platform.h"
#include "mem.h"
#include "structs.h"
#include "buffer.h"
#include "key.h"
#define PCP_RAW_KEYSIGSIZE sizeof(pcp_keysig_t) - sizeof(UT_hash_handle)
/* put a keysig into a buffer, convert to big endian while at it */
void pcp_keysig2blob(Buffer *b, pcp_keysig_t *s);
/* same, but allocs buffer */
Buffer *pcp_keysigblob(pcp_keysig_t *s);
/* fetch a keysig from a buffer, usually loaded from vault */
pcp_keysig_t *pcp_blob2keysig(Buffer *blob);
/* debug print a keysig */
void pcp_dumpkeysig(pcp_keysig_t *s);
#endif /* _HAVE_PCP_KEYSIG_H */

58
libpcp/include/pcp/mem.h Normal file
View File

@@ -0,0 +1,58 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_PCP_MEM
#define _HAVE_PCP_MEM
#include <string.h>
#include <stdlib.h>
#include <sodium.h>
#include "defines.h"
#include "platform.h"
/* simple malloc() wrapper */
/* behaves like calloc(), which */
/* I don't have here. */
/* */
/* exits if there's no more memory */
/* available. */
void *ucmalloc(size_t s);
/* same as ucmalloc, but uses secure allocation */
void *smalloc(size_t s);
/* the same but it fills the pointer with random values */
void *urmalloc(size_t s);
/* same as urmalloc(), but uses secure allocation using sodium_malloc() */
void *srmalloc(size_t s);
/* resize a a pointer and fill the added remainder with zeroes */
void *ucrealloc(void *d, size_t oldlen, size_t newlen);
/* clear and free */
void ucfree(void *d, size_t len);
/* same, but free a sodium pointer */
void sfree(void *d);
#endif /* _HAVE_PCP_MEM */

195
libpcp/include/pcp/mgmt.h Normal file
View File

@@ -0,0 +1,195 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2014-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
/*
key management, namely import and export routines.
we're working with buffers only, no direct file i/o */
#ifndef _HAVE_PCP_MGMT_H
#define _HAVE_PCP_MGMT_H
#if defined __linux__ || defined __GNU__ || defined __GLIBC__
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE 1
#endif
#
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 1
#endif
#
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#
#ifndef __USE_XOPEN
#define __USE_XOPEN 1
#endif
#
#else
#define _BSD_SOURCE 1
#endif
#include <sodium.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
// #ifdef HAVE_JSON
#ifndef JANSSON_H
#include <jansson.h>
#endif
#include "buffer.h"
#include "context.h"
#include "defines.h"
#include "ed.h"
#include "key.h"
#include "keysig.h"
#include "mem.h"
#include "platform.h"
#include "scrypt.h"
#include "structs.h"
/* key management api, export, import, and stuff */
/**
* \defgroup PubKeyExport KEYEXPORT
* @{
Functions to export and import keys in various formats.
*/
/** RFC4880 alike public key export with some modifications.
(Refer to the INTERNALS section of the pcp(1) manual page for details.
\param sk a secret key structure of type pcp_key_t. The secret keys
in there have to be already decrypted.
\return the function returns a Buffer object containing the binary
blob in the format described above.
*/
Buffer *pcp_export_rfc_pub(PCPCTX *ptx, pcp_key_t *sk);
/** Export a public key in PBP format.
Export a public key in the format described at
https://github.com/stef/pbp/blob/master/doc/fileformats.txt
\param sk a secret key structure of type pcp_key_t. The secret keys
in there have to be already decrypted.
\return the function returns a Buffer object containing the binary
blob in the format described above.
*/
Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
/** Export secret key.
Export a secret key. (refer to the INTERNALS section of the pcp(1) manual
page for details).
\param[in] ptx context.
\param sk a secret key structure of type pcp_key_t. The secret keys
in there have to be already decrypted.
\param passphrase the passphrase to be used to encrypt the export,
a null terminated char array.
\return the function returns a Buffer object containing the binary
blob in the format described above.
*/
Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase);
#ifdef HAVE_JSON
/** Export public key from a secret key in JSON format
\param[in] sk a secret key structure of type pcp_key_t. The secret keys
in there have to be already decrypted.
\param[in] sig the keysig blob.
\return the function returns a Buffer object containing the binary
blob containing a JSON string.
*/
Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig,
size_t siglen);
/** Export secret key in JSON format
\param[in] sk a secret key structure of type pcp_key_t. The secret keys
in there have to be already decrypted.
\param[in] nonce the nonce used to encrypt secret keys
\param[in] cipher the encrypted secret keys
\param[in] clen len of cipher
\return the function returns a Buffer object containing the binary
blob containing a JSON string.
*/
Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce,
byte *cipher, size_t clen);
/** Convert secret key struct into JSON struct
\param[in] sk a secret key structure of type pcp_key_t.
\param[in] sig the keysig blob, maybe NULL.
\return returns a json_t structure (see libjansson docs for details)
*/
json_t *pcp_sk2json(pcp_key_t *sk, byte *sig, size_t siglen);
/** Convert public key struct into JSON struct
\param[in] pk a public key structure of type pcp_key_t.
\param[in] sig the keysig blob, maybe NULL.
\return returns a json_t structure (see libjansson docs for details)
*/
json_t *pcp_pk2json(pcp_pubkey_t *pk);
pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize);
Buffer *pcp_import_secret_json(PCPCTX *ptx, Buffer *json);
#endif
pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize);
pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize);
pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob);
pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob);
/* import secret key */
pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize,
char *passphrase);
pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize,
char *passphrase);
pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher,
char *passphrase);
/* helpers */
int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h);
int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p,
pcp_keysig_t *sk);
int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p,
rfc_pub_sig_s *subheader);
#endif // _HAVE_PCP_MGMT_H
/**@}*/

View File

@@ -0,0 +1,291 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef HAVE_PCP_PCPSTEAM_H
#define HAVE_PCP_PCPSTEAM_H
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include "mem.h"
#include "structs.h"
#include "util.h"
#include "defines.h"
#include "context.h"
#include "buffer.h"
#include "z85.h"
/**
* \defgroup Pcpstream PCPSTREAMS
* @{
I/O wrapper for files or buffers.
Simple wrapper around FILE streams or Buffers, depending
how the user initialized them. The Pcpstream object behaves
always the same and it doesn't matter how it's backed.
We use it in the lib, e.g. in the crypto routines. That way
we can support blockwise crypto on buffers or files.
Streams are, just like iostreams in c++, either output or
input mode.
Sample usage:
\include tests/streamtest.c
*/
/* initialize a new empty stream */
Pcpstream *ps_init(void);
/** Create a new stream, backed with an open file.
The stream used for in- or output.
\param[in] backendfd An open FILE stream.
\return Returns a Pcpstream structure.
*/
Pcpstream *ps_new_file(FILE *backendfd);
/** Create a new input stream, backed with filled a buffer.
This kind of stream can be used for reading only.
\param[in] b A Buffer object filled with data.
\return Returns a Pcpstream structure.
*/
Pcpstream *ps_new_inbuffer(Buffer *b);
/** Create a new output stream, backed with a buffer.
The buffer used to write data to will be allocated
and filled by the class. You can retrieve it later.
\return Returns a Pcpstream structure.
*/
Pcpstream *ps_new_outbuffer();
/** Read bytes into the given buffer from the current stream.
This function reads 'readbytes' bytes from the stream
into given buf. The buffer needs to be properly allocated
by the caller in advance to have at least readbytes len.
Sets eof=1 if end of file or end of buffer has been reached.
Sets err=1 if an error occurred, fatals() maybe set, or errno.
See ps_end() and ps_err().
\param[in] stream The input stream to read from.
\param[out] buf The buffer where to put read bytes.
\param[in] readbytes The number of bytes to read.
\return Returns the bytes read, if there's nothing more to read, it returns 0.
*/
size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes);
/** Write bytes from the given buffer into the current stream.
This function writes 'writebytes' bytes from the given buf
into the stream
Sets err in case of an error. See ps_err().
\param[out] stream The input stream to write to.
\param[in] buf The buffer containing data to put into the stream.
\param[in] writebytes The number of bytes to write.
\return Returns the number of bytes written. in case of errors it returns 0.
*/
size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes);
/** Finalize writing the stream.
You NEED to call this function after you're done writing
to the stream if you enabled Z85 armoring using ps_armor().
It writes the remaining bytes (encoded) to the stream destination.
\param[in] stream The input stream to write to.
\return Returns the number of bytes written. in case of errors it returns 0.
*/
size_t ps_finish(Pcpstream *stream);
/** Write a formatted string to the stream.
Use an printf() style format string to print something out
to a stream.
Sets err in case of an error. See ps_err().
\param[out] stream The input stream to read from.
\param[in] fmt The printf() compatible format description.
\param[in] ... A variable number of arguments for the format string.
\return Returns the number of bytes written. in case of errors it returns 0.
*/
size_t ps_print(Pcpstream *stream, const char * fmt, ...);
/** Tell the current read or write offset.
This function works like ftell() on a FILE stream or
like Buffer->offset in the Buffer class.
\param[in] stream The input stream to read from.
\return Returns the the number of bytes read/written so far.
*/
size_t ps_tell(Pcpstream *stream);
/** Access the Buffer backend pointer.
Use this function to access the underlying Buffer object
of an output stream to access the contents written to it.
Only usefull if the stream have been initialized with
ps_new_outbuffer().
\param[in] stream The stream object.
\return Returns a pointer to the Buffer object.
*/
Buffer *ps_buffer(Pcpstream *stream);
/** Close the stream and frees allocated memory.
If the backend of the stream was a FILE stream, close it, unless it is
stdin, stdout or stderr.
If the backend was a Buffer, clear and free it.
\param[in] stream The stream to close.
*/
void ps_close(Pcpstream *stream);
/** Check if EOF have been reached.
This function can be used to check if there are no more
bytes to read. This will happen if we reach EOF with a
FILE backed stream or buffer_done() with a Buffer backed
stream.
\param[in] stream The stream object.
\return Returns 1 if we reached EOF, 0 otherwise
*/
int ps_end(Pcpstream *stream);
/** Check if an error occurred during a read or write operation.
\param[in] stream The stream object.
\return Returns 1 if there were any errors or 0 otherwise. Also check errno() and fatals_ifany().
*/
int ps_err(Pcpstream *stream);
/** Enable auto Z85 encoding detection for an input stream.
If you're not sure if your input is Z85 encoded, enable
detection.
\param[in] stream The stream object.
\param[in] blocksize The blocksize to for Z85 decoding (if encoded).
*/
void ps_setdetermine(Pcpstream *stream, size_t blocksize);
/** Enable Z85 encoding for an output stream.
\param[in] stream The stream object.
\param[in] blocksize The blocksize to for Z85 encoding.
*/
void ps_armor(Pcpstream *stream, size_t blocksize);
/** Disable Z85 encoding for an output stream.
\param[in] stream The stream object.
*/
void ps_unarmor(Pcpstream *stream);
/* read from primary source, decode z85 and out into cache.
if buf != NULL, consider it as the start of encoded data
and remove headers and comments, then continue as normal. */
size_t ps_read_decode(Pcpstream *stream);
/* determine if primary source is z85 encoded, put the data
read from it into the cache */
void ps_determine(Pcpstream *stream);
/* read and decode the next chunk and put it into stream->next */
size_t ps_read_next(Pcpstream *stream);
/* return readbytes from cache. if it is more than left in the cache
fetch (and decode) the next chunk, append it to cache and return from
that */
size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes);
/* really read from the source */
size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes);
/* helper, Z85 encodes current cache into the dst buffer */
void ps_write_encode(Pcpstream *stream, Buffer *dst);
/* really write the buffer z into the output stream */
size_t ps_write_buf(Pcpstream *stream, Buffer *z);
/* tell if we really reached eof, caching or not. 1=eof, 0=ok */
int ps_left(Pcpstream *stream);
/** Read a line from the stream.
\param[in] stream The stream object.
\param[out] line Linecontent will be written to this Buffer.
\return Returns the number of bytes read or -1 if PSMAXLINE have been
reached or the input doesn't have any newlines at all.
*/
int ps_readline(Pcpstream *stream, Buffer *line);
#endif // HAVE_PCP_PCPSTEAM_H
/**@}*/

View File

@@ -0,0 +1,87 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2016 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_PLATFORM_H
#define _HAVE_PCP_PLATFORM_H
#include "config.h"
#ifndef HAVE_ARC4RANDOM
#include <sodium.h>
#define arc4random() randombytes_random()
#endif
#ifndef HAVE_ARC4RANDOM_BUF
#include <sodium.h>
#define arc4random_buf(buf, nbytes) randombytes((byte *)buf, nbytes)
#endif
#ifndef HAVE_ERR_H
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
void err(int eval, const char *fmt, ...);
#else
#include <errno.h>
#include <err.h>
#endif
#ifndef HAVE_VASPRINTF
#include <stdarg.h>
int vasprintf(char **ret, const char *format, va_list args);
#endif
#ifdef _AIX_SOURCE
#define _LINUX_SOURCE_COMPAT
#endif
#ifndef HAVE_STRNLEN
size_t
strnlen(const char *msg, size_t maxlen);
#endif
#ifndef HAVE_STRNSTR
/* via FreeBSD libc */
#include <string.h>
char *
strnstr(const char *s, const char *find, size_t slen);
#endif
/* size_t format string */
#ifdef __LP64__
#define FMT_SIZE_T "llu"
#define SIZE_T_CAST long long unsigned int
#else
#define FMT_SIZE_T "lu"
#define SIZE_T_CAST long unsigned int
#endif
#endif /* !_HAVE_PCP_PLATFORM_H */

View File

@@ -0,0 +1,83 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T. von Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
/*
Simple linked list wrappers,
used for recipient- or keyid lists
*/
#ifndef _HAVE_PCP_PLIST_H
#define _HAVE_PCP_PLIST_H
#include <stdlib.h>
#include <stdio.h>
struct _plist_t {
char *value;
struct _plist_t *next;
struct _plist_t *first;
};
typedef struct _plist_t plist_t;
static inline void p_add(plist_t **lst, char *value) {
plist_t *newitem;
plist_t *iter = *lst;
newitem = (plist_t *)malloc(sizeof(plist_t));
newitem->value = (char *)malloc(strlen(value) + 1);
strncpy(newitem->value, value, strlen(value) + 1);
newitem->next = NULL;
if ( iter != NULL ) {
while (iter->next != NULL ) {
iter = iter->next;
}
newitem->first = iter->first;
iter->next = newitem;
}
else {
newitem->first = newitem;
*lst = newitem;
}
}
static inline void p_add_me(plist_t **lst) {
char *me = (char *)malloc(13);
strcpy(me, "__self__");
p_add(lst, me);
free(me);
}
static inline void p_clean(plist_t *lst) {
plist_t *iter = lst->first;
plist_t *tmp;
while (iter != NULL) {
tmp = iter;
iter = iter->next;
free(tmp->value);
free(tmp);
}
}
#endif /* _HAVE_PCP_PLIST_H */

View File

@@ -0,0 +1,54 @@
/* $OpenBSD: key.c,v 1.70 2008/06/11 21:01:35 grunk Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 2000, 2001 Markus Friedl. 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 ``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 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.
*/
/* key_fingerprint_randomart comitted by Alexander von Gernler in rev 1.70 */
#ifndef _HAVE_PCP_RANDOMART_H
#define _HAVE_PCP_RANDOMART_H
#include "mem.h"
#include <string.h>
/* from openssh key.c */
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
char *key_fingerprint_randomart(unsigned char *dgst_raw, unsigned int dgst_raw_len);
#endif /* _HAVE_PCP_RANDOMART_H */

View File

@@ -0,0 +1,69 @@
/*-
* Copyright 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.
*
* This file was originally written by Colin Percival as part of the Tarsnap
* online backup system.
*/
#ifndef _READPASS_H_
#define _READPASS_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "defines.h"
#include "context.h"
#include "util.h"
#define MAXPASSLEN 2048
/**
* tarsnap_getpass(passwd, prompt, confirmprompt, devtty)
* If ${devtty} is non-zero, read a password from /dev/tty if possible; if
* not, read from stdin. If reading from a tty (either /dev/tty or stdin),
* disable echo and prompt the user by printing ${prompt} to stderr. If
* ${confirmprompt} is non-NULL, read a second password (prompting if a
* terminal is being used) and repeat until the user enters the same password
* twice. Return the password as a malloced NUL-terminated string via
* ${passwd}. The obscure name is to avoid namespace collisions due to the
* getpass / readpass / readpassphrase / etc. functions in various libraries.
*/
int pcp_readpass(PCPCTX *ptx, char **passwd, const char *prompt,
const char *confirmprompt, int devtty, char *readfromfile);
/**
from encfs getUserKey().
*/
int pcp_readpass_fromprog(PCPCTX *ptx, char **passwd, const char *askpass);
#endif /* !_READPASS_H_ */

View File

@@ -0,0 +1,42 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_PCP_SCRYPT_H
#define _HAVE_PCP_SCRYPT_H
#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sodium.h>
#include "mem.h"
#include "defines.h"
#include "context.h"
byte * pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_t noncelen);
#endif /* _HAVE_PCP_SCRYPT_H */

View File

@@ -0,0 +1,380 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2014 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_STRUCTS_H
#define _HAVE_PCP_STRUCTS_H
#include "defines.h"
#include "uthash.h"
#include <sodium.h>
/**
\addtogroup KEYS
@{
*/
/** \struct _pcp_key_t
PCP private key structure. Most fields are self explanatory.
Some notes:
'encrypted' contains the encrypted secret keys (contatenated mastersecret,
secret and edsecret). If it's set,
the field 'secret' which contains the clear secret key will
be zeroed with random values, the first byte will be 0. Same
for the field 'edsecret'.
'nonce' contains the nonce required to decrypt the encrypted
secret, if set.
'serial' is a random number.
'id' is a string containing the hex values of the CRC32 checksum
of the public and secret key.
Upon creation everything will be filled with random bytes.
String fields will contain a string followed by 0 followed
by the rest of the pre-filled random bytes. To denote a string
field as empty, the first byte will be set to 0.
There are dynamically calculated attributes as well:
'checksum' is a 256 bit SHA hash of the public key returned
by pcpkey_getchecksum() or pcppubkey_getchecksum().
'random id' is a random art ascii image returned by
pcppubkey_get_art() or pcpkey_get_art(), calculated from
the public key.
If exported to a single file or printed, the structure will
be encoded using Z85 encoding.
*/
struct _pcp_key_t {
byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte mastersecret[LEDSEC]; /**< ED25519 master secret key signing key */
byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte secret[LBOXSEC]; /**< Curve25519 encryption secret key */
byte edpub[LEDPUB]; /**< ED25519 public signing key */
byte edsecret[LEDSEC]; /**< ED25519 secret signing key */
byte nonce[LNONCE]; /**< random nonce used to encrypt secret keys */
byte encrypted[LSEC]; /**< concatenated and encrypted secret keys */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
UT_hash_handle hh;
};
/** Typedef for secret keys */
typedef struct _pcp_key_t pcp_key_t;
/** \struct _pcp_pubkey_t
PCP public key structure.
This structure contains a subset of the pcp_key_t structure
without the secret and nonce fields.
*/
struct _pcp_pubkey_t {
byte masterpub[LEDPUB]; /**< ED25519 master public key signing key */
byte pub[LBOXPUB]; /**< Curve25519 encryption public key */
byte edpub[LEDPUB]; /**< ED25519 public signing key (FIXME: huh? 2 of them???) */
char owner[255]; /**< the key owner, string */
char mail[255]; /**< mail address of the owner, string */
char id[17]; /**< key-id, used internally only, jenhash of public keys */
uint8_t type; /**< key type: MASTER_SECRET or SECRET */
uint64_t ctime; /**< creation time, epoch */
uint32_t version; /**< key version */
uint32_t serial; /**< serial number of the key, randomly generated */
uint8_t valid; /**< 1 if import signature verified, 0 if not */
byte signature[crypto_generichash_BYTES_MAX + crypto_sign_BYTES]; /**< raw binary blob of pubkey export signature */
UT_hash_handle hh;
};
/** Typedef for public keys */
typedef struct _pcp_pubkey_t pcp_pubkey_t;
/* the PBP public key format */
/* keys.mp+keys.cp+keys.sp+keys.name */
struct _pbp_pubkey_t {
byte masterpub[crypto_sign_PUBLICKEYBYTES];
byte edpub[crypto_sign_PUBLICKEYBYTES];
byte pub[crypto_box_PUBLICKEYBYTES];
char iso_ctime[32];
char iso_expire[32];
char name[1024];
};
typedef struct _pbp_pubkey_t pbp_pubkey_t;
/** \struct _pcp_rec_t
Encrypted recipient list.
Encrypted recipient list, required for crypt+sign
contains the encrypted recipients and the secret
key required for signing the message+recipients.
Used internally only.
*/
struct _pcp_rec_t {
size_t ciphersize; /**< the size of the encrypted recipient list */
byte *cipher; /**< contains the whole encrypted recipient list */
pcp_key_t *secret; /**< the secret key of the recipient for signing */
pcp_pubkey_t *pub; /**< if verification were ok, contains the public key of the signer */
};
/** Typedef for public keys */
typedef struct _pcp_rec_t pcp_rec_t;
/* holds a public key signature */
struct _pcp_keysig_t {
uint8_t type;
uint32_t size;
char id[17];
byte checksum[LSHA];
byte *blob;
UT_hash_handle hh;
};
typedef struct _pcp_keysig_t pcp_keysig_t;
/** @}
*/
/**
\addtogroup CONTEXT
@{
*/
/** \struct _pcp_ctx_t
PCP context object.
Holds error state and key hashes.
*/
struct _pcp_ctx_t {
char *pcp_err; /**< last error message. retrieve with fatals_ifany() */
byte pcp_errset; /**< indicates if an error occurred. */
int pcp_exit; /**< exit code for pcp commandline utility */
int verbose; /**< enable verbose output */
int json; /**< enable json i/o */
pcp_key_t *pcpkey_hash; /**< hash containing for keys */
pcp_pubkey_t *pcppubkey_hash; /**< hash for keys. */
pcp_keysig_t *pcpkeysig_hash; /**< hash for key sigs */
};
typedef struct _pcp_ctx_t PCPCTX;
/** @}
*/
/**
\addtogroup VAULT
@{
*/
/** \struct _vault_t
This structure represents a vault. */
struct _vault_t {
char *filename; /**< The filename of the vault (full path) */
FILE *fd; /**< Filehandle if opened */
uint8_t unsafed; /**< Flag to tell if the file needs to be written */
uint8_t isnew; /**< Flag to tell if the vault has been newly created */
uint32_t size; /**< Filesize */
time_t modified; /**< mtime */
mode_t mode; /**< File mode */
uint32_t version; /**< Vault version */
byte checksum[LSHA]; /**< SHA256 checksum over the whole vault */
};
/** Name of the struct */
typedef struct _vault_t vault_t;
/** \struct _vault_header_t
Defines the vault header. */
struct _vault_header_t {
uint8_t fileid; /**< File id, proprietary. Marks the vault as a vault */
uint32_t version; /**< File version */
byte checksum[LSHA]; /**< SHA256 checksum over the whole vault */
};
/** Name of the struct */
typedef struct _vault_header_t vault_header_t;
/** \struct _vault_item_header_t
An item header. */
struct _vault_item_header_t {
uint8_t type; /**< Item type (secret key, public, key, keysig, \see _PCP_KEY_TYPES */
uint32_t size; /**< Size of the item */
uint32_t version; /**< Version of the item */
byte checksum[LSHA]; /**< SHA256 checksum of the item */
};
/** Name of the struct */
typedef struct _vault_item_header_t vault_item_header_t;
/** @}
*/
/**
\addtogroup BUFFER
@{
*/
/** \struct _pcp_buffer
A flexible buffer object wich automatically resizes, if neccessary.
*/
struct _pcp_buffer {
char *name; /**< just for convenience in error messages and the like, so we know which buffer cause trouble */
uint8_t allocated; /**< marks the buffer as allocated */
size_t blocksize; /**< the blocksize to use when resizing, also used for initial malloc() */
size_t size; /**< stores the current allocated size of the object */
size_t offset; /**< current read position */
size_t end; /**< current write position, data end. maybe less than size. */
uint8_t isstring; /**< treat as char array/string */
void *buf; /**< the actual storage buffer */
};
/** The name used everywhere */
typedef struct _pcp_buffer Buffer;
/** @}
*/
/**
\addtogroup PCPSTREAMS
@{
*/
/** \struct _pcp_stream_t
An I/O wrapper object backed by a file or a buffer.
*/
struct _pcp_stream_t {
FILE *fd; /**< The backend FILE stream */
Buffer *b; /**< The backend Buffer object */
Buffer *cache; /**< The caching Buffer object (for look ahead read) */
Buffer *next; /**< The caching Next-Buffer object (for look ahead read) */
Buffer *save; /**< Temporary buffer to backup overflow data */
byte *xb; /**< Temporary byte buffer for reading/writing data */
uint8_t is_buffer; /**< Set to 1 if the backend is a Buffer */
uint8_t eof; /**< Set to 1 if EOF reached */
uint8_t err; /**< Set to 1 if an error occured */
uint8_t armor; /**< Set to 1 if Z85 en/de-coding is requested */
uint8_t determine; /**< Set to 1 to automatically determine armor mode */
uint8_t firstread; /**< Internal flag, will be set after first read() */
size_t linewr; /**< Used for Z85 writing, number of chars written on last line */
size_t blocksize; /**< Blocksize used for z85, if requested */
uint8_t is_output; /**< marks the stream as output stream */
uint8_t have_begin; /**< flag to indicate we already got the begin header, if any */
size_t pos; /**< remember i/o position */
};
typedef enum _PSVARS {
PSMAXLINE = 20000
} PSVARS;
/** The name used everywhere */
typedef struct _pcp_stream_t Pcpstream;
/** @}
*/
/* various helper structs for mgmt.c, used internally only */
struct _pcp_rfc_pubkey_header_t {
uint8_t version;
uint64_t ctime;
uint8_t cipher;
};
struct _pcp_rfc_pubkey_0x21_t {
byte sig_ed25519_pub[crypto_sign_PUBLICKEYBYTES];
byte ed25519_pub[crypto_sign_PUBLICKEYBYTES];
byte curve25519_pub[crypto_box_PUBLICKEYBYTES];
};
struct _pcp_rfc_pubkey_sigheader_0x21_t {
uint8_t version;
uint8_t type;
uint8_t pkcipher;
uint8_t hashcipher;
uint16_t numsubs;
};
struct _pcp_rfc_pubkey_sigsub_0x21_t {
uint32_t size;
uint8_t type;
};
typedef struct _pcp_rfc_pubkey_header_t rfc_pub_h;
typedef struct _pcp_rfc_pubkey_0x21_t rfc_pub_k;
typedef struct _pcp_rfc_pubkey_sigheader_0x21_t rfc_pub_sig_h;
typedef struct _pcp_rfc_pubkey_sigsub_0x21_t rfc_pub_sig_s;
struct _pcp_ks_bundle_t {
pcp_pubkey_t *p;
pcp_keysig_t *s;
};
typedef struct _pcp_ks_bundle_t pcp_ks_bundle_t;
#endif //_HAVE_PCP_STRUCTS_H

948
libpcp/include/pcp/uthash.h Executable file
View File

@@ -0,0 +1,948 @@
/*
Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
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.
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 THE COPYRIGHT OWNER
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 UTHASH_H
#define UTHASH_H
#include <string.h> /* memcmp,strlen */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit() */
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#ifdef _MSC_VER /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
#define DECLTYPE(x) (decltype(x))
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define DECLTYPE(x)
#endif
#else /* GNU, Sun and other compilers */
#define DECLTYPE(x) (__typeof(x))
#endif
#ifdef NO_DECLTYPE
#define DECLTYPE_ASSIGN(dst,src) \
do { \
char **_da_dst = (char**)(&(dst)); \
*_da_dst = (char*)(src); \
} while(0)
#else
#define DECLTYPE_ASSIGN(dst,src) \
do { \
(dst) = DECLTYPE(dst)(src); \
} while(0)
#endif
/* a number of the hash function use uint32_t which isn't defined on win32 */
#ifdef _MSC_VER
typedef unsigned int uint32_t;
typedef byte uint8_t;
#else
#include <inttypes.h> /* uint32_t */
#endif
#define UTHASH_VERSION 1.9.8
#ifndef uthash_fatal
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
#endif
#ifndef uthash_malloc
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#endif
#ifndef uthash_free
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
#endif
#ifndef uthash_noexpand_fyi
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
#endif
#ifndef uthash_expand_fyi
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
#endif
/* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
/* calculate the element whose hash handle address is hhe */
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
#define HASH_FIND(hh,head,keyptr,keylen,out) \
do { \
unsigned _hf_bkt,_hf_hashv; \
out=NULL; \
if (head) { \
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
keyptr,keylen,out); \
} \
} \
} while (0)
#ifdef HASH_BLOOM
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
#define HASH_BLOOM_MAKE(tbl) \
do { \
(tbl)->bloom_nbits = HASH_BLOOM; \
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
} while (0)
#define HASH_BLOOM_FREE(tbl) \
do { \
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
} while (0)
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
#define HASH_BLOOM_ADD(tbl,hashv) \
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#define HASH_BLOOM_TEST(tbl,hashv) \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
#define HASH_BLOOM_MAKE(tbl)
#define HASH_BLOOM_FREE(tbl)
#define HASH_BLOOM_ADD(tbl,hashv)
#define HASH_BLOOM_TEST(tbl,hashv) (1)
#define HASH_BLOOM_BYTELEN 0
#endif
#define HASH_MAKE_TABLE(hh,head) \
do { \
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
sizeof(UT_hash_table)); \
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
(head)->hh.tbl->tail = &((head)->hh); \
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl->buckets, 0, \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_MAKE((head)->hh.tbl); \
(head)->hh.tbl->signature = HASH_SIGNATURE; \
} while(0)
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
do { \
replaced=NULL; \
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
if (replaced!=NULL) { \
HASH_DELETE(hh,head,replaced); \
}; \
HASH_ADD(hh,head,fieldname,keylen_in,add); \
} while(0)
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
do { \
unsigned _ha_bkt; \
(add)->hh.next = NULL; \
(add)->hh.key = (char*)(keyptr); \
(add)->hh.keylen = (unsigned)(keylen_in); \
if (!(head)) { \
head = (add); \
(head)->hh.prev = NULL; \
HASH_MAKE_TABLE(hh,head); \
} else { \
(head)->hh.tbl->tail->next = (add); \
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
(head)->hh.tbl->tail = &((add)->hh); \
} \
(head)->hh.tbl->num_items++; \
(add)->hh.tbl = (head)->hh.tbl; \
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
(add)->hh.hashv, _ha_bkt); \
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
HASH_FSCK(hh,head); \
} while(0)
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
do { \
bkt = ((hashv) & ((num_bkts) - 1)); \
} while(0)
/* delete "delptr" from the hash table.
* "the usual" patch-up process for the app-order doubly-linked-list.
* The use of _hd_hh_del below deserves special explanation.
* These used to be expressed using (delptr) but that led to a bug
* if someone used the same symbol for the head and deletee, like
* HASH_DELETE(hh,users,users);
* We want that to work, but by changing the head (users) below
* we were forfeiting our ability to further refer to the deletee (users)
* in the patch-up process. Solution: use scratch space to
* copy the deletee pointer, then the latter references are via that
* scratch pointer rather than through the repointed (users) symbol.
*/
#define HASH_DELETE(hh,head,delptr) \
do { \
unsigned _hd_bkt; \
struct UT_hash_handle *_hd_hh_del; \
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
head = NULL; \
} else { \
_hd_hh_del = &((delptr)->hh); \
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
(head)->hh.tbl->tail = \
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
(head)->hh.tbl->hho); \
} \
if ((delptr)->hh.prev) { \
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
} else { \
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
} \
if (_hd_hh_del->next) { \
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
(head)->hh.tbl->hho))->prev = \
_hd_hh_del->prev; \
} \
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
(head)->hh.tbl->num_items--; \
} \
HASH_FSCK(hh,head); \
} while (0)
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
#define HASH_FIND_STR(head,findstr,out) \
HASH_FIND(hh,head,findstr,strlen(findstr),out)
#define HASH_ADD_STR(head,strfield,add) \
HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced)
#define HASH_FIND_INT(head,findint,out) \
HASH_FIND(hh,head,findint,sizeof(int),out)
#define HASH_ADD_INT(head,intfield,add) \
HASH_ADD(hh,head,intfield,sizeof(int),add)
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
#define HASH_FIND_PTR(head,findptr,out) \
HASH_FIND(hh,head,findptr,sizeof(void *),out)
#define HASH_ADD_PTR(head,ptrfield,add) \
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
#define HASH_REPLACE_PTR(head,ptrfield,add) \
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
#define HASH_DEL(head,delptr) \
HASH_DELETE(hh,head,delptr)
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
*/
#ifdef HASH_DEBUG
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
#define HASH_FSCK(hh,head) \
do { \
unsigned _bkt_i; \
unsigned _count, _bkt_count; \
char *_prev; \
struct UT_hash_handle *_thh; \
if (head) { \
_count = 0; \
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
_bkt_count = 0; \
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
_prev = NULL; \
while (_thh) { \
if (_prev != (char*)(_thh->hh_prev)) { \
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
_thh->hh_prev, _prev ); \
} \
_bkt_count++; \
_prev = (char*)(_thh); \
_thh = _thh->hh_next; \
} \
_count += _bkt_count; \
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
HASH_OOPS("invalid bucket count %d, actual %d\n", \
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
} \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid hh item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
/* traverse hh in app order; check next/prev integrity, count */ \
_count = 0; \
_prev = NULL; \
_thh = &(head)->hh; \
while (_thh) { \
_count++; \
if (_prev !=(char*)(_thh->prev)) { \
HASH_OOPS("invalid prev %p, actual %p\n", \
_thh->prev, _prev ); \
} \
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
(head)->hh.tbl->hho) : NULL ); \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid app item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
} \
} while (0)
#else
#define HASH_FSCK(hh,head)
#endif
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
do { \
unsigned _klen = fieldlen; \
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
#else
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6 */
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hb_keylen=keylen; \
char *_hb_key=(char*)(key); \
(hashv) = 0; \
while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
bkt = (hashv) & (num_bkts-1); \
} while (0)
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _sx_i; \
char *_hs_key=(char*)(key); \
hashv = 0; \
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
bkt = hashv & (num_bkts-1); \
} while (0)
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _fn_i; \
char *_hf_key=(char*)(key); \
hashv = 2166136261UL; \
for(_fn_i=0; _fn_i < keylen; _fn_i++) \
hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _ho_i; \
char *_ho_key=(char*)(key); \
hashv = 0; \
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
hashv += _ho_key[_ho_i]; \
hashv += (hashv << 10); \
hashv ^= (hashv >> 6); \
} \
hashv += (hashv << 3); \
hashv ^= (hashv >> 11); \
hashv += (hashv << 15); \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_JEN_MIX(a,b,c) \
do { \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
} while (0)
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hj_i,_hj_j,_hj_k; \
byte *_hj_key=(byte*)(key); \
hashv = 0xfeedbeef; \
_hj_i = _hj_j = 0x9e3779b9; \
_hj_k = (unsigned)(keylen); \
while (_hj_k >= 12) { \
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ ( (unsigned)_hj_key[2] << 16 ) \
+ ( (unsigned)_hj_key[3] << 24 ) ); \
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ ( (unsigned)_hj_key[6] << 16 ) \
+ ( (unsigned)_hj_key[7] << 24 ) ); \
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ ( (unsigned)_hj_key[10] << 16 ) \
+ ( (unsigned)_hj_key[11] << 24 ) ); \
\
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
\
_hj_key += 12; \
_hj_k -= 12; \
} \
hashv += keylen; \
switch ( _hj_k ) { \
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
case 5: _hj_j += _hj_key[4]; \
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
case 1: _hj_i += _hj_key[0]; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
bkt = hashv & (num_bkts-1); \
} while(0)
/* The Paul Hsieh hash function */
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
do { \
byte *_sfh_key=(byte*)(key); \
uint32_t _sfh_tmp, _sfh_len = keylen; \
\
int _sfh_rem = _sfh_len & 3; \
_sfh_len >>= 2; \
hashv = 0xcafebabe; \
\
/* Main loop */ \
for (;_sfh_len > 0; _sfh_len--) { \
hashv += get16bits (_sfh_key); \
_sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \
hashv = (hashv << 16) ^ _sfh_tmp; \
_sfh_key += 2*sizeof (uint16_t); \
hashv += hashv >> 11; \
} \
\
/* Handle end cases */ \
switch (_sfh_rem) { \
case 3: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 16; \
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \
hashv += hashv >> 11; \
break; \
case 2: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 11; \
hashv += hashv >> 17; \
break; \
case 1: hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
} \
\
/* Force "avalanching" of final 127 bits */ \
hashv ^= hashv << 3; \
hashv += hashv >> 5; \
hashv ^= hashv << 4; \
hashv += hashv >> 17; \
hashv ^= hashv << 25; \
hashv += hashv >> 6; \
bkt = hashv & (num_bkts-1); \
} while(0)
#ifdef HASH_USING_NO_STRICT_ALIASING
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
#define MUR_GETBLOCK(p,i) p[i]
#else /* non intel */
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
#else /* assume little endian non-intel */
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
#endif
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
MUR_ONE_THREE(p))))
#endif
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
#define MUR_FMIX(_h) \
do { \
_h ^= _h >> 16; \
_h *= 0x85ebca6b; \
_h ^= _h >> 13; \
_h *= 0xc2b2ae35l; \
_h ^= _h >> 16; \
} while(0)
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
do { \
const uint8_t *_mur_data = (const uint8_t*)(key); \
const int _mur_nblocks = (keylen) / 4; \
uint32_t _mur_h1 = 0xf88D5353; \
uint32_t _mur_c1 = 0xcc9e2d51; \
uint32_t _mur_c2 = 0x1b873593; \
uint32_t _mur_k1 = 0; \
const uint8_t *_mur_tail; \
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
int _mur_i; \
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
\
_mur_h1 ^= _mur_k1; \
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
_mur_h1 = _mur_h1*5+0xe6546b64; \
} \
_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
_mur_k1=0; \
switch((keylen) & 3) { \
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
case 1: _mur_k1 ^= _mur_tail[0]; \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
_mur_h1 ^= _mur_k1; \
} \
_mur_h1 ^= (keylen); \
MUR_FMIX(_mur_h1); \
hashv = _mur_h1; \
bkt = hashv & (num_bkts-1); \
} while(0)
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
do { \
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
else out=NULL; \
while (out) { \
if ((out)->hh.keylen == keylen_in) { \
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
} \
if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
else out = NULL; \
} \
} while(0)
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head,addhh) \
do { \
head.count++; \
(addhh)->hh_next = head.hh_head; \
(addhh)->hh_prev = NULL; \
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
(head).hh_head=addhh; \
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
&& (addhh)->tbl->noexpand != 1) { \
HASH_EXPAND_BUCKETS((addhh)->tbl); \
} \
} while(0)
/* remove an item from a given bucket */
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
(head).count--; \
if ((head).hh_head == hh_del) { \
(head).hh_head = hh_del->hh_next; \
} \
if (hh_del->hh_prev) { \
hh_del->hh_prev->hh_next = hh_del->hh_next; \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
}
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
* the hash function as it applies to the key domain).
*
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
* the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
*
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
* Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
*
* ceil(n/b) = (n/b) + ((n%b)?1:0)
*
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
*
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
*
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
unsigned _he_bkt; \
unsigned _he_bkt_i; \
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
memset(_he_new_buckets, 0, \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->ideal_chain_maxlen = \
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
tbl->nonideal_items = 0; \
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
{ \
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
while (_he_thh) { \
_he_hh_nxt = _he_thh->hh_next; \
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
tbl->nonideal_items++; \
_he_newbkt->expand_mult = _he_newbkt->count / \
tbl->ideal_chain_maxlen; \
} \
_he_thh->hh_prev = NULL; \
_he_thh->hh_next = _he_newbkt->hh_head; \
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
_he_thh; \
_he_newbkt->hh_head = _he_thh; \
_he_thh = _he_hh_nxt; \
} \
} \
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
tbl->num_buckets *= 2; \
tbl->log2_num_buckets++; \
tbl->buckets = _he_new_buckets; \
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
(tbl->ineff_expands+1) : 0; \
if (tbl->ineff_expands > 1) { \
tbl->noexpand=1; \
uthash_noexpand_fyi(tbl); \
} \
uthash_expand_fyi(tbl); \
} while(0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
#define HASH_SRT(hh,head,cmpfcn) \
do { \
unsigned _hs_i; \
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
if (head) { \
_hs_insize = 1; \
_hs_looping = 1; \
_hs_list = &((head)->hh); \
while (_hs_looping) { \
_hs_p = _hs_list; \
_hs_list = NULL; \
_hs_tail = NULL; \
_hs_nmerges = 0; \
while (_hs_p) { \
_hs_nmerges++; \
_hs_q = _hs_p; \
_hs_psize = 0; \
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
_hs_psize++; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
if (! (_hs_q) ) break; \
} \
_hs_qsize = _hs_insize; \
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
if (_hs_psize == 0) { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
_hs_e = _hs_p; \
if (_hs_p){ \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
} \
_hs_psize--; \
} else if (( \
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
) <= 0) { \
_hs_e = _hs_p; \
if (_hs_p){ \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
} \
_hs_psize--; \
} else { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} \
if ( _hs_tail ) { \
_hs_tail->next = ((_hs_e) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
} else { \
_hs_list = _hs_e; \
} \
if (_hs_e) { \
_hs_e->prev = ((_hs_tail) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
} \
_hs_tail = _hs_e; \
} \
_hs_p = _hs_q; \
} \
if (_hs_tail){ \
_hs_tail->next = NULL; \
} \
if ( _hs_nmerges <= 1 ) { \
_hs_looping=0; \
(head)->hh.tbl->tail = _hs_tail; \
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
} \
_hs_insize *= 2; \
} \
HASH_FSCK(hh,head); \
} \
} while (0)
/* This function selects items from one hash into another hash.
* The end result is that the selected items have dual presence
* in both hashes. There is no copy of the items made; rather
* they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
unsigned _src_bkt, _dst_bkt; \
void *_last_elt=NULL, *_elt; \
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
if (src) { \
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
_src_hh; \
_src_hh = _src_hh->hh_next) { \
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
if (cond(_elt)) { \
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
_dst_hh->key = _src_hh->key; \
_dst_hh->keylen = _src_hh->keylen; \
_dst_hh->hashv = _src_hh->hashv; \
_dst_hh->prev = _last_elt; \
_dst_hh->next = NULL; \
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
if (!dst) { \
DECLTYPE_ASSIGN(dst,_elt); \
HASH_MAKE_TABLE(hh_dst,dst); \
} else { \
_dst_hh->tbl = (dst)->hh_dst.tbl; \
} \
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
(dst)->hh_dst.tbl->num_items++; \
_last_elt = _elt; \
_last_elt_hh = _dst_hh; \
} \
} \
} \
} \
HASH_FSCK(hh_dst,dst); \
} while (0)
#define HASH_CLEAR(hh,head) \
do { \
if (head) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
(head)=NULL; \
} \
} while(0)
#define HASH_OVERHEAD(hh,head) \
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
(sizeof(UT_hash_table)) + \
(HASH_BLOOM_BYTELEN)))
#ifdef NO_DECLTYPE
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
#else
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
#endif
/* obtain a count of items in the hash */
#define HASH_COUNT(head) HASH_CNT(hh,head)
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
typedef struct UT_hash_bucket {
struct UT_hash_handle *hh_head;
unsigned count;
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
* the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* (The multiplier is simply expand_mult+1). The whole idea of this
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
* value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
} UT_hash_bucket;
/* random signature used only to find hash tables in external analysis */
#define HASH_SIGNATURE 0xa0111fe1
#define HASH_BLOOM_SIGNATURE 0xb12220f2
typedef struct UT_hash_table {
UT_hash_bucket *buckets;
unsigned num_buckets, log2_num_buckets;
unsigned num_items;
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
/* in an ideal situation (all buckets used equally), no bucket would have
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
unsigned ideal_chain_maxlen;
/* nonideal_items is the number of items in the hash whose chain position
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
/* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
* function isn't a good fit for the key domain. When expansion is inhibited
* the hash will still work, albeit no longer in constant time. */
unsigned ineff_expands, noexpand;
uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOM
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
uint8_t *bloom_bv;
char bloom_nbits;
#endif
} UT_hash_table;
typedef struct UT_hash_handle {
struct UT_hash_table *tbl;
void *prev; /* prev element in app order */
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
#endif /* UTHASH_H */

142
libpcp/include/pcp/util.h Normal file
View File

@@ -0,0 +1,142 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T. von Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
/* various helpers, too small to put into own c */
#ifndef _HAVE_PCP_UTIL_H
#define _HAVE_PCP_UTIL_H
/** \defgroup UTILs UTILS
@{
Various useful helper functions.
*/
#include <ctype.h>
#include <wctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "platform.h"
#include "defines.h"
/** Convert a char array to lowercase.
The supplied char array will be directly modified. Use
a copy if you want to retain the original.
\param[in,out] in The char array to convert.
\return Returns the pointer to the char array.
*/
char *_lc(char *in);
/** Find the offset of some offset marker in some arbitrary data.
Sample input:
@code
ABABABABnacl-98a7sd98a7das98d7
@endcode
If you look for the offset of "nacl" within that data, the
function will return 9, which is the position within the data
where the marker starts.
\param[in] bin Aribrary data where to look for the marker.
\param[in] binlen The size of the data.
\param[in] sigstart The offset marker.
\param[in] hlen Size of the offset marker.
\return Returns the offset or -1 of the offset were not found.
*/
long int _findoffset(byte *bin, size_t binlen, char *sigstart, size_t hlen);
/** XOR an input buffer with another buffer.
Both buffers have to have the same size. The input
buffer will bei modified directly.
\param[in] iv The buffer to XOR with.
\param[in,out] buf The buffer which will be XORed with 'iv'.
\param[in] xlen The size of the buffers (they must have the same size).
*/
void _xorbuf(byte *iv, byte *buf, size_t xlen);
/** Dump binary data as hex to stderr.
\param[in] n Description, string.
\param[in] d Data to print.
\param[in] s Size of d.
*/
void _dump(char *n, byte *d, size_t s);
/** return hex string of binary data
\param[in] bin byte array
\param[in] len size of byte array
\return Returns malloc'd hex string. Caller must free.
*/
char *_bin2hex(byte *bin, size_t len);
/** convert hex string to binary date
\param[in] hex_str hex string
\param[out] byte_array output buffer (malloc'd to byte_array_max)
\param[in] byte_array_max max size allowed for output buffer
\return Returns size of output buffer
*/
size_t _hex2bin(const char *hex_str, unsigned char *byte_array, size_t byte_array_max);
/** compare two memory regions in a constant time
\param[in] m1 array1
\param[in] m2 array2
\param[in] n size in bytes to compare
\return 0 if m1 and m2 are equal up to n
*/
int cst_time_memcmp(const void *m1, const void *m2, size_t n);
// be32toh
uint64_t _wireto64(byte *data);
uint32_t _wireto32(byte *data);
uint16_t _wireto16(byte *data);
// htobe32
void _64towire(uint64_t i, byte *data);
void _32towire(uint32_t i, byte *data);
void _16towire(uint16_t i, byte *data);
#endif /* _HAVE_PCP_UTIL_H */
/**@}*/

230
libpcp/include/pcp/vault.h Normal file
View File

@@ -0,0 +1,230 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_VAULT
#define _HAVE_PCP_VAULT
/** \defgroup VAULT VAULT
@{
The vault file is used to store keys and key-signatures on disk.
It works like a keyring.
\section vformat Vault File Format
The vault file contains all public and secret keys. It's a portable
binary file.
The file starts with a header:
@code
+-------------------------------------------+
| Field Size Description |
+-------------------------------------------+
| File ID | 1 | Vault Identifier 0xC4 |
+-------------------------------------------+
| Version | 4 | Big endian, version |
+-------------------------------------------+
| Checksum | 32 | SHA256 Checksum |
+-------------------------------------------+
@endcode
The checksum is a checksum of all keys.
The header is followed by the keys. Each key is preceded by an
item header which looks like this:
@code
+--------------------------------------------+
| Field Size Description |
+--------------------------------------------+
| Type | 1 | Key type (S,P,M) |
+--------------------------------------------+
| Size | 4 | Big endian, keysize |
+--------------------------------------------+
| Version | 4 | Big endian, keyversion |
+--------------------------------------------+
| Checksum | 32 | SHA256 Key Checksum |
+--------------------------------------------+
@endcode
Type can be one of:
- PCP_KEY_TYPE_MAINSECRET 0x01
- PCP_KEY_TYPE_SECRET 0x02
- PCP_KEY_TYPE_PUBLIC 0x03
The item header is followed by the actual key contents.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sodium.h>
#include <unistd.h>
#include "defines.h"
#include "platform.h"
#include "mem.h"
#include "key.h"
#include "uthash.h"
#include "buffer.h"
#include "keysig.h"
#include "structs.h"
#include "context.h"
/** Open a vault file.
If the file doesn't exist, it will be created.
\param[in] ptx pcp context.
\param[in] filename The filename of the vault file.
\return Returns a vault object.
*/
vault_t *pcpvault_init(PCPCTX *ptx, char *filename);
/* Creates a new vault file. Called internally only.
If is_tmp If set to 1, create a temporary vault file.
*/
vault_t *pcpvault_new(PCPCTX *ptx, char *filename, int is_tmp);
/* Writes the initial vault header to the vault.
Called internally only. */
int pcpvault_create(PCPCTX *ptx, vault_t *vault);
/** Add an item to the vault.
Adds \a item with the size \a itemsize and type \a type
to the vault. Generates the item header and the checksum
of the item.
This function writes directly into the vault file. Use
with care. To be safe, use pcpvault_addkey() instead.
\param[in] ptx pcp context.
\param[out] vault The vault object.
\param[in] item The item to write.
\param[in] itemsize Size of the item.
\param[in] type Type of the item. \see _PCP_KEY_TYPES.
\return Returns the number of bytes written or 0 in case of
an error. Check fatals_if_any().
*/
int pcpvault_additem(PCPCTX *ptx, vault_t *vault, void *item, size_t itemsize, uint8_t type);
/** Add a key to the vault.
This function determines the size of the item to write
based on the given type. It converts the internal structure
to a binary blob and converty multibyte values to big
endian.
It copies the given vault file to a temporary vault file,
adds the item and if this went ok, copies the temporary file
back to the original location. It then re-calculates the
vault checksum and puts it into the vault header.
\param[in] ptx pcp context.
\param[out] vault The vault object.
\param[in] item The item to write (a key or keysig)
\param[in] type Type of the item. \see _PCP_KEY_TYPES.
\return Returns 0 on success or 1 in case of errors. Check fatals_if_any().
*/
int pcpvault_addkey(PCPCTX *ptx, vault_t *vault, void *item, uint8_t type);
/** Close a vault file.
If the vault is in unsafed state, write everything to disk
and close the vault. Before overwriting the current vault file
a backup will be made. If anything fails during writing the
backup file will be retained and the error message will
contain the filename of the backup file, so that the user
doesn't loose data.
\param[in] ptx pcp context.
\param[out] vault The vault object.
\return Returns 0. Check fatals_if_any() anyway.
*/
int pcpvault_close(PCPCTX *ptx, vault_t *vault);
/** Free vault resources
\param[in] vault The vault object.
*/
void pcpvault_free(vault_t *vault);
/** Reads in the vault contents.
This function reads the open vault contents and puts
them into the apropriate hashes. \see KEYHASH.
Currently only known types can be read. If your're saving
unknown types to the vault, an error will occur. \see _PCP_KEY_TYPES.
Each item will be converted put into the aproprieate
structure, multibyte values will be converted to
host endianess. It also calculates the checksum of the vault
contents and compares it with the one stored in the vault
header. If it doesn't match an error will be thrown.
\param[in] ptx pcp context.
\param[out] vault The vault object.
\return Returns 0 on success or -1 in case of errors. Check fatals_if_any().
*/
int pcpvault_fetchall(PCPCTX *ptx, vault_t *vault);
/* Write everything back to disk. */
int pcpvault_writeall(PCPCTX *ptx, vault_t *vault);
/* copy a vault to another file */
int pcpvault_copy(PCPCTX *ptx, vault_t *tmp, vault_t *vault);
/* delete a vault file */
void pcpvault_unlink(vault_t *tmp);
/* calculate the checksum of the current vault (that is, from the
list of keys in the current context */
byte *pcpvault_create_checksum(PCPCTX *ptx);
/* write the new checksum to the header of the current vault */
void pcpvault_update_checksum(PCPCTX *ptx, vault_t *vault);
/* bigendian converters */
vault_header_t * vh2be(vault_header_t *h);
vault_header_t * vh2native(vault_header_t *h);
vault_item_header_t * ih2be(vault_item_header_t *h);
vault_item_header_t * ih2native(vault_item_header_t *h);
#endif /* _HAVE_PCP_VAULT */
/**@}*/

View File

@@ -0,0 +1,35 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2017 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#ifndef _HAVE_PCP_VERSION
#define _HAVE_PCP_VERSION
#define PCP_VERSION_MAJOR 0
#define PCP_VERSION_MINOR 4
#define PCP_VERSION_PATCH 1
#define PCP_VERSION PCP_MAKE_VERSION(PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH)
#define PCP_MAKE_VERSION(major, minor, patch) ((major * 10000) + (minor * 100) + (patch))
int pcp_version();
#endif /* _HAVE_PCP_VERSION */

166
libpcp/include/pcp/z85.h Normal file
View File

@@ -0,0 +1,166 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013-2015 T.v.Dein.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
/* from https://github.com/tlinden/curve-keygen/ */
#ifndef _HAVE_PCP_Z85_H
/**
* \defgroup Z85 Z85
* @{
Z85 Encoding functions.
The Z85 encoding format is described here: <a href="http://rfc.zeromq.org/spec:32">ZeroMQ Spec.32</a>.
It's part of <a href="http://zeromq.org">ZeroMQ</a>. Z85 is based on ASCII85 with
a couple of modifications (portability, readability etc).
To fulfil the requirements of the ZeroMQ Z85 functions, PCP
does some additional preparations of raw input before actually doing the
encoding, since the input for zmq_z85_encode() must be divisible by 4. Therefore
we pad the input with zeroes and remove them after decoding.
*/
#include <ctype.h>
#include "defines.h"
#include "zmq_z85.h"
#include "mem.h"
#include "structs.h"
#include "context.h"
#include "buffer.h"
/** Zero-pad some input data.
This function allocates new memory for the returned data. It puts
the original pointer into it and adds a number of zeros so that the
result has a size divisable by 4.
\param[in] src Unpadded data.
\param[in] srclen Size of unpadded data.
\param[out] dstlen Returned size of padded data (pointer to int).
\return Returns a pointer to the padded data.
*/
byte *pcp_padfour(byte *src, size_t srclen, size_t *dstlen);
/** Decode data from Z85 encoding.
The input \a z85block may contain newlines which will be removed.
\param[in] ptx pcp context object.
\param[in] z85block The Z85 encoded string.
\param[in] dstlen Returned size of decoded data (pointer to int).
\return Returns a newly allocated pointer to the decoded data. If decoding failed,
returns NULL. Check fatals_if_any().
*/
byte *pcp_z85_decode(PCPCTX *ptx, char *z85block, size_t *dstlen);
/** Encode data to Z85 encoding.
Beside Z85 encoding it also adds a newline everiy 72 characters.
It allocates the memory for the returned char pointer. The caller
is responsible the free() it.
\param[in] raw Pointer to raw data.
\param[in] srclen Size of the data.
\param[out] dstlen Returned size of encoded data (pointer to int).
\param[in] doblock If set to 1, turn the encoded data into a 72 chars wide block.
\return Returns a string (char array) containing the Z85 encoded data.
*/
char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock);
/** Read a Z85 encoded file.
Reads a file and returns the raw Z85 encoded string.
It ignores newlines, comments and Headerstrings.
\param[in] ptx pcp context object.
\param[in] infile FILE stream to read from.
\return Raw Z85 encoded string with comments, headers and newlines removed.
*/
char *pcp_readz85file(PCPCTX *ptx, FILE *infile);
/** Read a Z85 encoded string.
Parses the given input string and returns the raw Z85 encoded string.
It ignores newlines, comments and Headerstrings.
\param[in] ptx pcp context object.
\param[in] input Z85 encoded string.
\param[in] bufsize Size of the string.
\return Raw Z85 encoded string with comments, headers and newlines removed.
*/
char *pcp_readz85string(PCPCTX *ptx, byte *input, size_t bufsize);
/** Check if a binary array is utf8.
Based on http://stackoverflow.com/questions/1031645/how-to-detect-utf-8-in-plain-c
by Christoph Gärtner
Modified to only check for one utf8 char. The given sequence must have
at least 4 bytes length. No boundary checks are being made.
\param[in] bytes A byte sequence with 4 or more bytes length.
\return Returns 0 if the sequence is not utf8 or a number greater than 1 indicating the size of the utf8 char.
*/
uint8_t is_utf8(const byte * bytes);
/** Determine if a buffer is binary or ascii.
\param[in] buf The buffer to check.
\param[in] len Len of the buffer.
\return Returns 0 if the input is ascii or a number > 0 if
it contains binary data.
*/
size_t _buffer_is_binary(byte *buf, size_t len);
/** Determine if a char is a Z85 character
\param[out] z Buffer object where to put the char if it's z85 and not inside a comment.
\param[in] c The char to check.
\param[in] is_comment Denotes if we're currently within a comment.
\return Returns 1 if a comment starts or 0 otherwise.
*/
uint8_t _parse_zchar(Buffer *z, uint8_t c, uint8_t is_comment);
long int z85_header_startswith(Buffer *buf, char *what);
int z85_isheader(Buffer *buf);
int z85_isend(Buffer *buf);
int z85_isbegin(Buffer *buf);
int z85_iscomment(Buffer *buf);
int z85_isempty(Buffer *line);
int z85_isencoded(Buffer *line);
#endif /* _HAVE_PCP_Z85_H */
/**@}*/

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ZMQ_Z85_H_INCLUDED__
#define __ZMQ_Z85_H_INCLUDED__
#define __STDC_LIMIT_MACROS
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
uint8_t *zmq_z85_decode (uint8_t *dest, const char *string);
char *zmq_z85_encode (char *dest, const uint8_t *data, size_t size);
#endif