Exemple #1
0
// Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys.
static bool receive_sig(sptps_t *s, const char *data, uint16_t len) {
	size_t keylen = ECDH_SIZE;
	size_t siglen = ecdsa_size(s->hiskey);

	// Verify length of KEX record.
	if(len != siglen)
		return error(s, EIO, "Invalid KEX record length");

	// Concatenate both KEX messages, plus tag indicating if it is from the connection originator
	char msg[(1 + 32 + keylen) * 2 + 1 + s->labellen];

	msg[0] = !s->initiator;
	memcpy(msg + 1, s->hiskex, 1 + 32 + keylen);
	memcpy(msg + 1 + 33 + keylen, s->mykex, 1 + 32 + keylen);
	memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);

	// Verify signature.
	if(!ecdsa_verify(s->hiskey, msg, sizeof msg, data))
		return error(s, EIO, "Failed to verify SIG record");

	// Compute shared secret.
	char shared[ECDH_SHARED_SIZE];
	if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared))
		return error(s, EINVAL, "Failed to compute ECDH shared secret");
	s->ecdh = NULL;

	// Generate key material from shared secret.
	if(!generate_key_material(s, shared, sizeof shared))
		return false;

	free(s->mykex);
	free(s->hiskex);

	s->mykex = NULL;
	s->hiskex = NULL;

	// Send cipher change record
	if(s->outstate && !send_ack(s))
		return false;

	// TODO: only set new keys after ACK has been set/received
	if(s->initiator) {
		if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN))
			return error(s, EINVAL, "Failed to set key");
	} else {
		if(!chacha_poly1305_set_key(s->outcipher, s->key))
			return error(s, EINVAL, "Failed to set key");
	}

	return true;
}
Exemple #2
0
// Receive an ACKnowledgement record.
static bool receive_ack(sptps_t *s, const char *data, uint16_t len) {
	if(len)
		return error(s, EIO, "Invalid ACK record length");

	if(s->initiator) {
		if(!chacha_poly1305_set_key(s->incipher, s->key))
			return error(s, EINVAL, "Failed to set counter");
	} else {
		if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN))
			return error(s, EINVAL, "Failed to set counter");
	}

	free(s->key);
	s->key = NULL;
	s->instate = true;

	return true;
}
Exemple #3
0
// Encrypts plaintext ptxt, stores as ciphertext ctxt
void encrypt_phrase(dheluks_ctx_t *ctx, dheluks_pkg_t *pkg, dheluks_kys_t *skr, dheluks_txt_t *txt) {

	chacha_poly1305_set_key(&ctx->ciph, skr->sharekey); //set key

	gen_random(&ctx->rand, NONCE_SIZE, pkg->nonce);	//generate nonce

	chacha_poly1305_set_nonce(&ctx->ciph, pkg->nonce);	//set nonce

	chacha_poly1305_encrypt(&ctx->ciph, pkg->csize, pkg->cphtxt, txt->plntxt); //encrypt

	chacha_poly1305_digest(&ctx->ciph, DIGEST_SIZE, pkg->digest);

}
Exemple #4
0
// Decrypts ctxt, stores as an encoded uint8
int decrypt_phrase(dheluks_ctx_t *ctx, dheluks_pkg_t *pkg, dheluks_kys_t *skr, dheluks_txt_t *txt) {

	uint8_t dig[DIGEST_SIZE];

	chacha_poly1305_set_key(&ctx->ciph, skr->sharekey); //set key

	chacha_poly1305_set_nonce(&ctx->ciph, pkg->nonce); //set nonce

	chacha_poly1305_decrypt(&ctx->ciph, pkg->csize, txt->plntxt, pkg->cphtxt); //decrypt

	chacha_poly1305_digest(&ctx->ciph, DIGEST_SIZE, dig);

	if (not_equal(dig, pkg->digest, DIGEST_SIZE, "Message authentication failed.")) //if the digests aren't equal,
		return -1; //return an error

	return 0;

}
Exemple #5
0
// Initialize chacha-poly1305 cipher
void init_cipher(dheluks_ctx_t *ctx, uint8_t *sk) {

	chacha_poly1305_set_key(&ctx->ciph, sk); //initialize symm cipher with key sk

}