mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-16 19:40:57 +01:00
migrate to codeberg (#21)
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# 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>.
|
||||
#
|
||||
AM_CFLAGS = -I../include/pcp
|
||||
|
||||
lib_LTLIBRARIES = libpcp1.la
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libpcp1.pc
|
||||
|
||||
libpcp1_la_SOURCES = platform.c mem.c version.c \
|
||||
context.c z85.c zmq_z85.c key.c randomart.c \
|
||||
vault.c jenhash.c readpass.c \
|
||||
crypto.c ed.c keyhash.c scrypt.c \
|
||||
util.c buffer.c mgmt.c keysig.c pcpstream.c
|
||||
|
||||
include_HEADERS = ../include/pcp.h
|
||||
|
||||
libpcp1_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=link $(CCLD) $(AM_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
17
libpcp/config.h.in
Normal file
17
libpcp/config.h.in
Normal file
@@ -0,0 +1,17 @@
|
||||
/* platform.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
#mesondefine HAVE_SODIUM
|
||||
#mesondefine HAVE_JSON
|
||||
|
||||
#mesondefine HAVE_GETOPT
|
||||
#mesondefine HAVE_GETOPT_LONG
|
||||
#mesondefine HAVE_SETRLIMIT
|
||||
#mesondefine HAVE_VASPRINTF
|
||||
#mesondefine HAVE_STRNLEN
|
||||
|
||||
#define PACKAGE "pcp"
|
||||
|
||||
#define VERSION "@VERSION@"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
29
libpcp/include/Makefile.am
Normal file
29
libpcp/include/Makefile.am
Normal 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
39
libpcp/include/pcp.h
Normal 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
654
libpcp/include/pcp/buffer.h
Normal 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
|
||||
|
||||
/**@}*/
|
||||
182
libpcp/include/pcp/config.h.in
Normal file
182
libpcp/include/pcp/config.h.in
Normal 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
|
||||
96
libpcp/include/pcp/context.h
Normal file
96
libpcp/include/pcp/context.h
Normal 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
354
libpcp/include/pcp/crypto.h
Normal 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 */
|
||||
|
||||
/**@}*/
|
||||
185
libpcp/include/pcp/defines.h
Normal file
185
libpcp/include/pcp/defines.h
Normal 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
202
libpcp/include/pcp/ed.h
Normal 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 */
|
||||
|
||||
/**@}*/
|
||||
22
libpcp/include/pcp/getpass.h
Normal file
22
libpcp/include/pcp/getpass.h
Normal 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 */
|
||||
25
libpcp/include/pcp/jenhash.h
Normal file
25
libpcp/include/pcp/jenhash.h
Normal 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
324
libpcp/include/pcp/key.h
Normal 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 */
|
||||
|
||||
/**@}*/
|
||||
153
libpcp/include/pcp/keyhash.h
Normal file
153
libpcp/include/pcp/keyhash.h
Normal 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 */
|
||||
|
||||
/**@}*/
|
||||
50
libpcp/include/pcp/keysig.h
Normal file
50
libpcp/include/pcp/keysig.h
Normal 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
58
libpcp/include/pcp/mem.h
Normal 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
195
libpcp/include/pcp/mgmt.h
Normal 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
|
||||
|
||||
/**@}*/
|
||||
291
libpcp/include/pcp/pcpstream.h
Normal file
291
libpcp/include/pcp/pcpstream.h
Normal 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
|
||||
|
||||
|
||||
/**@}*/
|
||||
87
libpcp/include/pcp/platform.h
Normal file
87
libpcp/include/pcp/platform.h
Normal 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 */
|
||||
|
||||
|
||||
83
libpcp/include/pcp/plist.h
Normal file
83
libpcp/include/pcp/plist.h
Normal 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 */
|
||||
54
libpcp/include/pcp/randomart.h
Normal file
54
libpcp/include/pcp/randomart.h
Normal 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 */
|
||||
69
libpcp/include/pcp/readpass.h
Normal file
69
libpcp/include/pcp/readpass.h
Normal 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_ */
|
||||
42
libpcp/include/pcp/scrypt.h
Normal file
42
libpcp/include/pcp/scrypt.h
Normal 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 */
|
||||
|
||||
380
libpcp/include/pcp/structs.h
Normal file
380
libpcp/include/pcp/structs.h
Normal 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
948
libpcp/include/pcp/uthash.h
Executable 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
142
libpcp/include/pcp/util.h
Normal 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
230
libpcp/include/pcp/vault.h
Normal 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 */
|
||||
|
||||
/**@}*/
|
||||
35
libpcp/include/pcp/version.h
Normal file
35
libpcp/include/pcp/version.h
Normal 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
166
libpcp/include/pcp/z85.h
Normal 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 */
|
||||
|
||||
/**@}*/
|
||||
34
libpcp/include/pcp/zmq_z85.h
Normal file
34
libpcp/include/pcp/zmq_z85.h
Normal 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
|
||||
246
libpcp/key.c
246
libpcp/key.c
@@ -19,7 +19,6 @@
|
||||
You can contact me by mail: <tom AT vondein DOT org>.
|
||||
*/
|
||||
|
||||
|
||||
#include "key.h"
|
||||
#include "context.h"
|
||||
|
||||
@@ -36,10 +35,10 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
|
||||
byte *scrypted = pcp_scrypt(ptx, passphrase, plen, nonce, LNONCE);
|
||||
|
||||
/* make a hash from the scrypt() result */
|
||||
crypto_hash_sha256(key, (byte*)scrypted, 64);
|
||||
crypto_hash_sha256(key, (byte *)scrypted, 64);
|
||||
|
||||
/* turn the 32byte hash into a secret key */
|
||||
key[0] &= 248;
|
||||
key[0] &= 248;
|
||||
key[31] &= 127;
|
||||
key[31] |= 64;
|
||||
|
||||
@@ -48,7 +47,6 @@ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) {
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
char *pcp_getkeyid(pcp_key_t *k) {
|
||||
uint32_t s, p;
|
||||
p = jen_hash(k->pub, LBOXPUB, JEN_PSALT);
|
||||
@@ -68,7 +66,8 @@ char *pcp_getpubkeyid(pcp_pubkey_t *k) {
|
||||
return id;
|
||||
}
|
||||
|
||||
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *epk) {
|
||||
void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk,
|
||||
byte *epk) {
|
||||
/* generate keypairs from random seed */
|
||||
byte *ms = urmalloc(32);
|
||||
byte *ss = urmalloc(32);
|
||||
@@ -82,7 +81,7 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
|
||||
|
||||
/* curve25519 secret key */
|
||||
memcpy(csk, cs, 32);
|
||||
csk[0] &= 248;
|
||||
csk[0] &= 248;
|
||||
csk[31] &= 63;
|
||||
csk[31] |= 64;
|
||||
|
||||
@@ -94,7 +93,7 @@ void pcp_keypairs(byte *msk, byte *mpk, byte *csk, byte *cpk, byte *esk, byte *e
|
||||
ucfree(cs, 32);
|
||||
}
|
||||
|
||||
pcp_key_t * pcpkey_new () {
|
||||
pcp_key_t *pcpkey_new() {
|
||||
byte *mp = ucmalloc(LEDPUB);
|
||||
byte *ms = ucmalloc(LEDSEC);
|
||||
byte *sp = ucmalloc(LEDPUB);
|
||||
@@ -107,22 +106,22 @@ pcp_key_t * pcpkey_new () {
|
||||
|
||||
/* fill in our struct */
|
||||
pcp_key_t *key = urmalloc(sizeof(pcp_key_t));
|
||||
memcpy (key->masterpub, mp, LEDPUB);
|
||||
memcpy (key->mastersecret, ms, LEDSEC);
|
||||
memcpy (key->pub, cp, LBOXPUB);
|
||||
memcpy (key->secret, cs, LBOXSEC);
|
||||
memcpy (key->edpub, sp, LEDPUB);
|
||||
memcpy (key->edsecret, ss, LEDSEC);
|
||||
memcpy(key->masterpub, mp, LEDPUB);
|
||||
memcpy(key->mastersecret, ms, LEDSEC);
|
||||
memcpy(key->pub, cp, LBOXPUB);
|
||||
memcpy(key->secret, cs, LBOXSEC);
|
||||
memcpy(key->edpub, sp, LEDPUB);
|
||||
memcpy(key->edsecret, ss, LEDSEC);
|
||||
|
||||
char *id = pcp_getkeyid(key);
|
||||
memcpy (key->id, id, 17);
|
||||
memcpy(key->id, id, 17);
|
||||
free(id);
|
||||
|
||||
key->ctime = (long)time(0);
|
||||
|
||||
key->version = PCP_KEY_VERSION;
|
||||
key->serial = arc4random();
|
||||
key->type = PCP_KEY_TYPE_SECRET;
|
||||
key->serial = arc4random();
|
||||
key->type = PCP_KEY_TYPE_SECRET;
|
||||
|
||||
key->owner[0] = '\0';
|
||||
key->mail[0] = '\0';
|
||||
@@ -138,7 +137,7 @@ pcp_key_t * pcpkey_new () {
|
||||
return key;
|
||||
}
|
||||
|
||||
byte * pcp_gennonce() {
|
||||
byte *pcp_gennonce() {
|
||||
byte *nonce = ucmalloc(LNONCE);
|
||||
arc4random_buf(nonce, LNONCE);
|
||||
return nonce;
|
||||
@@ -150,13 +149,13 @@ void pcpkey_setowner(pcp_key_t *key, char *owner, char *mail) {
|
||||
}
|
||||
|
||||
pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
|
||||
if(key->nonce[0] == 0) {
|
||||
if (key->nonce[0] == 0) {
|
||||
byte *nonce = pcp_gennonce();
|
||||
memcpy (key->nonce, nonce, LNONCE);
|
||||
memcpy(key->nonce, nonce, LNONCE);
|
||||
ucfree(nonce, LNONCE);
|
||||
}
|
||||
|
||||
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
|
||||
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
|
||||
|
||||
byte *encrypted;
|
||||
size_t es;
|
||||
@@ -166,20 +165,20 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
|
||||
buffer_add(both, key->edsecret, LEDSEC);
|
||||
buffer_add(both, key->secret, LBOXSEC);
|
||||
|
||||
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both), key->nonce, encryptkey);
|
||||
es = pcp_sodium_mac(&encrypted, buffer_get(both), buffer_size(both),
|
||||
key->nonce, encryptkey);
|
||||
|
||||
buffer_free(both);
|
||||
sfree(encryptkey);
|
||||
|
||||
if(es == LSEC) {
|
||||
if (es == LSEC) {
|
||||
/* success */
|
||||
memcpy(key->encrypted, encrypted, LSEC);
|
||||
ucfree(encrypted, es);
|
||||
memset(key->secret, 0, LBOXSEC);
|
||||
memset(key->edsecret, 0, LEDSEC);
|
||||
memset(key->mastersecret, 0, LEDSEC);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fatal(ptx, "failed to encrypt the secret key!\n");
|
||||
ucfree(encrypted, es);
|
||||
ucfree(key, sizeof(pcp_key_t));
|
||||
@@ -190,23 +189,23 @@ pcp_key_t *pcpkey_encrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
|
||||
}
|
||||
|
||||
pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
|
||||
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
|
||||
byte *encryptkey = pcp_derivekey(ptx, passphrase, key->nonce);
|
||||
|
||||
byte *decrypted = ucmalloc(LSEC - crypto_secretbox_MACBYTES);
|
||||
size_t es;
|
||||
|
||||
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, LSEC, key->nonce, encryptkey);
|
||||
|
||||
es = pcp_sodium_verify_mac(&decrypted, key->encrypted, LSEC, key->nonce,
|
||||
encryptkey);
|
||||
|
||||
sfree(encryptkey);
|
||||
|
||||
if(es == 0) {
|
||||
if (es == 0) {
|
||||
/* success */
|
||||
memcpy(key->mastersecret, decrypted, LEDSEC);
|
||||
memcpy(key->edsecret, decrypted + LEDSEC, LEDSEC);
|
||||
memcpy(key->edsecret, decrypted + LEDSEC, LEDSEC);
|
||||
memcpy(key->secret, decrypted + LEDSEC + LEDSEC, LBOXSEC);
|
||||
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fatal(ptx, "failed to decrypt the secret key (got %d, expected 32)!\n", es);
|
||||
ucfree(decrypted, LEDSEC + LEDSEC + LBOXSEC);
|
||||
return NULL;
|
||||
@@ -216,7 +215,7 @@ pcp_key_t *pcpkey_decrypt(PCPCTX *ptx, pcp_key_t *key, char *passphrase) {
|
||||
}
|
||||
|
||||
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key) {
|
||||
pcp_pubkey_t *pub = urmalloc(sizeof (pcp_pubkey_t));
|
||||
pcp_pubkey_t *pub = urmalloc(sizeof(pcp_pubkey_t));
|
||||
memcpy(pub->masterpub, key->masterpub, LEDPUB);
|
||||
memcpy(pub->pub, key->pub, LBOXPUB);
|
||||
memcpy(pub->edpub, key->edpub, LEDSEC);
|
||||
@@ -224,9 +223,9 @@ pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key) {
|
||||
memcpy(pub->mail, key->mail, 255);
|
||||
memcpy(pub->id, key->id, 17);
|
||||
pub->version = key->version;
|
||||
pub->type = PCP_KEY_TYPE_PUBLIC;
|
||||
pub->ctime = key->ctime;
|
||||
pub->serial = key->serial;
|
||||
pub->type = PCP_KEY_TYPE_PUBLIC;
|
||||
pub->ctime = key->ctime;
|
||||
pub->serial = key->serial;
|
||||
return pub;
|
||||
}
|
||||
|
||||
@@ -252,7 +251,6 @@ byte *pcpkey_getchecksum(pcp_key_t *k) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
void pcp_pubkeyblob(Buffer *b, pcp_pubkey_t *k) {
|
||||
buffer_add(b, k->masterpub, LEDPUB);
|
||||
buffer_add(b, k->pub, LBOXPUB);
|
||||
@@ -286,8 +284,8 @@ void pcp_seckeyblob(Buffer *b, pcp_key_t *k) {
|
||||
}
|
||||
|
||||
pcp_key_t *pcp_blob2key(Buffer *b) {
|
||||
pcp_key_t *k = ucmalloc(sizeof(pcp_key_t));
|
||||
|
||||
pcp_key_t *k = ucmalloc(sizeof(pcp_key_t));
|
||||
|
||||
buffer_get_chunk(b, k->masterpub, LEDPUB);
|
||||
buffer_get_chunk(b, k->mastersecret, LEDSEC);
|
||||
buffer_get_chunk(b, k->pub, LBOXPUB);
|
||||
@@ -300,17 +298,17 @@ pcp_key_t *pcp_blob2key(Buffer *b) {
|
||||
buffer_get_chunk(b, k->mail, 255);
|
||||
buffer_get_chunk(b, k->id, 17);
|
||||
|
||||
k->type = buffer_get8(b);
|
||||
k->ctime = buffer_get64na(b);
|
||||
k->version = buffer_get32na(b);
|
||||
k->serial = buffer_get32na(b);
|
||||
k->type = buffer_get8(b);
|
||||
k->ctime = buffer_get64na(b);
|
||||
k->version = buffer_get32na(b);
|
||||
k->serial = buffer_get32na(b);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
pcp_pubkey_t *pcp_blob2pubkey(Buffer *b) {
|
||||
pcp_pubkey_t *k = ucmalloc(sizeof(pcp_key_t));
|
||||
|
||||
pcp_pubkey_t *k = ucmalloc(sizeof(pcp_key_t));
|
||||
|
||||
buffer_get_chunk(b, k->masterpub, LEDPUB);
|
||||
buffer_get_chunk(b, k->pub, LBOXPUB);
|
||||
buffer_get_chunk(b, k->edpub, LEDPUB);
|
||||
@@ -318,56 +316,62 @@ pcp_pubkey_t *pcp_blob2pubkey(Buffer *b) {
|
||||
buffer_get_chunk(b, k->mail, 255);
|
||||
buffer_get_chunk(b, k->id, 17);
|
||||
|
||||
k->type = buffer_get8(b);
|
||||
k->ctime = buffer_get64na(b);
|
||||
k->version = buffer_get32na(b);
|
||||
k->serial = buffer_get32na(b);
|
||||
k->valid = buffer_get8(b);
|
||||
k->type = buffer_get8(b);
|
||||
k->ctime = buffer_get64na(b);
|
||||
k->version = buffer_get32na(b);
|
||||
k->serial = buffer_get32na(b);
|
||||
k->valid = buffer_get8(b);
|
||||
return k;
|
||||
}
|
||||
|
||||
Buffer *pcp_keyblob(void *k, int type) {
|
||||
if(type == PCP_KEY_TYPE_PUBLIC) {
|
||||
if (type == PCP_KEY_TYPE_PUBLIC) {
|
||||
Buffer *b = buffer_new(PCP_RAW_PUBKEYSIZE, "bp");
|
||||
pcp_pubkeyblob(b, (pcp_pubkey_t *)k);
|
||||
return b;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Buffer *b = buffer_new(PCP_RAW_KEYSIZE, "bs");
|
||||
pcp_seckeyblob(b, (pcp_key_t *)k);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
|
||||
if(key->pub[0] == 0) {
|
||||
fatal(ptx, "Pubkey sanity check: public key contained in key seems to be empty!\n");
|
||||
if (key->pub[0] == 0) {
|
||||
fatal(ptx, "Pubkey sanity check: public key contained in key seems to be "
|
||||
"empty!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->type != PCP_KEY_TYPE_PUBLIC) {
|
||||
fatal(ptx, "Pubkey sanity check: key type is not PUBLIC (expected: %02x, got: %02x)!\n",
|
||||
if (key->type != PCP_KEY_TYPE_PUBLIC) {
|
||||
fatal(ptx,
|
||||
"Pubkey sanity check: key type is not PUBLIC (expected: %02x, got: "
|
||||
"%02x)!\n",
|
||||
PCP_KEY_TYPE_PUBLIC, key->type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->version != PCP_KEY_VERSION) {
|
||||
fatal(ptx, "Pubkey sanity check: unknown key version (expected: %08X, got: %08X)!\n",
|
||||
if (key->version != PCP_KEY_VERSION) {
|
||||
fatal(ptx,
|
||||
"Pubkey sanity check: unknown key version (expected: %08X, got: "
|
||||
"%08X)!\n",
|
||||
PCP_KEY_VERSION, key->version);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->serial <= 0) {
|
||||
fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n", key->serial);
|
||||
|
||||
if (key->serial <= 0) {
|
||||
fatal(ptx, "Pubkey sanity check: invalid serial number: %08X!\n",
|
||||
key->serial);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->id[16] != '\0') {
|
||||
if (key->id[16] != '\0') {
|
||||
char *got = ucmalloc(17);
|
||||
memcpy(got, key->id, 17);
|
||||
got[16] = '\0';
|
||||
fatal(ptx, "Pubkey sanity check: invalid key id (expected 16 bytes, got: %s)!\n", got);
|
||||
fatal(ptx,
|
||||
"Pubkey sanity check: invalid key id (expected 16 bytes, got: %s)!\n",
|
||||
got);
|
||||
free(got);
|
||||
return 1;
|
||||
}
|
||||
@@ -375,50 +379,63 @@ int pcp_sanitycheck_pub(PCPCTX *ptx, pcp_pubkey_t *key) {
|
||||
struct tm *c;
|
||||
time_t t = (time_t)key->ctime;
|
||||
c = localtime(&t);
|
||||
if(c->tm_year <= 0 || c->tm_year > 1100) {
|
||||
if (c->tm_year <= 0 || c->tm_year > 1100) {
|
||||
/* well, I'm perhaps overacting here :) */
|
||||
fatal(ptx, "Pubkey sanity check: invalid creation timestamp (got year %04d)!\n", c->tm_year + 1900);
|
||||
fatal(ptx,
|
||||
"Pubkey sanity check: invalid creation timestamp (got year %04d)!\n",
|
||||
c->tm_year + 1900);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pcp_pubkey_t *maybe = pcphash_pubkeyexists(ptx, key->id);
|
||||
if(maybe != NULL) {
|
||||
fatal(ptx, "Pubkey sanity check: there already exists a key with the id 0x%s\n", key->id);
|
||||
if (maybe != NULL) {
|
||||
fatal(ptx,
|
||||
"Pubkey sanity check: there already exists a key with the id 0x%s\n",
|
||||
key->id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
|
||||
if(key->encrypted[0] == 0) {
|
||||
fatal(ptx, "Secretkey sanity check: secret key contained in key seems to be empty!\n");
|
||||
if (key->encrypted[0] == 0) {
|
||||
fatal(ptx, "Secretkey sanity check: secret key contained in key seems to "
|
||||
"be empty!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->type != PCP_KEY_TYPE_SECRET && key->type != PCP_KEY_TYPE_MAINSECRET) {
|
||||
fatal(ptx, "Secretkey sanity check: key type is not SECRET (expected: %02x, got: %02x)!\n",
|
||||
if (key->type != PCP_KEY_TYPE_SECRET &&
|
||||
key->type != PCP_KEY_TYPE_MAINSECRET) {
|
||||
fatal(ptx,
|
||||
"Secretkey sanity check: key type is not SECRET (expected: %02x, "
|
||||
"got: %02x)!\n",
|
||||
PCP_KEY_TYPE_SECRET, key->type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->version != PCP_KEY_VERSION) {
|
||||
fatal(ptx, "Secretkey sanity check: unknown key version (expected: %08X, got: %08X)!\n",
|
||||
if (key->version != PCP_KEY_VERSION) {
|
||||
fatal(ptx,
|
||||
"Secretkey sanity check: unknown key version (expected: %08X, got: "
|
||||
"%08X)!\n",
|
||||
PCP_KEY_VERSION, key->version);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->serial <= 0) {
|
||||
fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n", key->serial);
|
||||
|
||||
if (key->serial <= 0) {
|
||||
fatal(ptx, "Secretkey sanity check: invalid serial number: %08X!\n",
|
||||
key->serial);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(key->id[16] != '\0') {
|
||||
if (key->id[16] != '\0') {
|
||||
char *got = ucmalloc(17);
|
||||
memcpy(got, key->id, 17);
|
||||
got[16] = '\0';
|
||||
fatal(ptx, "Secretkey sanity check: invalid key id (expected 16 bytes, got: %s)!\n", got);
|
||||
fatal(ptx,
|
||||
"Secretkey sanity check: invalid key id (expected 16 bytes, got: "
|
||||
"%s)!\n",
|
||||
got);
|
||||
free(got);
|
||||
return 1;
|
||||
}
|
||||
@@ -426,15 +443,21 @@ int pcp_sanitycheck_key(PCPCTX *ptx, pcp_key_t *key) {
|
||||
struct tm *c;
|
||||
time_t t = (time_t)key->ctime;
|
||||
c = localtime(&t);
|
||||
if(c->tm_year <= 70 || c->tm_year > 1100) {
|
||||
if (c->tm_year <= 70 || c->tm_year > 1100) {
|
||||
/* well, I'm perhaps overacting here :) */
|
||||
fatal(ptx, "Secretkey sanity check: invalid creation timestamp (got year %04d)!\n", c->tm_year + 1900);
|
||||
fatal(
|
||||
ptx,
|
||||
"Secretkey sanity check: invalid creation timestamp (got year %04d)!\n",
|
||||
c->tm_year + 1900);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pcp_key_t *maybe = pcphash_keyexists(ptx, key->id);
|
||||
if(maybe != NULL) {
|
||||
fatal(ptx, "Secretkey sanity check: there already exists a key with the id 0x%s\n", key->id);
|
||||
if (maybe != NULL) {
|
||||
fatal(
|
||||
ptx,
|
||||
"Secretkey sanity check: there already exists a key with the id 0x%s\n",
|
||||
key->id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -447,35 +470,43 @@ void pcp_dumpkey(pcp_key_t *k) {
|
||||
printf("Dumping pcp_key_t raw values:\n");
|
||||
|
||||
printf("masterpub: ");
|
||||
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->masterpub[i]);
|
||||
for (i = 0; i < LEDPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->masterpub[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" public: ");
|
||||
for ( i = 0;i < LBOXPUB;++i) printf("%02x",(unsigned int) k->pub[i]);
|
||||
for (i = 0; i < LBOXPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->pub[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" edpub: ");
|
||||
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->edpub[i]);
|
||||
for (i = 0; i < LEDPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->edpub[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("mastersec: ");
|
||||
for ( i = 0;i < LEDSEC;++i) printf("%02x",(unsigned int) k->mastersecret[i]);
|
||||
for (i = 0; i < LEDSEC; ++i)
|
||||
printf("%02x", (unsigned int)k->mastersecret[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" secret: ");
|
||||
for ( i = 0;i < LBOXPUB;++i) printf("%02x",(unsigned int) k->secret[i]);
|
||||
for (i = 0; i < LBOXPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->secret[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" edsecret: ");
|
||||
for ( i = 0;i < LEDSEC;++i) printf("%02x",(unsigned int) k->edsecret[i]);
|
||||
for (i = 0; i < LEDSEC; ++i)
|
||||
printf("%02x", (unsigned int)k->edsecret[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" nonce: ");
|
||||
for ( i = 0;i < LNONCE;++i) printf("%02x",(unsigned int) k->nonce[i]);
|
||||
for (i = 0; i < LNONCE; ++i)
|
||||
printf("%02x", (unsigned int)k->nonce[i]);
|
||||
printf("\n");
|
||||
|
||||
printf("encrypted: ");
|
||||
for ( i = 0;i < LSEC;++i) printf("%02x",(unsigned int) k->encrypted[i]);
|
||||
for (i = 0; i < LSEC; ++i)
|
||||
printf("%02x", (unsigned int)k->encrypted[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" owner: %s\n", k->owner);
|
||||
@@ -493,21 +524,23 @@ void pcp_dumpkey(pcp_key_t *k) {
|
||||
printf(" type: 0x%02X\n", k->type);
|
||||
}
|
||||
|
||||
|
||||
void pcp_dumppubkey(pcp_pubkey_t *k) {
|
||||
unsigned int i;
|
||||
printf("Dumping pcp_pubkey_t raw values:\n");
|
||||
|
||||
printf("masterpub: ");
|
||||
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->masterpub[i]);
|
||||
for (i = 0; i < LEDPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->masterpub[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" public: ");
|
||||
for ( i = 0;i < LBOXPUB;++i) printf("%02x",(unsigned int) k->pub[i]);
|
||||
for (i = 0; i < LBOXPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->pub[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" edpub: ");
|
||||
for ( i = 0;i < LEDPUB;++i) printf("%02x",(unsigned int) k->edpub[i]);
|
||||
for (i = 0; i < LEDPUB; ++i)
|
||||
printf("%02x", (unsigned int)k->edpub[i]);
|
||||
printf("\n");
|
||||
|
||||
printf(" owner: %s\n", k->owner);
|
||||
@@ -525,9 +558,8 @@ void pcp_dumppubkey(pcp_pubkey_t *k) {
|
||||
printf(" type: 0x%02X\n", k->type);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
via
|
||||
via
|
||||
http://rosettacode.org/wiki/Entropy#C
|
||||
*/
|
||||
double pcp_getentropy(char *source) {
|
||||
@@ -535,27 +567,27 @@ double pcp_getentropy(char *source) {
|
||||
int *hist;
|
||||
double H;
|
||||
int wherechar[256];
|
||||
int i,histlen;
|
||||
|
||||
int i, histlen;
|
||||
|
||||
histlen = 0;
|
||||
H = 0;
|
||||
len = (int)strlen(source);
|
||||
hist = (int*)calloc(len, sizeof(int));
|
||||
hist = (int *)calloc(len, sizeof(int));
|
||||
|
||||
for(i=0; i<256; i++)
|
||||
for (i = 0; i < 256; i++)
|
||||
wherechar[i] = -1;
|
||||
|
||||
for(i=0; i<len; i++){
|
||||
if(wherechar[(int)source[i]] == -1) {
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (wherechar[(int)source[i]] == -1) {
|
||||
wherechar[(int)source[i]] = histlen;
|
||||
histlen++;
|
||||
}
|
||||
hist[wherechar[(int)source[i]]]++;
|
||||
}
|
||||
|
||||
for(i=0; i<histlen; i++) {
|
||||
for (i = 0; i < histlen; i++) {
|
||||
H -= (double)hist[i] / len * log2((double)hist[i] / len);
|
||||
}
|
||||
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
64
libpcp/meson.build
Normal file
64
libpcp/meson.build
Normal file
@@ -0,0 +1,64 @@
|
||||
# -*-python-*-
|
||||
|
||||
|
||||
libincludes = include_directories('include', 'include/pcp')
|
||||
|
||||
# check for libraries with CMAKE or pkg-config
|
||||
sodium = dependency('libsodium')
|
||||
|
||||
# manually check for libraries
|
||||
jansson = c.find_library('jansson', required: true,
|
||||
dirs : ['/usr', '/usr/local'])
|
||||
|
||||
conf.set('HAVE_SODIUM', sodium.found())
|
||||
conf.set('HAVE_JSON', jansson.found())
|
||||
|
||||
math = c.find_library('m')
|
||||
|
||||
# add dependencies, manual libs are added directly below
|
||||
pcp_deps = [
|
||||
sodium, jansson, math
|
||||
]
|
||||
|
||||
|
||||
libpcp = shared_library(
|
||||
'pcp',
|
||||
'buffer.c',
|
||||
'context.c',
|
||||
'crypto.c',
|
||||
'ed.c',
|
||||
'getpass.c',
|
||||
'jenhash.c',
|
||||
'key.c',
|
||||
'keyhash.c',
|
||||
'keysig.c',
|
||||
'mem.c',
|
||||
'mgmt.c',
|
||||
'pcpstream.c',
|
||||
'platform.c',
|
||||
'randomart.c',
|
||||
'readpass.c',
|
||||
'scrypt.c',
|
||||
'util.c',
|
||||
'vault.c',
|
||||
'version.c',
|
||||
'z85.c',
|
||||
'zmq_z85.c',
|
||||
include_directories: libincludes,
|
||||
install: true,
|
||||
dependencies: pcp_deps
|
||||
)
|
||||
|
||||
libpcp_dep = declare_dependency(
|
||||
include_directories: libincludes,
|
||||
link_with: libpcp,
|
||||
)
|
||||
|
||||
|
||||
|
||||
# write out the config header
|
||||
m = configure_file(
|
||||
input : 'config.h.in',
|
||||
output : 'config.h',
|
||||
configuration : conf,
|
||||
)
|
||||
536
libpcp/mgmt.c
536
libpcp/mgmt.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user