Exemple #1
0
int
main(int argc, char **argv)
{
	uint8 output[AKW_MAX_WRAP_LEN+AKW_BLOCK_LEN];
	uint8 input2[AKW_MAX_WRAP_LEN];
	int retv, k, fail = 0;

	for (k = 0; k < NUM_VECTORS; k++) {
		retv = aes_wrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il,
		                akw_vec[k].input, output);
		pres("\n   AES Wrap: ", akw_vec[k].il+AKW_BLOCK_LEN, output);

		if (retv) {
			dbg(("%s: aes_wrap failed\n", *argv));
			fail++;
		}
		if (memcmp(output, akw_vec[k].ref, akw_vec[k].il+AKW_BLOCK_LEN) != 0) {
			dbg(("%s: aes_wrap failed\n", *argv));
			fail++;
		}

		retv = aes_unwrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il + AKW_BLOCK_LEN,
		                  output, input2);
		pres("\n   AES Unwrap: ", akw_vec[k].il, input2);

		if (retv) {
			dbg(("%s: aes_unwrap failed\n", *argv));
			fail++;
		}
		if (memcmp(akw_vec[k].input, input2, akw_vec[k].il) != 0) {
			dbg(("%s: aes_unwrap failed\n", *argv));
			fail++;
		}
	}

	for (k = 0; k < NUM_WRAP_FAIL_VECTORS; k++) {
		if (!aes_wrap(akw_wrap_fail_vec[k].kl, akw_wrap_fail_vec[k].key,
		              akw_wrap_fail_vec[k].il, akw_wrap_fail_vec[k].input, output)) {
			dbg(("%s: aes_wrap didn't detect failure case\n", *argv));
			fail++;
		}
	}

	for (k = 0; k < NUM_UNWRAP_FAIL_VECTORS; k++) {
		if (!aes_unwrap(akw_unwrap_fail_vec[k].kl, akw_unwrap_fail_vec[k].key,
		                akw_unwrap_fail_vec[k].il, akw_unwrap_fail_vec[k].input, input2)) {
			dbg(("%s: aes_unwrap didn't detect failure case\n", *argv));
			fail++;
		}
	}

	dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED"));
	return (fail);
}
Exemple #2
0
static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
{
	u8 *subelem, *pos;
	struct wpa_group *gsm = sm->group;
	size_t subelem_len;

	/* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
	 * Key[16+8] */
	subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8;
	subelem = os_zalloc(subelem_len);
	if (subelem == NULL)
		return NULL;

	pos = subelem;
	*pos++ = FTIE_SUBELEM_IGTK;
	*pos++ = subelem_len - 2;
	WPA_PUT_LE16(pos, gsm->GN_igtk);
	pos += 2;
	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
	pos += 6;
	*pos++ = WPA_IGTK_LEN;
	if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8,
		     gsm->IGTK[gsm->GN_igtk - 4], pos)) {
		os_free(subelem);
		return NULL;
	}

	*len = subelem_len;
	return subelem;
}
Exemple #3
0
static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
				   struct wpa_ft_pmk_r0_sa *pmk_r0,
				   struct ft_remote_r1kh *r1kh,
				   const u8 *s1kh_id, int pairwise)
{
	struct ft_r0kh_r1kh_push_frame frame, f;
	struct os_time now;

	os_memset(&frame, 0, sizeof(frame));
	frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
	frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH;
	frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN);
	os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);

	/* aes_wrap() does not support inplace encryption, so use a temporary
	 * buffer for the data. */
	os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN);
	os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
	os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN);
	wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id,
			  s1kh_id, f.pmk_r1, f.pmk_r1_name);
	wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id));
	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN);
	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name,
		    WPA_PMK_NAME_LEN);
	os_get_time(&now);
	WPA_PUT_LE32(f.timestamp, now.sec);
	f.pairwise = host_to_le16(pairwise);
	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
		     f.timestamp, frame.timestamp) < 0)
		return;

	wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame));
}
Exemple #4
0
static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
{
	u8 *subelem;
	struct wpa_group *gsm = sm->group;
	size_t subelem_len, pad_len;
	const u8 *key;
	size_t key_len;
	u8 keybuf[32];

	key_len = gsm->GTK_len;
	if (key_len > sizeof(keybuf))
		return NULL;

	/*
	 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less
	 * than 16 bytes.
	 */
	pad_len = key_len % 8;
	if (pad_len)
		pad_len = 8 - pad_len;
	if (key_len + pad_len < 16)
		pad_len += 8;
	if (pad_len) {
		os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);
		os_memset(keybuf + key_len, 0, pad_len);
		keybuf[key_len] = 0xdd;
		key_len += pad_len;
		key = keybuf;
	} else
		key = gsm->GTK[gsm->GN - 1];

	/*
	 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
	 * Key[5..32].
	 */
	subelem_len = 13 + key_len + 8;
	subelem = os_zalloc(subelem_len);
	if (subelem == NULL)
		return NULL;

	subelem[0] = FTIE_SUBELEM_GTK;
	subelem[1] = 11 + key_len + 8;
	/* Key ID in B0-B1 of Key Info */
	WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
	subelem[4] = gsm->GTK_len;
	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
	if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) {
		os_free(subelem);
		return NULL;
	}

	*len = subelem_len;
	return subelem;
}
Exemple #5
0
bool
wpa_encr_key_data(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey,
	uint8 *gtk,	uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key)
{
	uint16 len;

	switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) {
	case WPA_KEY_DESC_V1:
		if (gtk)
			len = ntoh16_ua((uint8 *)&body->key_len);
		else
			len = ntoh16_ua((uint8 *)&body->data_len);

		/* create the iv/ptk key */
		bcopy(body->iv, encrkey, 16);
		bcopy(ekey, &encrkey[16], 16);
		/* encrypt the key data */
		prepare_key(encrkey, 32, rc4key);
		rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
		rc4(body->data, len, rc4key);
		break;
	case WPA_KEY_DESC_V2:
	case WPA_KEY_DESC_V3:
		len = ntoh16_ua((uint8 *)&body->data_len);
		/* pad if needed - min. 16 bytes, 8 byte aligned */
		/* padding is 0xdd followed by 0's */
		if (len < 2*AKW_BLOCK_LEN) {
			body->data[len] = WPA2_KEY_DATA_PAD;
			bzero(&body->data[len+1], 2*AKW_BLOCK_LEN - (len+1));
			len = 2*AKW_BLOCK_LEN;
		} else if (len % AKW_BLOCK_LEN) {
			body->data[len] = WPA2_KEY_DATA_PAD;
			bzero(&body->data[len+1], AKW_BLOCK_LEN - ((len+1) % AKW_BLOCK_LEN));
			len += AKW_BLOCK_LEN - (len % AKW_BLOCK_LEN);
		}
		if (aes_wrap(WPA_MIC_KEY_LEN, ekey, len, body->data, body->data)) {
			return FALSE;
		}
		len += 8;
		hton16_ua_store(len, (uint8 *)&body->data_len);
		break;
	default:
		return FALSE;
	}

	return TRUE;
}
Exemple #6
0
static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth,
			      const u8 *s1kh_id, const u8 *r0kh_id,
			      size_t r0kh_id_len, const u8 *pmk_r0_name)
{
	struct ft_remote_r0kh *r0kh;
	struct ft_r0kh_r1kh_pull_frame frame, f;

	r0kh = wpa_auth->conf.r0kh_list;
	while (r0kh) {
		if (r0kh->id_len == r0kh_id_len &&
		    os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0)
			break;
		r0kh = r0kh->next;
	}
	if (r0kh == NULL)
		return -1;

	wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
		   "address " MACSTR, MAC2STR(r0kh->addr));

	os_memset(&frame, 0, sizeof(frame));
	frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
	frame.packet_type = FT_PACKET_R0KH_R1KH_PULL;
	frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN);
	os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);

	/* aes_wrap() does not support inplace encryption, so use a temporary
	 * buffer for the data. */
	if (random_get_bytes(f.nonce, sizeof(f.nonce))) {
		wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
			   "nonce");
		return -1;
	}
	os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
	os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
	os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
	os_memset(f.pad, 0, sizeof(f.pad));

	if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
		     f.nonce, frame.nonce) < 0)
		return -1;

	wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));

	return 0;
}
Exemple #7
0
/*
 * Generate a new encryption key for use in volume encryption.
 * We don't ask the user for a encryption key but generate a semi
 * random passphrase of the wanted length which is way stronger.
 * When the config has a wrap key we use that to wrap the newly
 * created passphrase using RFC3394 aes wrap and always convert
 * the passphrase into a base64 encoded string. This key is
 * stored in the database and is passed to the storage daemon
 * when needed. The storage daemon has the same wrap key per
 * director so it can unwrap the passphrase for use.
 *
 * Changing the wrap key will render any previously created
 * crypto keys useless so only change the wrap key after initial
 * setting when you know what you are doing and always store
 * the old key somewhere save so you can use bscrypto to
 * convert them for the new wrap key.
 */
static bool generate_new_encryption_key(UAContext *ua, MEDIA_DBR *mr)
{
   int length;
   char *passphrase;

   passphrase = generate_crypto_passphrase(DEFAULT_PASSPHRASE_LENGTH);
   if (!passphrase) {
      ua->error_msg(_("Failed to generate new encryption passphrase for Volume %s.\n"), mr->VolumeName);
      return false;
   }

   /*
    * See if we need to wrap the passphrase.
    */
   if (me->keyencrkey) {
      char *wrapped_passphrase;

      length = DEFAULT_PASSPHRASE_LENGTH + 8;
      wrapped_passphrase = (char *)malloc(length);
      memset(wrapped_passphrase, 0, length);
      aes_wrap((unsigned char *)me->keyencrkey,
               DEFAULT_PASSPHRASE_LENGTH / 8,
               (unsigned char *)passphrase,
               (unsigned char *)wrapped_passphrase);

      free(passphrase);
      passphrase = wrapped_passphrase;
   } else {
      length = DEFAULT_PASSPHRASE_LENGTH;
   }

   /*
    * The passphrase is always base64 encoded.
    */
   bin_to_base64(mr->EncrKey, sizeof(mr->EncrKey), passphrase, length, true);

   free(passphrase);
   return true;
}
Exemple #8
0
int main(int argc, char *argv[])
{
	u8 kek[] = {
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
	};
	u8 plain[] = {
		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
		0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
	};
	u8 crypt[] = {
		0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
		0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
		0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
	};
	u8 result[24];
	int ret = 0;
	unsigned int i;
	struct omac1_test_vector *tv;

	if (aes_wrap(kek, 2, plain, result)) {
		printf("AES-WRAP-128-128 reported failure\n");
		ret++;
	}
	if (memcmp(result, crypt, 24) != 0) {
		printf("AES-WRAP-128-128 failed\n");
		ret++;
	}
	if (aes_unwrap(kek, 2, crypt, result)) {
		printf("AES-UNWRAP-128-128 reported failure\n");
		ret++;
	}
	if (memcmp(result, plain, 16) != 0) {
		printf("AES-UNWRAP-128-128 failed\n");
		ret++;
		for (i = 0; i < 16; i++)
			printf(" %02x", result[i]);
		printf("\n");
	}

	test_aes_perf();

	for (i = 0; i < ARRAY_SIZE(test_vectors); i++) {
		tv = &test_vectors[i];
		if (omac1_aes_128(tv->k, tv->msg, tv->msg_len, result) ||
		    memcmp(result, tv->tag, 16) != 0) {
			printf("OMAC1-AES-128 test vector %d failed\n", i);
			ret++;
		}

		if (tv->msg_len > 1) {
			const u8 *addr[2];
			size_t len[2];

			addr[0] = tv->msg;
			len[0] = 1;
			addr[1] = tv->msg + 1;
			len[1] = tv->msg_len - 1;

			if (omac1_aes_128_vector(tv->k, 2, addr, len,
						 result) ||
			    memcmp(result, tv->tag, 16) != 0) {
				printf("OMAC1-AES-128(vector) test vector %d "
				       "failed\n", i);
				ret++;
			}
		}
	}

	ret += test_eax();

	ret += test_cbc();

	ret += test_gcm();

	if (ret)
		printf("FAILED!\n");

	return ret;
}
static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
					  struct eap_fast_data *data)
{
	u8 pac_key[EAP_FAST_PAC_KEY_LEN];
	u8 *pac_buf, *pac_opaque;
	struct wpabuf *buf;
	u8 *pos;
	size_t buf_len, srv_id_info_len, pac_len;
	struct eap_tlv_hdr *pac_tlv;
	struct pac_tlv_hdr *pac_info;
	struct eap_tlv_result_tlv *result;
	struct os_time now;

	if (random_get_bytes(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 ||
	    os_get_time(&now) < 0)
		return NULL;
	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key",
			pac_key, EAP_FAST_PAC_KEY_LEN);

	pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) +
		(2 + sm->identity_len) + 8;
	pac_buf = os_malloc(pac_len);
	if (pac_buf == NULL)
		return NULL;

	srv_id_info_len = os_strlen(data->srv_id_info);

	pos = pac_buf;
	*pos++ = PAC_OPAQUE_TYPE_KEY;
	*pos++ = EAP_FAST_PAC_KEY_LEN;
	os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN);
	pos += EAP_FAST_PAC_KEY_LEN;

	*pos++ = PAC_OPAQUE_TYPE_LIFETIME;
	*pos++ = 4;
	WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime);
	pos += 4;

	if (sm->identity) {
		*pos++ = PAC_OPAQUE_TYPE_IDENTITY;
		*pos++ = sm->identity_len;
		os_memcpy(pos, sm->identity, sm->identity_len);
		pos += sm->identity_len;
	}

	pac_len = pos - pac_buf;
	while (pac_len % 8) {
		*pos++ = PAC_OPAQUE_TYPE_PAD;
		pac_len++;
	}

	pac_opaque = os_malloc(pac_len + 8);
	if (pac_opaque == NULL) {
		os_free(pac_buf);
		return NULL;
	}
	if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
		     pac_len / 8, pac_buf, pac_opaque) < 0) {
		os_free(pac_buf);
		os_free(pac_opaque);
		return NULL;
	}
	os_free(pac_buf);

	pac_len += 8;
	wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque",
		    pac_opaque, pac_len);

	buf_len = sizeof(*pac_tlv) +
		sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN +
		sizeof(struct pac_tlv_hdr) + pac_len +
		data->srv_id_len + srv_id_info_len + 100 + sizeof(*result);
	buf = wpabuf_alloc(buf_len);
	if (buf == NULL) {
		os_free(pac_opaque);
		return NULL;
	}

	/* Result TLV */
	wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)");
	result = wpabuf_put(buf, sizeof(*result));
	WPA_PUT_BE16((u8 *) &result->tlv_type,
		     EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV);
	WPA_PUT_BE16((u8 *) &result->length, 2);
	WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS);

	/* PAC TLV */
	wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV");
	pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv));
	pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
					 EAP_TLV_PAC_TLV);

	/* PAC-Key */
	eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN);

	/* PAC-Opaque */
	eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len);
	os_free(pac_opaque);

	/* PAC-Info */
	pac_info = wpabuf_put(buf, sizeof(*pac_info));
	pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO);

	/* PAC-Lifetime (inside PAC-Info) */
	eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4);
	wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime);

	/* A-ID (inside PAC-Info) */
	eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);
	
	/* Note: headers may be misaligned after A-ID */

	if (sm->identity) {
		eap_fast_put_tlv(buf, PAC_TYPE_I_ID, sm->identity,
				 sm->identity_len);
	}

	/* A-ID-Info (inside PAC-Info) */
	eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info,
			 srv_id_info_len);

	/* PAC-Type (inside PAC-Info) */
	eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2);
	wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC);

	/* Update PAC-Info and PAC TLV Length fields */
	pos = wpabuf_put(buf, 0);
	pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1));
	pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1));

	return buf;
}
Exemple #10
0
static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
			      const u8 *src_addr,
			      const u8 *data, size_t data_len)
{
	struct ft_r0kh_r1kh_pull_frame *frame, f;
	struct ft_remote_r1kh *r1kh;
	struct ft_r0kh_r1kh_resp_frame resp, r;
	u8 pmk_r0[PMK_LEN];
	int pairwise;

	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull");

	if (data_len < sizeof(*frame))
		return -1;

	r1kh = wpa_auth->conf.r1kh_list;
	while (r1kh) {
		if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0)
			break;
		r1kh = r1kh->next;
	}
	if (r1kh == NULL) {
		wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for "
			   "PMK-R1 pull source address " MACSTR,
			   MAC2STR(src_addr));
		return -1;
	}

	frame = (struct ft_r0kh_r1kh_pull_frame *) data;
	/* aes_unwrap() does not support inplace decryption, so use a temporary
	 * buffer for the data. */
	if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
		       frame->nonce, f.nonce) < 0) {
		wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
			   "request from " MACSTR, MAC2STR(src_addr));
		return -1;
	}

	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
		    f.nonce, sizeof(f.nonce));
	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
		    f.pmk_r0_name, WPA_PMK_NAME_LEN);
	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
		   MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));

	os_memset(&resp, 0, sizeof(resp));
	resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
	resp.packet_type = FT_PACKET_R0KH_R1KH_RESP;
	resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN);
	os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN);

	/* aes_wrap() does not support inplace encryption, so use a temporary
	 * buffer for the data. */
	os_memcpy(r.nonce, f.nonce, sizeof(f.nonce));
	os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN);
	os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN);
	if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0,
				&pairwise) < 0) {
		wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for "
			   "PMK-R1 pull");
		return -1;
	}

	wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id,
			  r.pmk_r1, r.pmk_r1_name);
	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
		    WPA_PMK_NAME_LEN);
	r.pairwise = host_to_le16(pairwise);

	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
		     r.nonce, resp.nonce) < 0) {
		os_memset(pmk_r0, 0, PMK_LEN);
		return -1;
	}

	os_memset(pmk_r0, 0, PMK_LEN);

	wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp));

	return 0;
}
Exemple #11
0
int main(int argc, char *const *argv)
{
    int retval = 0;
    int ch, kfd, length;
    bool base64_transform = false,
         clear_encryption = false,
         drive_encryption_status = false,
         generate_passphrase = false,
         populate_cache = false,
         set_encryption = false,
         show_keydata = false,
         volume_encryption_status = false,
         wrapped_keys = false;
    char *keyfile = NULL;
    char *cache_file = NULL;
    char *wrap_keyfile = NULL;
    char keydata[64];
    char wrapdata[64];

    setlocale(LC_ALL, "");
    bindtextdomain("bareos", LOCALEDIR);
    textdomain("bareos");

    while ((ch = getopt(argc, argv, "bcd:eg:k:p:s:vw:?")) != -1) {
        switch (ch) {
        case 'b':
            base64_transform = true;
            break;

        case 'c':
            clear_encryption = true;
            break;

        case 'd':
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
                debug_level = 1;
            }
            break;

        case 'e':
            drive_encryption_status = true;
            break;

        case 'g':
            generate_passphrase = true;
            if (keyfile) {
                usage();
                goto bail_out;
            }
            keyfile = bstrdup(optarg);
            break;

        case 'k':
            show_keydata = true;
            if (keyfile) {
                usage();
                goto bail_out;
            }
            keyfile = bstrdup(optarg);
            break;

        case 'p':
            populate_cache = true;
            cache_file = bstrdup(optarg);
            break;

        case 's':
            set_encryption = true;
            if (keyfile) {
                usage();
                goto bail_out;
            }
            keyfile = bstrdup(optarg);
            break;

        case 'v':
            volume_encryption_status = true;
            break;

        case 'w':
            wrapped_keys = true;
            wrap_keyfile = bstrdup(optarg);
            break;

        case '?':
        default:
            usage();
            goto bail_out;

        }
    }

    argc -= optind;
    argv += optind;

    if (!generate_passphrase && !show_keydata && !populate_cache && argc < 1) {
        fprintf(stderr, _("Missing device_name argument for this option\n"));
        usage();
        retval = 1;
        goto bail_out;
    }

    if (generate_passphrase && show_keydata) {
        fprintf(stderr, _("Either use -g or -k not both\n"));
        retval = 1;
        goto bail_out;
    }

    if (clear_encryption && set_encryption) {
        fprintf(stderr, _("Either use -c or -s not both\n"));
        retval = 1;
        goto bail_out;
    }

    if ((clear_encryption ||
            set_encryption) &&
            (drive_encryption_status ||
             volume_encryption_status)) {
        fprintf(stderr, _("Either set or clear the crypto key or ask for status not both\n"));
        retval = 1;
        goto bail_out;
    }

    if ((clear_encryption ||
            set_encryption ||
            drive_encryption_status ||
            volume_encryption_status) &&
            (generate_passphrase ||
             show_keydata ||
             populate_cache)) {
        fprintf(stderr, _("Don't mix operations which are incompatible "
                          "e.g. generate/show vs set/clear etc.\n"));
        retval = 1;
        goto bail_out;
    }

    OSDependentInit();
    init_msg(NULL, NULL);

    if (populate_cache) {
        char *VolumeName, *EncrKey;
        char new_cache_entry[256];

        /*
         * Load any keys currently in the cache.
         */
        read_crypto_cache(cache_file);

        /*
         * Read new entries from stdin and parse them to update
         * the cache.
         */
        fprintf(stdout, _("Enter cache entrie(s) (close with ^D): "));
        fflush(stdout);
        while (read(1, new_cache_entry, sizeof(new_cache_entry)) > 0) {
            strip_trailing_junk(new_cache_entry);

            /*
             * Try to parse the entry.
             */
            VolumeName = new_cache_entry;
            EncrKey = strchr(new_cache_entry, '\t');
            if (!EncrKey) {
                break;
            }

            *EncrKey++ = '\0';
            update_crypto_cache(VolumeName, EncrKey);
        }

        /*
         * Write out the new cache entries.
         */
        write_crypto_cache(cache_file);
        goto bail_out;
    }

    memset(keydata, 0, sizeof(keydata));
    memset(wrapdata, 0, sizeof(wrapdata));

    if (wrapped_keys) {
        /*
         * Read the key bits from the keyfile.
         * - == stdin
         */
        if (bstrcmp(wrap_keyfile, "-")) {
            kfd = 0;
            fprintf(stdout, _("Enter Key Encryption Key: "));
            fflush(stdout);
        } else {
            kfd = open(wrap_keyfile, O_RDONLY);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), wrap_keyfile);
                retval = 1;
                goto bail_out;
            }
        }
        read(kfd, wrapdata, sizeof(wrapdata));
        if (kfd > 0) {
            close(kfd);
        }
        strip_trailing_junk(wrapdata);
        Dmsg1(10, "Wrapped keydata = %s\n", wrapdata);
    }

    /*
     * Generate a new passphrase allow it to be wrapped using the given wrapkey
     * and base64 if specified or when wrapped.
     */
    if (generate_passphrase) {
        int cnt;
        char *passphrase;

        passphrase = generate_crypto_passphrase(DEFAULT_PASSPHRASE_LENGTH);
        if (!passphrase) {
            retval = 1;
            goto bail_out;
        }

        Dmsg1(10, "Generated passphrase = %s\n", passphrase);

        /*
         * See if we need to wrap the passphrase.
         */
        if (wrapped_keys) {
            char *wrapped_passphrase;

            length = DEFAULT_PASSPHRASE_LENGTH + 8;
            wrapped_passphrase = (char *)malloc(length);
            memset(wrapped_passphrase, 0, length);
            aes_wrap((unsigned char *)wrapdata,
                     DEFAULT_PASSPHRASE_LENGTH / 8,
                     (unsigned char *)passphrase,
                     (unsigned char *)wrapped_passphrase);

            free(passphrase);
            passphrase = wrapped_passphrase;
        } else {
            length = DEFAULT_PASSPHRASE_LENGTH;
        }

        /*
         * See where to write the key.
         * - == stdout
         */
        if (bstrcmp(keyfile, "-")) {
            kfd = 1;
        } else {
            kfd = open(keyfile, O_WRONLY | O_CREAT, 0644);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile);
                free(passphrase);
                retval = 1;
                goto bail_out;
            }
        }

        if (base64_transform || wrapped_keys) {
            cnt = bin_to_base64(keydata, sizeof(keydata), passphrase, length, true);
            if (write(kfd, keydata, cnt) != cnt) {
                fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile);
            }
        } else {
            cnt = DEFAULT_PASSPHRASE_LENGTH;
            if (write(kfd, passphrase, cnt) != cnt) {
                fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile);
            }
        }

        Dmsg1(10, "Keydata = %s\n", keydata);

        if (kfd > 1) {
            close(kfd);
        } else {
            write(kfd, "\n", 1);
        }
        free(passphrase);
        goto bail_out;
    }

    if (show_keydata) {
        char *passphrase;

        /*
         * Read the key bits from the keyfile.
         * - == stdin
         */
        if (bstrcmp(keyfile, "-")) {
            kfd = 0;
            fprintf(stdout, _("Enter Encryption Key: "));
            fflush(stdout);
        } else {
            kfd = open(keyfile, O_RDONLY);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile);
                retval = 1;
                goto bail_out;
            }
        }
        read(kfd, keydata, sizeof(keydata));
        if (kfd > 0) {
            close(kfd);
        }
        strip_trailing_junk(keydata);
        Dmsg1(10, "Keydata = %s\n", keydata);

        /*
         * See if we need to unwrap the passphrase.
         */
        if (wrapped_keys) {
            char *wrapped_passphrase;
            /*
             * A wrapped key is base64 encoded after it was wrapped so first
             * convert it from base64 to bin. As we first go from base64 to bin
             * and the base64_to_bin has a check if the decoded string will fit
             * we need to alocate some more bytes for the decoded buffer to be
             * sure it will fit.
             */
            length = DEFAULT_PASSPHRASE_LENGTH + 12;
            wrapped_passphrase = (char *)malloc(length);
            memset(wrapped_passphrase, 0, length);
            if (base64_to_bin(wrapped_passphrase, length,
                              keydata, strlen(keydata)) == 0) {
                fprintf(stderr,
                        _("Failed to base64 decode the keydata read from %s, aborting...\n"),
                        keyfile);
                free(wrapped_passphrase);
                goto bail_out;
            }

            length = DEFAULT_PASSPHRASE_LENGTH;
            passphrase = (char *)malloc(length);
            memset(passphrase, 0, length);

            if (aes_unwrap((unsigned char *)wrapdata,
                           length / 8,
                           (unsigned char *)wrapped_passphrase,
                           (unsigned char *)passphrase) == -1) {
                fprintf(stderr,
                        _("Failed to aes unwrap the keydata read from %s using the wrap data from %s, aborting...\n"),
                        keyfile, wrap_keyfile);
                free(wrapped_passphrase);
                goto bail_out;
            }

            free(wrapped_passphrase);
        } else {
            if (base64_transform) {
                /*
                 * As we first go from base64 to bin and the base64_to_bin has a check
                 * if the decoded string will fit we need to alocate some more bytes
                 * for the decoded buffer to be sure it will fit.
                 */
                length = DEFAULT_PASSPHRASE_LENGTH + 4;
                passphrase = (char *)malloc(length);
                memset(passphrase, 0, length);

                base64_to_bin(passphrase, length, keydata, strlen(keydata));
            } else {
                length = DEFAULT_PASSPHRASE_LENGTH;
                passphrase = (char *)malloc(length);
                memset(passphrase, 0, length);
                bstrncpy(passphrase, keydata, length);
            }
        }

        Dmsg1(10, "Unwrapped passphrase = %s\n", passphrase);
        fprintf(stdout, "%s\n", passphrase);

        free(passphrase);
        goto bail_out;
    }

    /*
     * Clear the loaded encryption key of the given drive.
     */
    if (clear_encryption) {
        if (clear_scsi_encryption_key(-1, argv[0])) {
            goto bail_out;
        } else {
            retval = 1;
            goto bail_out;
        }
    }

    /*
     * Get the drive encryption status of the given drive.
     */
    if (drive_encryption_status) {
        POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE);

        if (get_scsi_drive_encryption_status(-1, argv[0], encryption_status, 0)) {
            fprintf(stdout, "%s", encryption_status);
            free_pool_memory(encryption_status);
        } else {
            retval = 1;
            free_pool_memory(encryption_status);
            goto bail_out;
        }
    }

    /*
     * Load a new encryption key onto the given drive.
     */
    if (set_encryption) {
        /*
         * Read the key bits from the keyfile.
         * - == stdin
         */
        if (bstrcmp(keyfile, "-")) {
            kfd = 0;
            fprintf(stdout, _("Enter Encryption Key (close with ^D): "));
            fflush(stdout);
        } else {
            kfd = open(keyfile, O_RDONLY);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile);
                retval = 1;
                goto bail_out;
            }
        }
        read(kfd, keydata, sizeof(keydata));
        if (kfd > 0) {
            close(kfd);
        }
        strip_trailing_junk(keydata);

        if (set_scsi_encryption_key(-1, argv[0], keydata)) {
            goto bail_out;
        } else {
            retval = 1;
            goto bail_out;
        }
    }

    /*
     * Get the volume encryption status of volume currently loaded in the given drive.
     */
    if (volume_encryption_status) {
        POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE);

        if (get_scsi_volume_encryption_status(-1, argv[0], encryption_status, 0)) {
            fprintf(stdout, "%s", encryption_status);
            free_pool_memory(encryption_status);
        } else {
            retval = 1;
            free_pool_memory(encryption_status);
            goto bail_out;
        }
    }

bail_out:
    if (cache_file) {
        free(cache_file);
    }

    if (keyfile) {
        free(keyfile);
    }

    if (wrap_keyfile) {
        free(wrap_keyfile);
    }

    exit(retval);
}
Exemple #12
0
static int test_nist_key_wrap_ae(const char *fname)
{
	FILE *f;
	int ret = 0;
	char buf[15000], *pos, *pos2;
	u8 bin[2000], k[32], p[1024], c[1024 + 8], result[1024 + 8];
	size_t bin_len, k_len = 0, p_len = 0, c_len = 0;
	int ok = 0;

	printf("NIST KW AE tests from %s\n", fname);

	f = fopen(fname, "r");
	if (f == NULL) {
		printf("%s does not exist - cannot validate test vectors\n",
		       fname);
		return 1;
	}

	while (fgets(buf, sizeof(buf), f)) {
		if (buf[0] == '#')
			continue;
		pos = os_strchr(buf, '=');
		if (pos == NULL)
			continue;
		pos2 = pos - 1;
		while (pos2 >= buf && *pos2 == ' ')
			*pos2-- = '\0';
		*pos++ = '\0';
		while (*pos == ' ')
			*pos++ = '\0';
		pos2 = os_strchr(pos, '\r');
		if (!pos2)
			pos2 = os_strchr(pos, '\n');
		if (pos2)
			*pos2 = '\0';
		else
			pos2 = pos + os_strlen(pos);

		if (buf[0] == '[') {
			printf("%s = %s\n", buf, pos);
			continue;
		}

		if (os_strcmp(buf, "COUNT") == 0) {
			printf("Test %s - ", pos);
			continue;
		}

		bin_len = os_strlen(pos);
		if (bin_len > sizeof(bin) * 2) {
			printf("Too long binary data (%s)\n", buf);
			return 1;
		}
		if (bin_len & 0x01) {
			printf("Odd number of hexstring values (%s)\n",
				buf);
			return 1;
		}
		bin_len /= 2;
		if (hexstr2bin(pos, bin, bin_len) < 0) {
			printf("Invalid hex string '%s' (%s)\n", pos, buf);
			return 1;
		}

		if (os_strcmp(buf, "K") == 0) {
			if (bin_len > sizeof(k)) {
				printf("Too long K (%u)\n", (unsigned) bin_len);
				return 1;
			}
			os_memcpy(k, bin, bin_len);
			k_len = bin_len;
			continue;
		}

		if (os_strcmp(buf, "P") == 0) {
			if (bin_len > sizeof(p)) {
				printf("Too long P (%u)\n", (unsigned) bin_len);
				return 1;
			}
			os_memcpy(p, bin, bin_len);
			p_len = bin_len;
			continue;
		}

		if (os_strcmp(buf, "C") != 0) {
			printf("Unexpected field '%s'\n", buf);
			continue;
		}

		if (bin_len > sizeof(c)) {
			printf("Too long C (%u)\n", (unsigned) bin_len);
			return 1;
		}
		os_memcpy(c, bin, bin_len);
		c_len = bin_len;

		if (p_len % 8 != 0 || c_len % 8 != 0 || c_len - p_len != 8) {
			printf("invalid parameter length (p_len=%u c_len=%u)\n",
			       (unsigned) p_len, (unsigned) c_len);
			continue;
		}

		if (aes_wrap(k, k_len, p_len / 8, p, result)) {
			printf("aes_wrap() failed\n");
			ret++;
			continue;
		}

		if (os_memcmp(c, result, c_len) == 0) {
			printf("OK\n");
			ok++;
		} else {
			printf("FAIL\n");
			ret++;
		}
	}

	fclose(f);

	if (ret)
		printf("Test case failed\n");
	else
		printf("%d test vectors OK\n", ok);

	return ret;
}
Exemple #13
0
int
yacl_aes_wrap(const uint8_t *kek, size_t kek_len,
                  const uint8_t *wkey, uint8_t *out)
{
  return aes_wrap(kek, kek_len, 4, wkey, out);
}