Ejemplo n.º 1
0
/**
 * @brief
 *  Serialize an EC public key to be shared.
 * @param
 *  key a pointer to the EC key pair to have its public key serialized.
 * @param
 *  outsize a pointer to a variable that will receive the length of the
 *  serialized key on success.
 * @return
 *  a pointer to the serialized EC public key on success, or NULL on failure.
 */
unsigned char * _serialize_ec_pubkey(EC_KEY *key, size_t *outsize) {
	unsigned char *buf = NULL;

	if (!key || !outsize) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	stringer_t *pub;
	if (!(pub = secp256k1_public_get(key, MANAGEDBUF(33)))) {
		PUSH_ERROR_OPENSSL();
		RET_ERROR_PTR(ERR_UNSPEC, "unable to serialize EC public key");
	}

	buf = mm_alloc(33);
	memmove(buf, st_data_get(pub), st_length_get(pub));

	*outsize = st_length_get(pub);

//    EC_KEY_set_conv_form_d(key, POINT_CONVERSION_COMPRESSED);
//    if ((bsize = i2o_ECPublicKey_d(key, &buf)) < 0) {
//        PUSH_ERROR_OPENSSL();
//        RET_ERROR_PTR(ERR_UNSPEC, "unable to serialize EC public key");
//    }

//    *outsize = bsize;

	return buf;
}
Ejemplo n.º 2
0
/**
 * @brief	Retrieves the encryption key from the keys file.
 * @param	filename	Null terminated filename string.
 * @return	Pointer to the elliptic curve encryption key.
 * @free_using{free_ec_key}
*/
static EC_KEY *keys_fetch_enc_key(const char *filename) {

	size_t keys_len;
	unsigned char *keys_bin;
	EC_KEY *key;

	if(!filename) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	} else if(!strlen(filename)) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if(!(keys_bin = keys_file_serialize(filename, &keys_len))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not retrieve keys binary string");
	}

	key = keys_serial_get_enc_key(keys_bin, keys_len);
	_secure_wipe(keys_bin, keys_len);
	free(keys_bin);

	if (!key) {
		RET_ERROR_PTR_FMT(ERR_UNSPEC, "could not retrieve ed25519 signing key from %s", filename);
	}

	return key;
}
Ejemplo n.º 3
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Clone a pointer chain.
 * @param buf
 *  a pointer to the pointer chain to be cloned.
 * @return
 *  a pointer to the cloned pointer chain on success, or NULL on failure.
 * @free_usingref{ptr_chain_free}
 */
void *
_ptr_chain_clone(void *buf) {
	unsigned char **result, **inptr = (unsigned char **)buf;
	size_t totsize;
	int nitems;

	if (!buf) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if ((nitems = _count_ptr_chain(buf)) < 0) {
		RET_ERROR_PTR(ERR_UNSPEC, "unable to count items in pointer chain");
	}
	else if (!nitems) {
		RET_ERROR_PTR(ERR_UNSPEC, "cannot clone empty pointer chain");
	}

	totsize = (nitems + 1) * sizeof(unsigned char *);

	if (!(result = malloc(totsize))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, NULL);
	}

	memset(result, 0, totsize);

	for (int i = 0; i < nitems; i++) {
		result[i] = inptr[i];
	}

	return result;
}
Ejemplo n.º 4
0
/**
 * @brief
 *  Load an EC public key from a file.
 * @param filename
 *  the name of the file from which the key should be loaded
 * @return
 *  a pointer to the deserialized public key from the the file.
 */
EC_KEY * _load_ec_pubkey(char const *filename) {
	char *filedata;
	unsigned char *bin;
	size_t binsize;
	EC_KEY *result;

	if (!filename) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(filedata = _read_pem_data(filename, "PUBLIC KEY", 1))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not read ec pubkey pem file");
	}

	bin = _b64decode(filedata, strlen(filedata), &binsize);
	_secure_wipe(filedata, strlen(filedata));
	free(filedata);
	if (!bin) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not decode b64 data");
	}

	result = _deserialize_ec_pubkey(bin, binsize);
	_secure_wipe(bin, binsize);
	free(bin);
	if (!result) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not deserialize binary ec pubkey");
	}

	return result;
}
Ejemplo n.º 5
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Decode a base64-encoded string without any padding characters and return
 *  the result.
 * @param buf
 *  a pointer to a buffer containing the data to be decoded.
 * @param len
 *  the length, in bytes, of the buffer to be decoded.
 * @param outlen
 *  a pointer to a variable to receive the length of the decoded data.
 * @return
 *  a pointer to a newly allocated buffer containing the base64-decoded, or
 *  NULL on failure.
 * @free_using{free}
 */
unsigned char *
_b64decode_nopad(char const *buf, size_t len, size_t *outlen) {
	unsigned char *result;
	char *padded;
	size_t padlen;

	if (!buf || !len || !outlen) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(len % 4)) {
		return (_b64decode(buf, len, outlen));
	}

	padlen = (len + 4) & ~(3);

	if (!(padded = malloc(padlen + 1))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, "could not allocate space for temporary string");
	}

	memset(padded, '=', padlen);
	padded[padlen] = 0;
	memcpy(padded, buf, len);

	result = _b64decode(padded, padlen, outlen);
	free(padded);

	return result;
}
Ejemplo n.º 6
0
/**
 * @brief
 *  Sign a body of data using the ECDSA algorithm.
 * @param hash
 *  a pointer to the hashed data buffer to be signed.
 * @param hlen
 *  the length, in bytes, of the hashed data to be signed.
 * @param key
 *  the EC key which will have its private portion used to sign the supplied data.
 * @param siglen
 *  a pointer to a variable that will receive the length of the data signature
 *  buffer on success.
 * @return
 *  NULL on failure, or a pointer to the newly allocated signature data buffer
 *  on success.
 */
unsigned char * _ec_sign_data(unsigned char const *hash, size_t hlen, EC_KEY *key, size_t *siglen) {
	ECDSA_SIG *signature;
	unsigned char *buf = NULL;
	int bsize;

	if (!hash || !hlen || !key || !siglen) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(signature = ECDSA_do_sign_d(hash, hlen, key))) {
		PUSH_ERROR_OPENSSL();
		RET_ERROR_PTR(ERR_UNSPEC, "unable to take ECDSA signature of hash buffer");
	}

	if ((bsize = i2d_ECDSA_SIG_d(signature, &buf)) < 0) {
		PUSH_ERROR_OPENSSL();
		ECDSA_SIG_free_d(signature);
		RET_ERROR_PTR(ERR_UNSPEC, "unable to serialize ECDSA signature");
	}

	ECDSA_SIG_free_d(signature);

	*siglen = bsize;

	return buf;
}
Ejemplo n.º 7
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Get the human-readable, US-specific representation of a specified UNIX
 *  time.
 * @param time
 *  the time to be converted to a human-readable string.
 * @param local
 *  if set, return the time string as a local time; if not, as UTC.
 * @return
 *  a string containing the formatted date-time; or NULL on errors.
 * @free_using{free}
 */
char *
_get_chr_date(time_t time, int local) {
	struct tm tmr;
	char tbuf[64];
	char *result;
	const char *local_fmt = "%H:%M:%S %a %b %d %Y";
	char const *utc_fmt = "%H:%M:%S %a %b %d %Y (UTC)";

	if (local && (!localtime_r(&time, &tmr))) {
		RET_ERROR_PTR(ERR_UNSPEC, "error occurred formatting local date-time");
	}
	else if (!local && (!gmtime_r(&time, &tmr))) {
		RET_ERROR_PTR(ERR_UNSPEC, "error occurred formatting UTC date-time");
	}

	memset(tbuf, 0, sizeof(tbuf));

	if (!strftime(tbuf, sizeof(tbuf), (local ? local_fmt : utc_fmt), &tmr)) {
		RET_ERROR_PTR(ERR_UNSPEC, "error occurred packaging date-time");
	}

	if (!(result = strdup(tbuf))) {
		PUSH_ERROR_SYSCALL("strdup");
		RET_ERROR_PTR(ERR_NOMEM, "could not allocate space for date-time string");
	}

	return result;
}
Ejemplo n.º 8
0
/**
 * @brief
 *  Deserialize an EC public key stored in binary format.
 * @param buf
 *  a pointer to the buffer holding the EC public key in binary format.
 * @param blen
 *  the length, in bytes, of the buffer holding the EC public key.
 * @return
 *  a pointer to the deserialized EC public key on success, or NULL on failure.
 */
EC_KEY * _deserialize_ec_pubkey(unsigned char const *buf, size_t blen) {
	EC_KEY *result;

	if (!buf || !blen) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(result = EC_KEY_new_d())) {
		PUSH_ERROR_OPENSSL();
		RET_ERROR_PTR(ERR_UNSPEC, "could not generate new EC key for deserialization");
	}

	if (EC_KEY_set_group_d(result, EC_GROUP_new_by_curve_name_d(NID_secp256k1)) != 1) {
		PUSH_ERROR_OPENSSL();
		EC_KEY_free_d(result);
		RET_ERROR_PTR(ERR_UNSPEC, "could not get curve group for deserialization");
	}

	if (!(result = o2i_ECPublicKey_d(&result, (const unsigned char **)&buf, blen))) {
		PUSH_ERROR_OPENSSL();
		EC_KEY_free_d(result);
		RET_ERROR_PTR(ERR_UNSPEC, "deserialization of EC public key portion failed");
	}

	return result;
}
Ejemplo n.º 9
0
/**
 * @brief
 *  Sign a SHA-hashed body of data using the ECDSA algorithm.
 * @param data
 *  a pointer to the data buffer to be signed.
 * @param dlen
 *  the length, in bytes, of the data buffer to be signed.
 * @param
 *  shabits the number of bits for the desired SHA hash (160, 256, or 512).
 * @param key
 *  the EC key which will have its private portion used to sign the supplied
 *  data.
 * @param siglen
 *  a pointer to a variable that will receive the length of the data signature
 *  buffer on success.
 * @return
 *  NULL on failure, or a pointer to the newly allocated signature data buffer
 *  on success.
 */
unsigned char * _ec_sign_sha_data(unsigned char const *data, size_t dlen, unsigned int shabits, EC_KEY *key, size_t *siglen) {
	unsigned char hashbuf[SHA_512_SIZE];

	if (!data || !dlen || !key || !siglen) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}
	else if ((shabits != 160) && (shabits != 256) && (shabits != 512)) {
		RET_ERROR_PTR(ERR_BAD_PARAM, "ECDSA signature only accepts SHA hash sizes of 160, 256, or 512 bits");
	}

	if (_compute_sha_hash(shabits, data, dlen, hashbuf) < 0) {
		RET_ERROR_PTR(ERR_UNSPEC, "unable to compute SHA hash for ECDSA signature operation");
	}

	return (_ec_sign_data(hashbuf, shabits / 8, key, siglen));
}
Ejemplo n.º 10
0
/**
 * @brief
 *  Deserializes an ed25519 public key into a public-only ED25519_KEY structure
 *  that can only be used for signature verification, not signing.
 * @param serial_pubkey
 *  Serialized ed25519 public key.
 * @return
 *  Pointer to ED25519_KEY structure.
 */
ED25519_KEY * _deserialize_ed25519_pubkey(unsigned char const *serial_pubkey) {
	ED25519_KEY *key;

	if (!serial_pubkey) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(key = malloc(sizeof(ED25519_KEY)))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, NULL);
	}

	memset(key, 0, sizeof(ED25519_KEY));
	memcpy(key->public_key, serial_pubkey, ED25519_KEY_SIZE);

	return key;
}
Ejemplo n.º 11
0
/**
 * @brief
 *  Load an ed25519 private key from a file.
 * @param filename
 *  the path of the armored file from which the ed25519 private key will be
 *  loaded.
 * @return
 *  a pointer to a newly allocated ed25519 keypair on success, or NULL on
 *  failure.
 */
ED25519_KEY * _load_ed25519_privkey(char const *filename) {
	ED25519_KEY *result;
	unsigned char *keydata;
	char *pemdata;
	size_t klen;

	if (!filename) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(pemdata = _read_pem_data(filename, "ED25519 PRIVATE KEY", 1))) {
		RET_ERROR_PTR(ERR_UNSPEC, "unable to read ed25519 private key data from PEM file");
	}

	keydata = _b64decode(pemdata, strlen(pemdata), &klen);
	_secure_wipe(pemdata, strlen(pemdata));
	free(pemdata);

	if (!keydata || (klen != ED25519_KEY_SIZE)) {

		if (keydata) {
			_secure_wipe(keydata, klen);
			free(keydata);
		}

		RET_ERROR_PTR(ERR_UNSPEC, "bad ED25519 key data was read from file");
	}

	if (!(result = malloc(sizeof(ED25519_KEY)))) {
		PUSH_ERROR_SYSCALL("malloc");
		_secure_wipe(keydata, klen);
		free(keydata);
		RET_ERROR_PTR(ERR_NOMEM, "unable to allocate space for ED25519 key");
	}

	memset(result, 0, sizeof(ED25519_KEY));
	memcpy(result->private_key, keydata, sizeof(result->private_key));
	_secure_wipe(keydata, klen);
	free(keydata);
	ed25519_publickey_donna(result->private_key, result->public_key);

	return result;
}
Ejemplo n.º 12
0
/**
 * @brief
 *  Serialize an EC private key into a data buffer.
 * @param key
 *  a pointer to the EC key pair to have its private key serialized.
 * @param outsize
 *  a pointer to a variable that will receive the length of the serialized key
 *  on success.
 * @return
 *  a pointer to the serialized EC private key on success, or NULL on failure.
 */
unsigned char * _serialize_ec_privkey(EC_KEY *key, size_t *outsize) {
	unsigned char *buf = NULL;

	if (!key || !outsize) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	stringer_t *priv;
	buf = mm_alloc(32);

	if (!(priv = secp256k1_private_get(key, PLACER(buf, 32)))) {
		//  if ((bsize = i2d_ECPrivateKey_d(key, &buf)) < 0) {
		PUSH_ERROR_OPENSSL();
		RET_ERROR_PTR(ERR_UNSPEC, "unable to serialize EC private key");
	}

	*outsize = 32;

	return buf;
}
Ejemplo n.º 13
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Return the base64-encoded string of a data buffer without padding.
 * @note
 *  This function ensures the smallest possible output length with no trailing
 *  '=' characters.
 * @param buf
 *  a pointer to the data buffer to be base-64 encoded.
 * @param len
 *  the length, in bytes, of the buffer to be encoded.
 * @return
 *  a pointer to a newly allocated null-terminated string containing the
 *  base64-encoded data, or NULL on failure.
 * @free_using{free}
 */
char *
_b64encode_nopad(unsigned char const *buf, size_t len) {
	char *result, *ptr;

	if (!buf || !len) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if (!(result = _b64encode(buf, len))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not base64 encode input");
	}

	ptr = result + strlen(result) - 1;

	while ((ptr >= result) && (*ptr == '=')) {
		*ptr-- = 0;
	}

	return result;
}
Ejemplo n.º 14
0
/**
 * @brief	Retrieves the keys binary from the keys file.
 * @param	filename	Null terminated string containing specified filename.
 * @param	len		Pointer to the length of the output.
 * @return	Pointer to the keys binary string, this memory needs to be wipe before being freed. NULL on error.
 * @free_using{free}
*/
static unsigned char *keys_file_serialize(const char *filename, size_t *len) {

	char *b64_keys = NULL;
	unsigned char *serial_keys = NULL;

	if(!filename || !len) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	if(!(b64_keys = _read_pem_data(filename, SIGNET_PRIVATE_KEYCHAIN, 1))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not retrieve keys from PEM file");
	}

	if(!(serial_keys = _b64decode(b64_keys, strlen(b64_keys), len))) {
		free(b64_keys);
		RET_ERROR_PTR(ERR_UNSPEC, "could not base64 decode the keys");
	}

	free(b64_keys);

	return serial_keys;
}
Ejemplo n.º 15
0
/**
 * @brief
 *  Generate an ed25519 key pair.
 * @return
 *  a newly allocated and generated ed25519 key pair on success, or NULL on
 *  failure.
 */
ED25519_KEY * _generate_ed25519_keypair(void) {
	ED25519_KEY *result;

	if (!(result = malloc(sizeof(ED25519_KEY)))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, "could not generate ed25519 key because of "
			"memory allocation error");
	}

	memset(result, 0, sizeof(ED25519_KEY));

	if (RAND_bytes_d(result->private_key, sizeof(result->private_key)) != 1) {
		PUSH_ERROR_OPENSSL();
		_secure_wipe(result, sizeof(ED25519_KEY));
		free(result);
		RET_ERROR_PTR(ERR_UNSPEC, "could not generate ed25519 secret key");
	}

	ed25519_publickey_donna(result->private_key, result->public_key);

	return result;
}
Ejemplo n.º 16
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Return a simple hex string representing a data buffer.
 * @param buf
 *  a pointer to the data buffer to be encoded as a hex string.
 * @param len
 *  the size, in bytes, of the buffer to be processed.
 * @return
 *  NULL on failure, or a newly allocated null-terminated string containing the
 *  hex encoded input on success.
 * @free_using{free}
 */
char *
_hex_encode(unsigned char const *buf, size_t len) {
	char *result;
	size_t newlen;

	if (!buf || !len) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	newlen = (len * 2) + 1;

	if (!(result = malloc(newlen))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, "unable to allocate space for hex string");
	}

	memset(result, 0, newlen);

	for (size_t i = 0; i < len; i++) {
		snprintf(&(result[i * 2]), 3, "%.2x", (unsigned char)buf[i]);
	}

	return result;
}
Ejemplo n.º 17
0
/**
 * @brief	Retrieves the encryption key from the keys binary.
 * @param	bin_keys        Pointer to the keys buffer.
 * @param	len		Length of the keys buffer.
 * @return	Pointer to elliptic curve key, NULL if an error occurred.
 * @free_using{free_ec_key}
*/
static EC_KEY *keys_serial_get_enc_key(const unsigned char *bin_keys, size_t len) {

        /* unsigned char sign_fid, enc_fid; sign_fid is unused causing errors on 
           compilation */
        unsigned char enc_fid;
	size_t at = 0, privkeylen;
	EC_KEY *enc_key = NULL;

	if(!bin_keys) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	} else if(keys_check_length(bin_keys, len) < 0) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	switch(keys_type_get(bin_keys, len)) {

	case KEYS_TYPE_ORG:
		/* sign_fid = KEYS_ORG_PRIVATE_POK; */
		enc_fid = KEYS_ORG_PRIVATE_ENC;
		break;
	case KEYS_TYPE_USER:
		/* sign_fid = KEYS_USER_PRIVATE_SIGN; */
		enc_fid = KEYS_USER_PRIVATE_ENC;
		break;
	default:
		RET_ERROR_PTR(ERR_UNSPEC, "invalid keys type");
		break;

	}

	at = KEYS_HEADER_SIZE;

	while(bin_keys[at++] != enc_fid) {
		at += bin_keys[at] + 1;

		if(len <= at) {
			RET_ERROR_PTR(ERR_UNSPEC, "no private encryption key in keys file");
		}
	}

	privkeylen = _int_no_get_2b(bin_keys+at);
	at += 2;

	if(at + privkeylen > len) {
		RET_ERROR_PTR(ERR_UNSPEC, "invalid encryption key size");
	}

	if(!(enc_key = _deserialize_ec_privkey(bin_keys + at, privkeylen, 0))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not deserialize private EC encryption key");
	}

	return enc_key;
}
Ejemplo n.º 18
0
/**
 * @brief
 *  Deserialize an EC private key stored in binary format.
 * @param buf
 *  a pointer to the buffer holding the EC private key in binary format.
 * @param blen
 *  the length, in bytes, of the buffer holding the EC private key.
 * @return
 *  a pointer to the deserialized EC private key on success, or NULL on
 *  failure.
 */
EC_KEY * _deserialize_ec_privkey(unsigned char const *buf, size_t blen) {
	EC_KEY *result;
	const unsigned char *bufptr = buf;

	if (!buf || !blen) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	result = secp256k1_private_set(PLACER((unsigned char *)bufptr, blen));

	/*
	 * At this point, in most cases bufptr == buf + blen. There may be cases
	 * though where the private key is shorter than the provided buffer. This
	 * is because DER is a variable-length encoding. Parsing any field behind
	 * the privkey must take this into account.
	 */

	return result;
}
Ejemplo n.º 19
0
/**
 * @brief Retrieves the signing key from the keys binary.
 * @param	bin_keys	Pointer to the keys buffer.
 * @param	len		Length of the keys buffer.
 * @return	Pointer to ed25519 signing key, NULL if an error occurred.
 * @free_using{free_ed25519_key}
*/
static ED25519_KEY *keys_serial_get_sign_key(const unsigned char *bin_keys, size_t len) {

	unsigned char sign_fid;
	unsigned int at = 0;
	ED25519_KEY *sign_key;

	if(!bin_keys) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	} else if(keys_check_length(bin_keys, len) < 0) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	} else if(len < KEYS_HEADER_SIZE + 2 + ED25519_KEY_SIZE) {
		RET_ERROR_PTR(ERR_BAD_PARAM, "keys buffer too small for signing key");
	}

	switch(keys_type_get(bin_keys, len)) {

	case KEYS_TYPE_ORG:
		sign_fid = KEYS_ORG_PRIVATE_POK;
		break;
	case KEYS_TYPE_USER:
		sign_fid = KEYS_USER_PRIVATE_SIGN;
		break;
	default:
		RET_ERROR_PTR(ERR_UNSPEC, "invalid keys type");
		break;

	}

	at = KEYS_HEADER_SIZE;

	if(bin_keys[at++] != sign_fid) {
		RET_ERROR_PTR(ERR_UNSPEC, "no signing key was found");
	}

	if(bin_keys[at++] != ED25519_KEY_SIZE) {
		RET_ERROR_PTR(ERR_UNSPEC, "invalid size of signing key");
	}

	if(!(sign_key = _deserialize_ed25519_privkey(bin_keys + at))) {
		RET_ERROR_PTR(ERR_UNSPEC, "could not deserialize ed25119 signing key");
	}

	return sign_key;
}
Ejemplo n.º 20
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Append an address to the end of a pointer chain.
 * @param buf
 *  the address of the target pointer chain. If NULL, allocate a new one for
 *  the caller.
 * @param addr
 *  the address to be appended to the pointer chain.
 */
void *
_ptr_chain_add(void *buf, const void *addr) {
	unsigned char **newbuf, **ptr = (unsigned char **)buf, **obuf;
	size_t bufsize = sizeof(unsigned char *);

	// Get the entire size of the buffer, if it's not NULL.
	if (buf) {

		while (*ptr) {
			ptr++;
		}

		ptr++;
		bufsize = (unsigned long)ptr - (unsigned long)buf;
	}

	// Reallocate with space for one more pointer at the end of it.
	if (!(newbuf = realloc((obuf = buf), bufsize + sizeof(unsigned char *)))) {
		PUSH_ERROR_SYSCALL("realloc");

		if (obuf) {
			free(obuf);
		}

		RET_ERROR_PTR(ERR_NOMEM, "unable to lengthen pointer chain");
	}

	if (!buf) {
		ptr = (unsigned char **)newbuf;
	}
	else {
		ptr = (unsigned char **)((unsigned char *)newbuf + bufsize - sizeof(unsigned char *));
	}

	// Replace the next-to-last entry in the new pointer chain with our
	// address, then follow it with a terminating NULL pointer.
	*ptr++ = (unsigned char *)addr;
	*ptr = NULL;

	return newbuf;
}
Ejemplo n.º 21
0
Archivo: misc.c Proyecto: lavabit/magma
/**
 * @brief
 *  Perform base64-decoding on a string and return the result.
 * @param buf
 *  a pointer to a buffer containing the data to be decoded.
 * @param len
 *  the length, in bytes, of the buffer to be decoded.
 * @param outlen
 *  a pointer to a variable to receive the length of the decoded data.
 * @return
 *  a pointer to a newly allocated buffer containing the base64-decoded, or
 *  NULL on failure.
 * @free_using{free}
 */
unsigned char *
_b64decode(char const *buf, size_t len, size_t *outlen) {
	unsigned char *o, *result;
	const char *p;
	size_t new_len, written = 0;
	int loop = 0, value = 0;

	if (!buf || !len || !outlen) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	new_len = B64_DECODED_LEN(len);

	if (!(result = malloc(new_len))) {
		PUSH_ERROR_SYSCALL("malloc");
		RET_ERROR_PTR(ERR_NOMEM, "unable to allocate buffer for base64 decoded data");
	}

	memset(result, 0, new_len);

	o = result;
	p = buf;

	// Get four characters at a time from the input buffer and decode them.
	for (size_t i = 0; i < len; i++) {

		// Only process legit base64 characters.
		if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '+' || *p == '/') {
			// Do the appropriate operation.
			switch (loop) {

			case 0:
				value = _base64_vals[(int)*p++] << 18;
				loop++;
				break;
			case 1:
				value += _base64_vals[(int)*p++] << 12;
				*o++ = (value & 0x00ff0000) >> 16;
				written++;
				loop++;
				break;
			case 2:
				value += (unsigned int)_base64_vals[(int)*p++] << 6;
				*o++ = (value & 0x0000ff00) >> 8;
				written++;
				loop++;
				break;
			case 3:
				value += (unsigned int)_base64_vals[(int)*p++];
				*o++ = value & 0x000000ff;
				written++;
				loop = 0;
				break;
			default:
				free(result);
				RET_ERROR_PTR(ERR_UNSPEC, "an unexpected error occurred during base64 decoding");
				break;
			}

		}
		else if (*p == '=') {
			i = len;
		}
		else {
			p++;
		}

	}