mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-16 19:40:57 +01:00
503 lines
13 KiB
C
503 lines
13 KiB
C
#ifndef _HAVE_PCP
|
|
#define _HAVE_PCP
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <inttypes.h> /* uint32_t */
|
|
#include <limits.h>
|
|
#include <sodium.h>
|
|
#include <stddef.h> /* ptrdiff_t */
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdlib.h> /* exit() */
|
|
#include <string.h>
|
|
#include <string.h> /* memcmp,strlen */
|
|
#include <strings.h>
|
|
#include <sys/endian.h>
|
|
#include <sys/endian.h> // FIXME: put portable thing from scrypt here
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <termios.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include CONFIG_H_FILE
|
|
|
|
// +++ from libpcp/crypto.h: +++
|
|
|
|
|
|
|
|
|
|
size_t pcp_sodium_box(unsigned char **cipher,
|
|
unsigned char *cleartext,
|
|
size_t clearsize,
|
|
unsigned char *nonce,
|
|
unsigned char *secret,
|
|
unsigned char *public);
|
|
|
|
int pcp_sodium_verify_box(unsigned char **cleartext, unsigned char* message,
|
|
size_t messagesize, unsigned char *nonce,
|
|
unsigned char *secret, unsigned char *public);
|
|
|
|
unsigned char *pcp_box_encrypt(pcp_key_t *secret, pcp_pubkey_t *public,
|
|
unsigned char *message, size_t messagesize,
|
|
size_t *csize);
|
|
|
|
unsigned char *pcp_box_decrypt(pcp_key_t *secret, pcp_pubkey_t *public,
|
|
unsigned char *cipher, size_t ciphersize,
|
|
size_t *dsize);
|
|
|
|
|
|
// +++ from libpcp/getpass.h: +++
|
|
|
|
|
|
/*
|
|
* (unportable) functions to turn on/off terminal echo
|
|
* using termios functions. might compile however on
|
|
* most unices, tested on FreeBSD only.
|
|
*/
|
|
|
|
|
|
|
|
|
|
void pcp_echo_off();
|
|
void pcp_echo_on();
|
|
char *pcp_get_stdin();
|
|
char *pcp_get_passphrase(char *prompt);
|
|
|
|
|
|
// +++ from libpcp/key.h: +++
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
PCP private key structure. Most fields are self explanatory.
|
|
Some notes:
|
|
|
|
'encrypted' contains the encrypted secret key. 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.
|
|
|
|
'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 public[32];
|
|
byte secret[32];
|
|
byte nonce[24];
|
|
byte encrypted[48];
|
|
char owner[255];
|
|
char mail[255];
|
|
char id[17];
|
|
long ctime;
|
|
uint32_t version;
|
|
uint32_t serial;
|
|
uint8_t type;
|
|
UT_hash_handle hh;
|
|
};
|
|
|
|
struct _pcp_pubkey_t {
|
|
byte public[32];
|
|
char owner[255];
|
|
char mail[255];
|
|
char id[17];
|
|
long ctime;
|
|
uint32_t version;
|
|
uint32_t serial;
|
|
uint8_t type;
|
|
UT_hash_handle hh;
|
|
};
|
|
|
|
typedef struct _pcp_key_t pcp_key_t;
|
|
typedef struct _pcp_pubkey_t pcp_pubkey_t;
|
|
|
|
pcp_key_t *pcpkey_hash;
|
|
pcp_pubkey_t *pcppubkey_hash;
|
|
|
|
void pcp_cleanhashes();
|
|
pcp_key_t *pcpkey_new ();
|
|
|
|
char *pcppubkey_get_art(pcp_pubkey_t *k);
|
|
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);
|
|
unsigned char *pcppubkey_getchecksum(pcp_pubkey_t *k);
|
|
unsigned char *pcpkey_getchecksum(pcp_key_t *k);
|
|
void pcp_inithashes();
|
|
|
|
pcp_key_t *pcpkey_exists(char *id);
|
|
pcp_pubkey_t *pcppubkey_exists(char *id);
|
|
|
|
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);
|
|
|
|
unsigned char * pcp_gennonce();
|
|
|
|
void pcpedit_key(char *keyid);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
// +++ from libpcp/mac.h: +++
|
|
|
|
|
|
|
|
|
|
// how many times do we hash the passphrase
|
|
#define HCYCLES 128000
|
|
|
|
// encrypt some arbitrary cleartext using
|
|
// a curve25519 secret key and a given nonce.
|
|
//
|
|
// expects a pointer to the target binary
|
|
// stream containing the encrypted data,
|
|
// the cleartext string, its size, the nonce
|
|
// (24 bytes) and the secret key (32 bytes).
|
|
//
|
|
// allocates memory for the returned cipher
|
|
// and it is up to the user to free it after use.
|
|
//
|
|
// returns the size of the returned cipherstream.
|
|
// in case of an error, the cipher will be set
|
|
// to NULL.
|
|
size_t pcp_sodium_mac(unsigned char **cipher,
|
|
unsigned char *cleartext,
|
|
size_t clearsize,
|
|
unsigned char *nonce,
|
|
unsigned char *key);
|
|
|
|
// does the opposite of pcp_sodium_mac and decrypts
|
|
// a given encrypted binary stream using a nonce and
|
|
// a secret key (sizes: see above).
|
|
//
|
|
// allocates memory for the returned cleartext and
|
|
// it is up to the user to free it after use.
|
|
//
|
|
// returns 0 if decryption and verification were
|
|
// successful, otherwise -1.
|
|
int pcp_sodium_verify_mac(unsigned char **cleartext,
|
|
unsigned char* message,
|
|
size_t messagesize,
|
|
unsigned char *nonce,
|
|
unsigned char *key);
|
|
|
|
// generate a nonce from random source arc4random().
|
|
// allocates memory for the returned nonce and
|
|
// it is up to the user to free it after use.
|
|
void pcp_makenonce(unsigned char **nonce);
|
|
|
|
// proprietary key derivation function. derives an
|
|
// secure encryption key from the given passphrase by
|
|
// calculating a SALSA20 hash from it HCYCLES times.
|
|
//
|
|
// turns the result into a proper CURVE25519 secret
|
|
// key. allocates memory for key and it is up to the
|
|
// user to free it after use.
|
|
//
|
|
// deprecation warning: maybe removed once the libsodium
|
|
// developers incorporated some key derivation function
|
|
// into libsodium. so far, there's none but word goes
|
|
// that perhaps something like scrypt() from the star
|
|
// distribution may be added in the future.
|
|
unsigned char *pcp_derivekey(char *passphrase);
|
|
|
|
|
|
// +++ from libpcp/mem.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);
|
|
|
|
// the same but it fills the pointer with random values
|
|
void *urmalloc(size_t s);
|
|
|
|
// dito.
|
|
void *ucfree(void *ptr);
|
|
|
|
|
|
|
|
// +++ from libpcp/pad.h: +++
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
#define ZPADCHAR 48
|
|
#else
|
|
#define ZPADCHAR 0
|
|
#endif
|
|
|
|
// prepends a binary stream with a number of
|
|
// \0's as required by the secret_box and
|
|
// secret_box_open functions of libsodium.
|
|
//
|
|
// parameters:
|
|
//
|
|
// padded: destination array (ref)
|
|
// unpadded: source array without padding
|
|
// padlen: length of padding
|
|
// unpadlen: length of source array
|
|
//
|
|
// turns "efa5" into "00000000efa5" with padlen 8
|
|
//
|
|
// if DEBUG is set, destination will be padded with
|
|
// the character '0', NOT the integer 0.
|
|
//
|
|
// allocates memory for padded and it is up to the
|
|
// user to free it after use.
|
|
//
|
|
// sample call:
|
|
//
|
|
// char unpadded[] = {0xef, 0xa5};
|
|
// unsigned char *padded;
|
|
// pcp_pad_prepend(&padded, unpadded, 8, 2);
|
|
//
|
|
// the result, padded, would be 10 bytes long, 8
|
|
// bytes for the leading zeros and 2 for the content
|
|
// of the original unpadded.
|
|
void pcp_pad_prepend(unsigned char **padded, unsigned char *unpadded,
|
|
size_t padlen, size_t unpadlen);
|
|
|
|
// removes zero's of a binary stream, which is
|
|
// the reverse of pcp_pad_prepend().
|
|
//
|
|
// parameters:
|
|
//
|
|
// unpadded: destination array (ref), with padding removed
|
|
// padded: source array with padding
|
|
// padlen: length of padding
|
|
// unpadlen: length of source array
|
|
//
|
|
// turns "00000000efa5" into "efa5" with padlen 8
|
|
//
|
|
// allocates memory for unpadded and it is up to the
|
|
// user to free it after use.
|
|
//
|
|
// sample call:
|
|
//
|
|
// char padded[] = {0x0, 0x0, 0x0, 0x0, 0xef, 0xa5};
|
|
// unsigned char *unpadded;
|
|
// pcp_pad_remove(unpadded, padded, 4, 2);
|
|
//
|
|
// the result, unpadded would be 2 bytes long containing
|
|
// only the 2 bytes we want to have with zeros removed.
|
|
void pcp_pad_remove(unsigned char **unpadded, unsigned char *padded,
|
|
size_t padlen, size_t unpadlen);
|
|
|
|
|
|
|
|
// +++ from libpcp/platform.h: +++
|
|
|
|
|
|
#if defined(CONFIG_H_FILE)
|
|
#elif defined(HAVE_CONFIG_H)
|
|
#else
|
|
#error Need either CONFIG_H_FILE or HAVE_CONFIG_H defined.
|
|
#endif
|
|
|
|
|
|
|
|
// +++ from libpcp/randomart.h: +++
|
|
|
|
/* $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
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
// +++ from libpcp/vault.h: +++
|
|
|
|
|
|
|
|
|
|
|
|
struct _vault_t {
|
|
char *filename;
|
|
FILE *fd;
|
|
uint8_t unsafed;
|
|
uint8_t isnew;
|
|
uint32_t size;
|
|
time_t modified;
|
|
mode_t mode;
|
|
uint32_t version;
|
|
byte checksum[32];
|
|
};
|
|
|
|
struct _vault_header_t {
|
|
byte fileid;
|
|
uint32_t version;
|
|
byte checksum[32];
|
|
};
|
|
|
|
struct _vault_item_header_t {
|
|
byte type;
|
|
uint32_t size;
|
|
uint32_t version;
|
|
byte checksum[32];
|
|
};
|
|
|
|
typedef struct _vault_t vault_t;
|
|
typedef struct _vault_header_t vault_header_t;
|
|
typedef struct _vault_item_header_t vault_item_header_t;
|
|
|
|
vault_t *pcpvault_init(char *filename);
|
|
vault_t *pcpvault_new(char *filename, int is_tmp);
|
|
int pcpvault_create(vault_t *vault);
|
|
int pcpvault_additem(vault_t *vault, void *item, size_t itemsize, uint8_t type, uint8_t do_hash);
|
|
int pcpvault_close(vault_t *vault);
|
|
int pcpvault_fetchall(vault_t *vault);
|
|
int pcpvault_writeall(vault_t *vault);
|
|
void pcpvault_copy(vault_t *tmp, vault_t *vault);
|
|
void pcpvault_unlink(vault_t *tmp);
|
|
unsigned char *pcpvault_create_checksum(vault_t *vault);
|
|
void pcpvault_update_checksum(vault_t *vault);
|
|
|
|
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);
|
|
|
|
|
|
// +++ from libpcp/version.h: +++
|
|
|
|
|
|
#define PCP_VERSION_MAJOR 0
|
|
#define PCP_VERSION_MINOR 0
|
|
#define PCP_VERSION_PATCH 1
|
|
|
|
#define PCP_MAKE_VERSION(major, minor, patch) \
|
|
((major) * 10000 + (minor) * 100 + (patch))
|
|
#define PCP_VERSION \
|
|
PCP_MAKE_VERSION(PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH)
|
|
|
|
int pcp_version();
|
|
|
|
|
|
// +++ from libpcp/warn.h: +++
|
|
|
|
|
|
#ifdef HAVE_ERR_H
|
|
#else
|
|
#define NEED_WARN_PROGNAME
|
|
const char * warn_progname;
|
|
void warn(const char *, ...);
|
|
void warnx(const char *, ...);
|
|
#endif
|
|
|
|
|
|
// +++ from libpcp/z85.h: +++
|
|
|
|
// from https://github.com/tlinden/curve-keygen/
|
|
|
|
|
|
// convert a binary stream to one which gets accepted by zmq_z85_encode
|
|
// we pad it with zeroes and put the number of zerores in front of it
|
|
unsigned char *pcp_unpadfour(unsigned char *src, size_t srclen, size_t *dstlen);
|
|
|
|
// the reverse of the above
|
|
unsigned char *pcp_unpadfour(unsigned char *src, size_t srclen, size_t *dstlen);
|
|
|
|
// wrapper around zmq Z85 encoding function
|
|
unsigned char *pcp_z85_decode(char *z85block, size_t *dstlen);
|
|
|
|
// the reverse of the above
|
|
char *pcp_z85_encode(unsigned char *raw, size_t srclen, size_t *dstlen);
|
|
|
|
char *pcp_readz85file(FILE *infile);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
|
|
#endif
|