started documenting the api.

This commit is contained in:
git@daemon.de
2014-02-17 17:05:32 +01:00
parent 1afb5cc3d7
commit be867bdc26
5 changed files with 1695 additions and 191 deletions

View File

@@ -19,18 +19,6 @@
You can contact me by mail: <tom AT vondein DOT org>.
*/
/*
Flexible buffer management, idea from openssh/buffer.c.
This 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.
*/
#ifndef HAVE_PCP_BUFFER_H
#define HAVE_PCP_BUFFER_H
@@ -40,116 +28,551 @@
#include "util.h"
#include "defines.h"
/**
* \defgroup Buffer Buffer, a flexible buffer management class.
* @{
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.
*/
/** \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;
size_t blocksize;
size_t size;
size_t offset; /* read position */
size_t end; /* write position, data end */
uint8_t isstring; /* treat as char array */
void *buf;
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;
/* create a new buffer, initially alloc'd to blocksize and zero-filled */
/** 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);
/* same, but enable isstring */
/** Create a new 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);
/* initialize buffer vars */
void buffer_init(Buffer *b, size_t blocksize, char *name);
/* zero the buffer and free it, if allocated */
/** 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);
/* zero the buffer, reset counters, always called from buffer_free() */
/** 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 to start */
/** 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, memorize end position */
/** 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);
/* the same but use another buffer as source */
/** 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 string, support printf style */
/** 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 some binary data to the buffer, but as hex string */
/** 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 */
/* resize the buffer if necessary, used internally only */
void buffer_resize(Buffer *b, size_t len);
/* return true if there are no more bytes to read */
/** 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);
/* get some chunk of data from the buffer, starting from offset til len */
/** 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
unsigned char 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.
*/
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len);
/* return the whole buffer contents */
/** 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.
*/
unsigned char *buffer_get(Buffer *b);
/* access the buffer content as string (char *) the returned pointer
points to b->buf and should not be free'd directly*/
/** 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);
/* fetch whatever is left in the buffer */
/** 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
[..]
unsigned char g[4];
unsigned char *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).
*/
unsigned char *buffer_get_remainder(Buffer *b);
/* same as buffer_get() but fetch some data chunk from somewhere
in the middle of the buffer */
/** 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
[..]
unsigned char 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);
/* dump the buffer contents to stderr */
/** 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 */
/** 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 */
/** 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 */
/** 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
[..]
unsigned char g[4];
unsigned char 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);
/* same as get_chunk, but return numbers directly */
/** 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);
/* same, but convert to native endian before return */
/** 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);
/* access the last byte(s) as numbers directly, save typing,
in contrast to buffer_get() it doesn't increment offset */
/** 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 from a file directly into a buffer object */
/** 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, call fatals_ifany()
in case of errors.
*/
size_t buffer_fd_read(Buffer *b, FILE *in, size_t len);
/* write numbers as binary into the buffer */
/** 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);
/* the same, but convert to big-endian before doing so */
/** Write a 2 byte (16 bit) number in binary form into the buffer, converted to big endian.
\param[out] b The Buffer object to write to.
\param[in] v The uint16_t to write to the buffer.
*/
void buffer_add16be(Buffer *b, uint16_t v);
/** Write a 4 byte (32 bit) number in binary form into the buffer, converted to big endian.
\param[out] b The Buffer object to write to.
\param[in] v The uint32_t to write to the buffer.
*/
void buffer_add32be(Buffer *b, uint32_t v);
/** Write a 8 byte (64 bit) number in binary form into the buffer, converted to big endian.
\param[out] b The Buffer object to write to.
\param[in] v The uint64_t to write to the buffer.
*/
void buffer_add64be(Buffer *b, uint64_t v);
#endif // HAVE_PCP_BUFFER_H
/**@}*/

View File

@@ -92,21 +92,62 @@ typedef unsigned int qbyte; /* Quad byte = 32 bits */
#define PCP_RFC_CIPHER 0x21 /* curve25519+ed25519+poly1305+salsa20+blake2 */
/**
* \defgroup FATALS global variables and functions for error handling.
* @{
*/
/* error handling */
/** \var PCP_ERR
Global variable holding the last error message.
Can be retrieved with fatals_ifany().
*/
extern char *PCP_ERR;
/** \var PCP_ERRSET
Global variable indicating if an error occurred.
*/
extern byte PCP_ERRSET;
/** \var PCP_EXIT
Exitcode for the pcp commandline utility.
*/
extern int PCP_EXIT;
/* set error */
/** 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] fmt printf() like format description.
\param[in] ... format parameters, if any.
*/
void fatal(const char * fmt, ...);
/* fetch error */
/** Prints error messages to STDERR, if there are some.
FIXME: add something like this which returns the
message.
*/
void fatals_ifany();
/* reset */
/** Reset the error variables.
This can be used to ignore previous errors.
Use with care.
*/
void fatals_reset();
/* free mem */
/** Cleans up memory allocation of global error variables.
*/
void fatals_done();
#endif /* _DEFINES_H */
/**@}*/

View File

@@ -40,11 +40,21 @@
#include "scrypt.h"
#include "keysig.h"
/*
PCP private key structure. Most fields are self explanatory.
/**
* \defgroup PCPKEY PCP public and secret key functions
* @{
*/
/** \struct _pcp_key_t
PCP private key structure. Most fields are self explanatory.
Some notes:
'encrypted' contains the encrypted ed25519 secret key. If it's set,
'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'.
@@ -76,41 +86,55 @@
*/
struct _pcp_key_t {
byte masterpub[32];
byte mastersecret[64];
byte pub[32];
byte secret[32];
byte edpub[32];
byte edsecret[64];
byte nonce[24];
byte encrypted[176]; /* both sign+ed+curve encrypted */
char owner[255];
char mail[255];
char id[17];
uint8_t type;
uint64_t ctime; /* 8 */
uint32_t version; /* 4 */
uint32_t serial; /* 4 */
byte masterpub[32]; /**< ED25519 master public key signing key */
byte mastersecret[64]; /**< ED25519 master secret key signing key */
byte pub[32]; /**< Curve25519 encryption public key */
byte secret[32]; /**< Curve25519 encryption secret key */
byte edpub[32]; /**< ED25519 public signing key */
byte edsecret[64]; /**< ED25519 secret signing key */
byte nonce[24]; /**< random nonce used to encrypt secret keys */
byte encrypted[176]; /**< 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[32];
byte sigpub[32];
byte pub[32];
byte edpub[32];
char owner[255];
char mail[255];
char id[17];
uint8_t type;
uint64_t ctime;
uint32_t version;
uint32_t serial;
uint8_t valid;
byte signature[crypto_generichash_BYTES_MAX + crypto_sign_BYTES];
byte masterpub[32]; /**< ED25519 master public key signing key */
byte sigpub[32]; /**< ED25519 public signing key */
byte pub[32]; /**< Curve25519 encryption public key */
byte edpub[32]; /**< 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 {
@@ -122,9 +146,6 @@ struct _pbp_pubkey_t {
char name[1024];
};
typedef struct _pcp_key_t pcp_key_t;
typedef struct _pcp_pubkey_t pcp_pubkey_t;
typedef struct _pbp_pubkey_t pbp_pubkey_t;
/*
@@ -145,25 +166,212 @@ typedef struct _pcp_rec_t pcp_rec_t;
#define PCP_RAW_PUBKEYSIZE sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle)
/** Generate a new key structure.
void pcp_cleanhashes();
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);
pcp_key_t *pcpkey_encrypt(pcp_key_t *key, char *passphrase);
pcp_key_t *pcpkey_decrypt(pcp_key_t *key, char *passphrase);
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key);
char *pcp_getkeyid(pcp_key_t *k);
char *pcp_getpubkeyid(pcp_pubkey_t *k);
unsigned char *pcppubkey_getchecksum(pcp_pubkey_t *k);
unsigned char *pcpkey_getchecksum(pcp_key_t *k);
void pcp_inithashes();
/** 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,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(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,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(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 unsigned char.
*/
unsigned char *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 unsigned char.
*/
unsigned char *pcpkey_getchecksum(pcp_key_t *k);
/** Checks if a secret key structure is registered in the secret key hash.
Returns a pointer to a pcp_key_t structure if there
exists a secret key structure with the given id in the
secret key hash.
FIXME: needs to be moved to keyhash.h.
\param[in] id A null-terminated char pointer of 17 bytes containing a key-id.
\return Returns a pointer to a pcp_key_t struture or NULL if no key exists.
*/
pcp_key_t *pcpkey_exists(char *id);
/** Checks if a public key structure is registered in the public key hash.
Returns a pointer to a pcp_pubkey_t structure if there
exists a public key structure with the given id in the
public key hash.
FIXME: needs to be moved to keyhash.h.
\param[in] id A null-terminated char pointer of 17 bytes containing a key-id.
\return Returns a pointer to a pcp_pubkey_t struture or NULL if no key exists.
*/
pcp_pubkey_t *pcppubkey_exists(char *id);
pcp_key_t * key2be(pcp_key_t *k);
@@ -171,22 +379,45 @@ 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 unsigned char array.
*/
unsigned char * pcp_gennonce();
void pcpedit_key(char *keyid);
/* use scrypt() to create a key from a passphrase and a nonce */
/* use scrypt() to create a key from a passphrase and a nonce
FIXME: use pure scrypt() instead.
*/
unsigned char *pcp_derivekey(char *passphrase, unsigned char *nonce);
pcp_key_t *pcp_derive_pcpkey (pcp_key_t *ours, char *theirs);
/* FIXME: abandon and use Buffer instead */
void pcp_seckeyblob(void *blob, pcp_key_t *k);
void pcp_pubkeyblob(void *blob, pcp_pubkey_t *k);
void *pcp_keyblob(void *k, int type); /* allocates blob */
/** Make a sanity check of the given public key structure.
\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(pcp_pubkey_t *key);
/** Make a sanity check of the given secret key structure.
\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(pcp_key_t *key);
#endif /* _HAVE_PCP_KEYPAIR_H */
/**@}*/

View File

@@ -43,88 +43,12 @@
/* key management api, export, import, yaml and stuff */
/**
* \defgroup PubKeyExport Key export functions
* @{
*/
/* RFC4880 alike public key export with some modifications:
- Key material is native to us and not specified in the
rfc for curve25519/ed25519. Therefore we're doing it like
so: mp|sp|cp
where mp = master keysigning public key (ed25519), 32 bytes
sp = signing public key (ed25519), 32 bytes
cp = encryption public key (curve25519), 32 bytes
- The various cipher (algorithm) id's are unspecified for
our native ciphers. Therefore I created them, starting at
33 (afaik 22 is the last officially assigned one). Once
those cipher numbers become official, I'll use them instead
of my own.
- The exported public key packet contains a signature. We're
filling out all required fields. A signature has a variable
number of sig sub packets. We use only these types:
2 = Signature Creation Time (4 byte)
3 = Signature Expiration Time (4 byte)
9 = Key Expiration Time (4 bytes)
20 = Notation Data (4 byte flags, N bytes name+value)
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
- We use 3 notation fields:
* "owner", which contains the owner name, if set
* "mail", which contains the emailaddress, if set
* "serial", which contains the 32bit serial number
- The actual signature field consists of the blake2 hash of
(mp|sp|cp|keysig) followed by the nacl signature. However, we do
not put an extra 16byte value of the hash, since the nacl
signature already contains the full hash. So, an implementation
could simply pull the fist 16 bytes of said hash to get
the same result.
- The mp keypair will be used for signing. The recipient can
verify the signature, since mp is included.
- While we put expiration dates for the key and the signature
into the export as the rfc demands, we ignore them. Key expiring
is not implemented in PCP yet.
So, a full pubkey export looks like this
version
ctime
cipher
3 x raw keys \
sigheader > calc hash from this
sigsubs (header+data) /
hash
signature
We use big-endian always.
Unlike RC4880 public key exports, we're using Z85 encoding if
armoring have been requested by the user. Armored output has
a header and a footer line, however they are ignored by the
parser and are therefore optional. Newlines, if present, are
optional as well.
http://tools.ietf.org/html/rfc4880#section-5.2.3
The key sig blob will be saved in the Vault if we import a public key
unaltered, so we can verify the signature at will anytime. When exporting
a foreign public key, we will just put out that key sig blob to the
export untouched.
Currently PCP only support self-signed public key exports.
We only support one key signature per key. However, it would be easily
possible to support foreign keysigs as well in the future.
-----------
Secret key are exported in proprietary format. We just encrypt the
whole structure symmetrically and prepend it with a nonce.
*/
/* various helper structs, used internally only */
struct _pcp_rfc_pubkey_header_t {
@@ -197,29 +121,181 @@ typedef struct _pcp_ks_bundle_t pcp_ks_bundle_t;
#define EXP_FORMAT_PY 5
#define EXP_FORMAT_PERL 6
/** RFC4880 alike public key export with some modifications.
/* export self signed public key from master secret */
RFC4880 alike public key export with the following modifications:
- Key material is native to us and not specified in the
rfc for curve25519/ed25519. Therefore we're doing it like
so: mp|sp|cp
where mp = master keysigning public key (ed25519), 32 bytes
sp = signing public key (ed25519), 32 bytes
cp = encryption public key (curve25519), 32 bytes
- The various cipher (algorithm) id's are unspecified for
our native ciphers. Therefore I created them, starting at
33 (afaik 22 is the last officially assigned one). Once
those cipher numbers become official, I'll use them instead
of my own.
- The exported public key packet contains a signature. We're
filling out all required fields. A signature has a variable
number of sig sub packets. We use only these types:
2 = Signature Creation Time (4 byte)
3 = Signature Expiration Time (4 byte)
9 = Key Expiration Time (4 bytes)
20 = Notation Data (4 byte flags, N bytes name+value)
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
- We use 3 notation fields:
* "owner", which contains the owner name, if set
* "mail", which contains the emailaddress, if set
* "serial", which contains the 32bit serial number
- The actual signature field consists of the blake2 hash of
(mp|sp|cp|keysig) followed by the nacl signature. However, we do
not put an extra 16byte value of the hash, since the nacl
signature already contains the full hash. So, an implementation
could simply pull the fist 16 bytes of said hash to get
the same result.
- The mp keypair will be used for signing. The recipient can
verify the signature, since mp is included.
- While we put expiration dates for the key and the signature
into the export as the rfc demands, we ignore them. Key expiring
is not implemented in PCP yet.
So, a full pubkey export looks like this
version
ctime
cipher
3 x raw keys \
sigheader > calc hash from this
sigsubs (header+data) /
hash
signature
We use big-endian always.
Unlike RC4880 public key exports, we're using Z85 encoding if
armoring have been requested by the user. Armored output has
a header and a footer line, however they are ignored by the
parser and are therefore optional. Newlines, if present, are
optional as well.
http://tools.ietf.org/html/rfc4880#section-5.2.3
The key sig blob will be saved in the Vault if we import a public key
unaltered, so we can verify the signature at will anytime. When exporting
a foreign public key, we will just put out that key sig blob to the
export untouched.
Currently PCP only support self-signed public key exports.
We only support one key signature per key. However, it would be easily
possible to support foreign keysigs as well in the future.
\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 (pcp_key_t *sk);
/* export foreign public key
Buffer *pcp_export_rfc_pub_foreign (pcp_pubkey_t *pub); */
/* export public key in pbp format */
/** 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 public key in yaml format */
/** Export a public key in yaml format.
Export a public key in yaml format.
\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 containing a YAML string.
*/
Buffer *pcp_export_yaml_pub(pcp_key_t *sk);
/* export public key in perl format */
/** Export a public key in perl code format.
Export a public key in perl code format.
\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 containing a perl code string (a hash definition).
*/
Buffer *pcp_export_perl_pub(pcp_key_t *sk);
/* export public key in C format */
/** Export a public key in C code format.
Export a public key in C code format.
\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 containing a C code string.
*/
Buffer *pcp_export_c_pub(pcp_key_t *sk);
/* export secret key */
/** Export secret key.
Export a secret key.
Secret key are exported in proprietary format.
The exported binary blob is symmetrically encrypted using the NACL
function crypto_secret(). The passphrase will be used to derive an
encryption key using the STAR function scrypt().
The binary data before encryption consists of:
- ED25519 master signing secret
- Curve25519 encryption secret
- ED25519 signing secret
- ED25519 master signing public
- Curve25519 encryption public
- ED25519 signing public
- Optional notations, currently supported are the 'owner' and 'mail' attributes.
If an attribute is empty, the len field contains zero.
-# len(VAL) (2 byte uint)
-# VAL (string without trailing zero)
- 8 byte creation time (epoch)
- 4 byte key version
- 4 byte serial number
The encrypted cipher will be prepended with the random nonce used
to encrypt the data and looks after encryption as such:
Nonce | Cipher
\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(pcp_key_t *sk, char *passphrase);
/* import public keys */
pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize);
pcp_ks_bundle_t *pcp_import_pub_rfc(Buffer *blob);
pcp_ks_bundle_t *pcp_import_pub_pbp(Buffer *blob);
@@ -229,3 +305,5 @@ pcp_key_t *pcp_import_secret(unsigned char *raw, size_t rawsize, char *passphras
pcp_key_t *pcp_import_secret_native(Buffer *cipher, char *passphrase);
#endif // _HAVE_PCP_MGMT_H
/**@}*/