Пример #1
0
/**
 * proto_crypt_dh_validate(yh_r, dhmac_r, requirefps):
 * Return non-zero if the value ${yh_r} received from the remote party is not
 * correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or
 * if the included y value is >= the diffie-hellman group modulus, or if
 * ${requirefps} is non-zero and the included y value is 1.
 */
int
proto_crypt_dh_validate(const uint8_t yh_r[PCRYPT_YH_LEN],
    const uint8_t dhmac_r[PCRYPT_DHMAC_LEN], int requirefps)
{
	uint8_t hbuf[32];

	/* Compute HMAC. */
	HMAC_SHA256_Buf(dhmac_r, PCRYPT_DHMAC_LEN, yh_r, CRYPTO_DH_PUBLEN,
	    hbuf);

	/* Check that the MAC matches. */
	if (crypto_verify_bytes(&yh_r[CRYPTO_DH_PUBLEN], hbuf, 32))
		return (1);

	/* Sanity-check the diffie-hellman value. */
	if (crypto_dh_sanitycheck(&yh_r[0]))
		return (1);

	/* If necessary, enforce that the diffie-hellman value is != 1. */
	if (requirefps) {
		if (! is_not_one(&yh_r[0], CRYPTO_DH_PUBLEN))
			return (1);
	}

	/* Everything is good. */
	return (0);
}
Пример #2
0
/**
 * netpacket_hmac_verify(type, nonce, packetbuf, pos, key):
 * Verify that HMAC(type || nonce || packetbuf[0 .. pos - 1]) using the
 * specified key matches packetbuf[pos .. pos + 31].  If nonce is NULL, omit
 * it from the data being HMACed as appropriate.  Return -1 on error, 0 on
 * success, or 1 if the hash does not match.
 */
int
netpacket_hmac_verify(uint8_t type, const uint8_t nonce[32],
    const uint8_t * packetbuf, size_t pos, int key)
{
	uint8_t hmac_actual[32];
	uint8_t prefixbuf[33];
	size_t prefixlen;

	/* Compute the correct HMAC. */
	prefixbuf[0] = type;
	prefixlen = 1;
	if (nonce != NULL) {
		memcpy(&prefixbuf[prefixlen], nonce, 32);
		prefixlen += 32;
	}
	if (crypto_hash_data_2(key, prefixbuf, prefixlen,
	    packetbuf, pos, hmac_actual))
		goto err0;

	/* Compare. */
	if (crypto_verify_bytes(&packetbuf[pos], hmac_actual, 32))
		goto badhmac;

	/* Success! */
	return (0);

badhmac:
	/* HMAC doesn't match. */
	return (1);

err0:
	/* Failure! */
	return (-1);
}
Пример #3
0
static int
callback_register_response(void * cookie, NETPACKET_CONNECTION * NPC,
    int status, uint8_t packettype, const uint8_t * packetbuf,
    size_t packetlen)
{
	struct register_internal * C = cookie;
	uint8_t hmac_actual[32];

	(void)NPC; /* UNUSED */
	(void)packetlen; /* UNUSED */

	/* Handle errors. */
	if (status != NETWORK_STATUS_OK) {
		netproto_printerr(status);
		goto err0;
	}

	/* Make sure we received the right type of packet. */
	if (packettype != NETPACKET_REGISTER_RESPONSE)
		goto err1;

	/* Verify packet hmac. */
	if ((packetbuf[0] == 0) || (packetbuf[0] == 3)) {
		crypto_hash_data_key_2(C->register_key, 32, &packettype, 1,
		    packetbuf, 9, hmac_actual);
	} else {
		memset(hmac_actual, 0, 32);
	}
	if (crypto_verify_bytes(hmac_actual, &packetbuf[9], 32))
		goto err1;

	/* Record status code and machine number returned by server. */
	C->status = packetbuf[0];
	C->machinenum = be64dec(&packetbuf[1]);

	/* We have received a response. */
	C->done = 1;

	/* Success! */
	return (0);

err1:
	netproto_printerr(NETPROTO_STATUS_PROTERR);
err0:
	/* Failure! */
	return (-1);
}
Пример #4
0
/**
 * crypto_session_verify(CS, buf, buflen, sig):
 * Verify that sig = read_auth(buf).  Return non-zero if the signature
 * does not match.
 */
int
crypto_session_verify(CRYPTO_SESSION * CS, const uint8_t * buf, size_t buflen,
    const uint8_t sig[32])
{
	uint8_t nonce[8];
	uint8_t sig_actual[32];

	/* Convert nonce to 8-byte big-endian format, and increment. */
	be64enc(nonce, CS->auth_read_nonce);
	CS->auth_read_nonce += 1;

	/* Generate hash. */
	crypto_hash_data_key_2(CS->auth_read, 32,
	    nonce, 8, buf, buflen, sig_actual);

	/* Determine if the signatures match. */
	if (crypto_verify_bytes(sig, sig_actual, 32))
		return (1);
	else
		return (0);
}
Пример #5
0
/**
 * proto_crypt_dec(ibuf, obuf, k):
 * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}.  If the data
 * is valid, write it into ${obuf} and return the length; otherwise, return
 * -1.
 */
ssize_t proto_crypt_dec(uint8_t ibuf[PCRYPT_ESZ], uint8_t * obuf,
    struct proto_keys * k)
{
	HMAC_SHA256_CTX ctx;
	uint8_t hbuf[32];
	uint8_t pnum_exp[8];
	size_t len;

	/* Verify HMAC. */
	be64enc(pnum_exp, k->pnum);
	HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
	HMAC_SHA256_Update(&ctx, ibuf, PCRYPT_MAXDSZ + 4);
	HMAC_SHA256_Update(&ctx, pnum_exp, 8);
	HMAC_SHA256_Final(hbuf, &ctx);
	if (crypto_verify_bytes(hbuf, &ibuf[PCRYPT_MAXDSZ + 4], 32))
		return (-1);

	/* Decrypt the buffer in-place. */
	crypto_aesctr_buf(k->k_aes, k->pnum, ibuf, ibuf, PCRYPT_MAXDSZ + 4);

	/* Increment packet number. */
	k->pnum += 1;

	/* Parse length. */
	len = be32dec(&ibuf[PCRYPT_MAXDSZ]);

	/* Make sure nobody is being evil here... */
	if ((len == 0) || (len > PCRYPT_MAXDSZ))
		return (-1);

	/* Copy the bytes into the output buffer. */
	memcpy(obuf, ibuf, len);

	/* Return the decrypted length. */
	return (len);
}
Пример #6
0
static int
multitape_metadata_get(STORAGE_R * S, CHUNKS_S * C,
    struct tapemetadata * mdat,
    const uint8_t tapehash[32], const char * tapename, int quiet)
{
	uint8_t hbuf[32];
	uint8_t * mbuf;
	size_t mdlen;

	/* Read the tape metadata. */
	switch (storage_read_file_alloc(S, &mbuf, &mdlen, 'm', tapehash)) {
	case -1:
		/* Internal error. */
		goto err1;
	case 1:
		/* ENOENT. */
		goto notpresent;
	case 2:
		/* Corrupt metadata file. */
		goto corrupt;
	}

	/* Adjust chunk statistics. */
	if (C != NULL)
		chunks_stats_extrastats(C, mdlen);

	/* Parse the tape metadata. */
	switch (multitape_metadata_dec(mdat, mbuf, mdlen)) {
	case 1:
		/* Metadata is corrupt. */
		goto corrupt1;
	case -1:
		/* Error. */
		goto err2;
	}

	/* Store metadata length. */
	mdat->metadatalen = mdlen;

	/* Free tape metadata. */
	free(mbuf);

	/*
	 * Make sure the name stored in the archive metadata matches the
	 * name of the metadata file.
	 */
	if (crypto_hash_data(CRYPTO_KEY_HMAC_NAME,
	    (uint8_t *)mdat->name, strlen(mdat->name), hbuf))
		goto err0;
	if (crypto_verify_bytes(tapehash, hbuf, 32))
		goto corrupt;

	/* Success! */
	return (0);

corrupt1:
	free(mbuf);
corrupt:
	if (quiet == 0) {
		if (tapename)
			warn0("Archive metadata is corrupt: %s", tapename);
		else
			warn0("Archive metadata file is corrupt");
	}

	/* File is corrupt. */
	return (2);

notpresent:
	if (quiet == 0) {
		if (tapename)
			warn0("Archive does not exist: %s", tapename);
		else
			warn0("Cannot read archive metadata file");
	}

	/* ENOENT. */
	return (1);

err2:
	free(mbuf);
err1:
	warnp("Error reading archive metadata");
err0:
	/* Failure! */
	return (-1);
}
Пример #7
0
/**
 * crypto_rsa_decrypt(key, data, len, out, outlen):
 * Decrypt the provided data with the specified key, writing the ciphertext
 * into ${out} (of length ${outlen}).  Set ${*outlen} to the length of the
 * plaintext, and return 0 on success, 1 if the ciphertext is invalid, or
 * -1 on error.
 */
int
crypto_rsa_decrypt(int key, const uint8_t * data, size_t len,
    uint8_t * out, size_t * outlen)
{
	RSA * rsa;
	uint8_t EM[256];
	uint8_t lHash[32];
	uint8_t baddata, paddingmask;
	uint8_t maskedSeed[32];
	uint8_t maskedDB[223];
	uint8_t seedMask[32];
	uint8_t seed[32];
	uint8_t dbMask[223];
	uint8_t DB[223];
	size_t msglen;
	size_t i;
	unsigned long rsaerr;

	/* Sanity check. */
	assert(len < INT_MAX);

	/* Find the required key. */
	if ((rsa = crypto_keys_lookup_RSA(key)) == NULL)
		goto err0;

	/* Make sure the key and ciphertext buffer are the correct size. */
	if (!crypto_compat_RSA_valid_size(rsa)) {
		warn0("RSA key is incorrect size");
		goto err0;
	}
	if (len != 256) {
		warn0("Programmer error: "
		    "ciphertext buffer is incorrect length");
		goto err0;
	}

	/* Make sure the plaintext buffer is large enough. */
	if (*outlen < 256) {
		warn0("Programmer error: "
		    "plaintext buffer is too small");
		goto err0;
	}

	/* Convert the ciphertext to EM, via RSA. */
	if (RSA_private_decrypt((int)len, data, EM, rsa, RSA_NO_PADDING)
	    != 256) {
		/*
		 * We can only distinguish between bad ciphertext and an
		 * internal error in OpenSSL by looking at the error code.
		 */
		rsaerr = ERR_get_error();
		if (rsaerr == RSA_R_DATA_TOO_LARGE_FOR_MODULUS)
			goto bad;

		/* Anything else is an internal error in OpenSSL. */
		warn0("%s", ERR_error_string(rsaerr, NULL));
		goto err0;
	}

	/* Construct lHash as specified in RSAES-OAEP-DECRYPT in RFC 3447. */
	if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, NULL, 0, lHash)) {
		warn0("Programmer error: "
		    "SHA256 should never fail");
		goto err0;
	}

	/*
	 * The high byte of EM must be zero.  We test this later to avoid
	 * timing side channel attacks.
	 */
	baddata = EM[0];

	/* Construct maskedSeed and maskedDB. */
	memcpy(maskedSeed, EM + 1, 32);
	memcpy(maskedDB, EM + 33, 223);

	/* Construct seedMask and seed. */
	crypto_MGF1(maskedDB, 223, seedMask, 32);
	for (i = 0; i < 32; i++)
		seed[i] = maskedSeed[i] ^ seedMask[i];

	/* Construct dbMask and DB. */
	crypto_MGF1(seed, 32, dbMask, 223);
	for (i = 0; i < 223; i++)
		DB[i] = maskedDB[i] ^ dbMask[i];

	/*
	 * The leading 32 bytes of DB must be equal to lHash.  Test them all
	 * at once, simultaneous with other tests, in order to avoid timing
	 * side channel attacks.
	 */
	baddata = baddata | crypto_verify_bytes(DB, lHash, 32);

	/*
	 * Bytes 33 -- 223 of DB must be zero bytes followed by a one byte
	 * followed by the real data.  The following code will set baddata
	 * to a non-zero value if there are non-{0, 1} bytes which are not
	 * separated from the start by a 1 byte.
	 */
	paddingmask = 0xff;
	msglen = 191;
	for (i = 32; i < 223; i++) {
		/* If we're still doing padding, DB[i] should be 0 or 1. */
		baddata = baddata | (paddingmask & DB[i] & 0xfe);

		/*
		 * If baddata is still 0, paddingmask is either 0xff or 0x00
		 * depending upon whether the current byte is padding or not.
		 * Treating it as a signed integer and adding it to msglen
		 * will result in msglen holding the length of the message
		 * after the padding is removed.
		 */
		msglen += (size_t)((int8_t)(paddingmask));

		/*-
		 * If baddata is still 0, there are 3 cases:
		 * 1. We're no longer looking at padding, and paddingmask is
		 *    0x00, so &ing it with something won't change it.
		 * 2. We're looking at a 0 byte of padding, paddingmask is
		 *    0xff, and we want it to remain 0xff.
		 * 3. We're looking at a 1 byte of padding, paddingmask is
		 *    0xff, and we want it to become 0x00.
		 * In all three cases, &ing the byte minus one does what we
		 * want.
		 */
		paddingmask = paddingmask & (DB[i] - 1);
	}

	/* Once we hit the end, the padding should be over. */
	baddata = baddata | paddingmask;

	/* Is the data bad? */
	if (baddata)
		goto bad;

	/* Sanity check the message length. */
	if (msglen > *outlen) {
		warn0("Programmer error: "
		    "decrypted message length is insane");
		goto err0;
	}

	/* Copy the message into the output buffer. */
	memcpy(out, DB + 223 - msglen, msglen);
	*outlen = msglen;

	/* Success! */
	return (0);

bad:
	/* Bad signature. */
	return (1);

err0:
	/* Failure! */
	return (-1);
}
Пример #8
0
/**
 * crypto_rsa_verify(key, data, len, sig, siglen):
 * Verify that the provided signature matches the provided data.  Return 0
 * if the signature is valid, 1 if the signature is invalid, or -1 on error.
 */
int
crypto_rsa_verify(int key, const uint8_t * data, size_t len,
    const uint8_t * sig, size_t siglen)
{
	RSA * rsa;
	uint8_t EM[256];
	uint8_t mHash[32];
	uint8_t maskedDB[223];
	uint8_t H[32];
	uint8_t dbMask[223];
	uint8_t DB[223];
	uint8_t salt[32];
	uint8_t Mprime[72];
	uint8_t Hprime[32];
	size_t i;
	unsigned long rsaerr;

	/* Sanity check. */
	assert(siglen < INT_MAX);

	/* Find the required key. */
	if ((rsa = crypto_keys_lookup_RSA(key)) == NULL)
		goto err0;

	/* Make sure the key and signature buffer are the correct size. */
	if (!crypto_compat_RSA_valid_size(rsa)) {
		warn0("RSA key is incorrect size");
		goto err0;
	}
	if (siglen != 256) {
		warn0("Programmer error: "
		    "signature buffer is incorrect length");
		goto err0;
	}

	/* Convert the signature to EM, via RSA. */
	if (RSA_public_decrypt((int)siglen, sig, EM, rsa, RSA_NO_PADDING)
	    != 256) {
		/*
		 * We can only distinguish between a bad signature and an
		 * internal error in OpenSSL by looking at the error code.
		 */
		rsaerr = ERR_get_error();
		if (rsaerr == RSA_R_DATA_TOO_LARGE_FOR_MODULUS)
			goto bad;

		/* Anything else is an internal error in OpenSSL. */
		warn0("%s", ERR_error_string(rsaerr, NULL));
		goto err0;
	}

	/* Generate mHash as specified in EMSA-PSS-VERIFY from RFC 3447. */
	if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, data, len, mHash)) {
		warn0("Programmer error: "
		    "SHA256 should never fail");
		goto err0;
	}

	/* Verify rightmost octet of EM. */
	if (EM[255] != 0xbc)
		goto bad;

	/* Construct maskedDB and H. */
	memcpy(maskedDB, EM, 223);
	memcpy(H, EM + 223, 32);

	/* Verify high bit of leftmost octet of maskedDB. */
	if (maskedDB[0] & 0x80)
		goto bad;

	/* Construct dbMask and DB. */
	crypto_MGF1(H, 32, dbMask, 223);
	for (i = 0; i < 223; i++)
		DB[i] = maskedDB[i] ^ dbMask[i];

	/* Set high bit of leftmost octet of DB to zero. */
	DB[0] &= 0x7f;

	/* Verify padding in DB. */
	for (i = 0; i < 190; i++)
		if (DB[i] != 0)
			goto bad;
	if (DB[190] != 1)
		goto bad;

	/* Construct salt. */
	memcpy(salt, DB + 191, 32);

	/* Construct M'. */
	memset(Mprime, 0, 8);
	memcpy(Mprime + 8, mHash, 32);
	memcpy(Mprime + 40, salt, 32);

	/* Construct H'. */
	if (crypto_hash_data(CRYPTO_KEY_HMAC_SHA256, Mprime, 72, Hprime)) {
		warn0("Programmer error: "
		    "SHA256 should never fail");
		goto err0;
	}

	/* Verify that H' == H. */
	if (crypto_verify_bytes(H, Hprime, 32))
		goto bad;

	/* Success! */
	return (0);

bad:
	/* Bad signature. */
	return (1);

err0:
	/* Failure! */
	return (-1);
}