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 * decrypt_eapol_key_data_aes(const u8 *kek,
				       const struct wpa_eapol_key *hdr,
				       size_t *len)
{
	u8 *buf;
	u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);

	if (keydatalen % 8) {
		wpa_printf(MSG_INFO, "Unsupported AES-WRAP len %d",
			   keydatalen);
		return NULL;
	}
	keydatalen -= 8; /* AES-WRAP adds 8 bytes */
	buf = os_malloc(keydatalen);
	if (buf == NULL)
		return NULL;
	if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) {
		os_free(buf);
		wpa_printf(MSG_INFO, "AES unwrap failed - "
			   "could not decrypt EAPOL-Key key data");
		return NULL;
	}

	*len = keydatalen;
	return buf;
}
Exemple #3
0
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
					   struct wpa_eapol_key *key, u16 ver)
{
	u16 keydatalen = WPA_GET_BE16(key->key_data_length);

	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
		    (u8 *) (key + 1), keydatalen);
	if (!sm->ptk_set) {
		wpa_printf(MSG_WARNING, "WPA: PTK not available, "
			   "cannot decrypt EAPOL-Key key data.");
		return -1;
	}

	/* Decrypt key data here so that this operation does not need
	 * to be implemented separately for each message type. */
	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
		u8 ek[32];
		os_memcpy(ek, key->key_iv, 16);
		os_memcpy(ek + 16, sm->ptk.kek, 16);
		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
			wpa_printf(MSG_ERROR, "WPA: RC4 failed");
			return -1;
		}
	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
		u8 *buf;
		if (keydatalen % 8) {
			wpa_printf(MSG_WARNING, "WPA: Unsupported "
				   "AES-WRAP len %d", keydatalen);
			return -1;
		}
		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
		buf = os_malloc(keydatalen);
		if (buf == NULL) {
			wpa_printf(MSG_WARNING, "WPA: No memory for "
				   "AES-UNWRAP buffer");
			return -1;
		}
		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
			       (u8 *) (key + 1), buf)) {
			os_free(buf);
			wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - "
				   "could not decrypt EAPOL-Key key data");
			return -1;
		}
		os_memcpy(key + 1, buf, keydatalen);
		os_free(buf);
		WPA_PUT_BE16(key->key_data_length, keydatalen);
	} else {
		wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d",
			   ver);
		return -1;
	}
	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
			(u8 *) (key + 1), keydatalen);
	return 0;
}
Exemple #4
0
static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
				       size_t igtk_elem_len)
{
	u8 igtk[WPA_IGTK_LEN];
	u16 keyidx;

	if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
		return 0;

	if (igtk_elem == NULL) {
		wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE");
		return 0;
	}

	wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
			igtk_elem, igtk_elem_len);

	if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) {
		wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem "
			   "length %lu", (unsigned long) igtk_elem_len);
		return -1;
	}
	if (igtk_elem[8] != WPA_IGTK_LEN) {
		wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length "
			   "%d", igtk_elem[8]);
		return -1;
	}

	if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8,
		       igtk_elem + 9, igtk)) {
		wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
			   "decrypt IGTK");
		return -1;
	}

	/* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */

	keyidx = WPA_GET_LE16(igtk_elem);

	wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
			WPA_IGTK_LEN);
	if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
			   igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
		wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
			   "driver.");
		return -1;
	}

	return 0;
}
Exemple #5
0
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
					   struct wpa_eapol_key *key, u16 ver)
{
	u16 keydatalen = WPA_GET_BE16(key->key_data_length);

	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",(u8 *) (key + 1), keydatalen);
	if (!sm->ptk_set) //wpa_supplicant_verify_eapol_key_mic ÖÐÉèÖÃ
    {
		lwip_log("WPA: PTK not available, cannot decrypt EAPOL-Key key data.\n");
		return -1;
	}

	/* Decrypt key data here so that this operation does not need
	 * to be implemented separately for each message type. */
	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4)
    {
		u8 ek[32];
		os_memcpy(ek, key->key_iv, 16);
		os_memcpy(ek + 16, sm->ptk.kek, 16);
		rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen);
	} 
    else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES)
    {
		u8 buf[512];
		if (keydatalen % 8)
        {
			lwip_log("WPA: Unsupported AES-WRAP len %d\n", keydatalen);
			return -1;
		}
		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
		if (buf == NULL)
        {
			lwip_log("WPA: No memory for AES-UNWRAP buffer\n");
			return -1;
		}
		if (aes_unwrap(sm->ptk.kek, keydatalen / 8, (u8 *)(key + 1), buf))
	    {
			lwip_log("WPA: AES unwrap failed - could not decrypt EAPOL-Key key data\n");
			return -1;
		}
		os_memcpy(key + 1, buf, keydatalen);
		WPA_PUT_BE16(key->key_data_length, keydatalen);
	}
	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", (u8*)(key + 1), keydatalen);
	
	return 0;
}
Exemple #6
0
/* Decrypt a key data from a WPA key message */
bool
BCMROMFN(wpa_decr_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:
		bcopy(body->iv, encrkey, WPA_MIC_KEY_LEN);
		bcopy(ekey, &encrkey[WPA_MIC_KEY_LEN], WPA_MIC_KEY_LEN);
		/* decrypt the key data */
		prepare_key(encrkey, WPA_MIC_KEY_LEN*2, rc4key);
		rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */
		if (gtk)
			len = ntoh16_ua((uint8 *)&body->key_len);
		else
			len = ntoh16_ua((uint8 *)&body->data_len);
		rc4(body->data, len, rc4key);
		if (gtk)
			bcopy(body->data, gtk, len);
		break;

	case WPA_KEY_DESC_V2:
	case WPA_KEY_DESC_V3:
		len = ntoh16_ua((uint8 *)&body->data_len);
		if (aes_unwrap(WPA_MIC_KEY_LEN, ekey, len, body->data,
		               gtk ? gtk : body->data)) {
			return FALSE;
		}
		break;

	default:
		return FALSE;
	}
	return TRUE;
}
Exemple #7
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 #8
0
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
				      size_t gtk_elem_len)
{
	u8 gtk[32];
	int keyidx;
	enum wpa_alg alg;
	size_t gtk_len, keylen, rsc_len;

	if (gtk_elem == NULL) {
		wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE");
		return 0;
	}

	wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
			gtk_elem, gtk_elem_len);

	if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 ||
	    gtk_elem_len - 19 > sizeof(gtk)) {
		wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem "
			   "length %lu", (unsigned long) gtk_elem_len);
		return -1;
	}
	gtk_len = gtk_elem_len - 19;
	if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11,
		       gtk)) {
		wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
			   "decrypt GTK");
		return -1;
	}

	keylen = wpa_cipher_key_len(sm->group_cipher);
	rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
	alg = wpa_cipher_to_alg(sm->group_cipher);
	if (alg == WPA_ALG_NONE) {
		wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
			   sm->group_cipher);
		return -1;
	}

	if (gtk_len < keylen) {
		wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE");
		return -1;
	}

	/* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */

	keyidx = WPA_GET_LE16(gtk_elem) & 0x03;

	if (gtk_elem[2] != keylen) {
		wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
			   "negotiated %lu",
			   gtk_elem[2], (unsigned long) keylen);
		return -1;
	}

	wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
	if (sm->group_cipher == WPA_CIPHER_TKIP) {
		/* Swap Tx/Rx keys for Michael MIC */
		u8 tmp[8];
		os_memcpy(tmp, gtk + 16, 8);
		os_memcpy(gtk + 16, gtk + 24, 8);
		os_memcpy(gtk + 24, tmp, 8);
	}
	if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
			   gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
			   "driver.");
		return -1;
	}

	return 0;
}
Exemple #9
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;
}
Exemple #10
0
static bRC do_set_scsi_encryption_key(void *value)
{
   DCR *dcr;
   DEVICE *dev;
   DEVRES *device;
   DIRRES *director;
   char StoredVolEncrKey[MAX_NAME_LENGTH];
   char VolEncrKey[MAX_NAME_LENGTH];

   /*
    * Unpack the arguments passed in.
    */
   dcr = (DCR *)value;
   if (!dcr) {
      return bRC_Error;
   }
   dev = dcr->dev;
   if (!dev) {
      return bRC_Error;
   }
   device = dev->device;
   if (!device) {
      return bRC_Error;
   }

   *StoredVolEncrKey = '\0';
   if (!get_volume_encryption_key(dcr, StoredVolEncrKey)) {
      return bRC_Error;
   }

   /*
    * See if a volume encryption key is available.
    */
   if (!*StoredVolEncrKey) {
      Dmsg0(dbglvl, "scsicrypto-sd: No encryption key to load on device\n");
      return bRC_OK;
   }

   /*
    * See if device supports hardware encryption.
    */
   if (!device->drive_crypto_enabled) {
      Dmsg0(dbglvl, "scsicrypto-sd: Trying to load encryption key on drive without support\n");
      Emsg0(M_ERROR, 0,
            _("scsicrypto-sd: Trying to load encryption key on drive without support\n"));
      return bRC_Error;
   }

   /*
    * The key passed from the director to the storage daemon is always base64 encoded.
    */
   base64_to_bin(VolEncrKey, sizeof(VolEncrKey), StoredVolEncrKey, strlen(StoredVolEncrKey));

   /*
    * See if we have an key encryption key in the config then the passed key
    * has been wrapped using RFC3394 key wrapping. We first copy the current
    * wrapped key into a temporary variable for unwrapping.
    */
   if (dcr->jcr && dcr->jcr->director) {
      director = dcr->jcr->director;
      if (director->keyencrkey) {
         char WrappedVolEncrKey[MAX_NAME_LENGTH];

         memcpy(WrappedVolEncrKey, VolEncrKey, MAX_NAME_LENGTH);
         memset(VolEncrKey, 0, MAX_NAME_LENGTH);

         if (aes_unwrap((unsigned char *)director->keyencrkey,
                        DEFAULT_PASSPHRASE_LENGTH / 8,
                        (unsigned char *)WrappedVolEncrKey,
                        (unsigned char *)VolEncrKey) != 0) {
            Dmsg1(dbglvl,
                  "scsicrypto-sd: Failed to unwrap encryption key using %s\n", director->keyencrkey);
            Emsg0(M_ERROR, 0,
                  _("scsicrypto-sd: Failed to unwrap encryption key, probably wrong KeyEncryptionKey in config\n"));
            return bRC_Error;
         }
      }
   }

   Dmsg1(dbglvl, "scsicrypto-sd: Loading new crypto key %s\n", VolEncrKey);

   P(crypto_operation_mutex);
   if (set_scsi_encryption_key(dev->fd(), dev->dev_name, VolEncrKey)) {
      dev->set_crypto_enabled();
      V(crypto_operation_mutex);
      return bRC_OK;
   } else {
      V(crypto_operation_mutex);
      return bRC_Error;
   }
}
static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
				      const u8 *client_random,
				      const u8 *server_random,
				      u8 *master_secret)
{
	struct eap_fast_data *data = ctx;
	const u8 *pac_opaque;
	size_t pac_opaque_len;
	u8 *buf, *pos, *end, *pac_key = NULL;
	os_time_t lifetime = 0;
	struct os_time now;
	u8 *identity = NULL;
	size_t identity_len = 0;

	wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback");
	wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)",
		    ticket, len);

	if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid "
			   "SessionTicket");
		return 0;
	}

	pac_opaque_len = WPA_GET_BE16(ticket + 2);
	pac_opaque = ticket + 4;
	if (pac_opaque_len < 8 || pac_opaque_len % 8 ||
	    pac_opaque_len > len - 4) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid PAC-Opaque "
			   "(len=%lu left=%lu)",
			   (unsigned long) pac_opaque_len,
			   (unsigned long) len);
		return 0;
	}
	wpa_hexdump(MSG_DEBUG, "EAP-FAST: Received PAC-Opaque",
		    pac_opaque, pac_opaque_len);

	buf = os_malloc(pac_opaque_len - 8);
	if (buf == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory "
			   "for decrypting PAC-Opaque");
		return 0;
	}

	if (aes_unwrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
		       (pac_opaque_len - 8) / 8, pac_opaque, buf) < 0) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt "
			   "PAC-Opaque");
		os_free(buf);
		/*
		 * This may have been caused by server changing the PAC-Opaque
		 * encryption key, so just ignore this PAC-Opaque instead of
		 * failing the authentication completely. Provisioning can now
		 * be used to provision a new PAC.
		 */
		return 0;
	}

	end = buf + pac_opaque_len - 8;
	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted PAC-Opaque",
			buf, end - buf);

	pos = buf;
	while (end - pos > 1) {
		u8 id, elen;

		id = *pos++;
		elen = *pos++;
		if (elen > end - pos)
			break;

		switch (id) {
		case PAC_OPAQUE_TYPE_PAD:
			goto done;
		case PAC_OPAQUE_TYPE_KEY:
			if (elen != EAP_FAST_PAC_KEY_LEN) {
				wpa_printf(MSG_DEBUG,
					   "EAP-FAST: Invalid PAC-Key length %d",
					   elen);
				os_free(buf);
				return -1;
			}
			pac_key = pos;
			wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key from "
					"decrypted PAC-Opaque",
					pac_key, EAP_FAST_PAC_KEY_LEN);
			break;
		case PAC_OPAQUE_TYPE_LIFETIME:
			if (elen != 4) {
				wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid "
					   "PAC-Key lifetime length %d",
					   elen);
				os_free(buf);
				return -1;
			}
			lifetime = WPA_GET_BE32(pos);
			break;
		case PAC_OPAQUE_TYPE_IDENTITY:
			identity = pos;
			identity_len = elen;
			break;
		}

		pos += elen;
	}
done:

	if (pac_key == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key included in "
			   "PAC-Opaque");
		os_free(buf);
		return -1;
	}

	if (identity) {
		wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Identity from "
				  "PAC-Opaque", identity, identity_len);
		os_free(data->identity);
		data->identity = os_malloc(identity_len);
		if (data->identity) {
			os_memcpy(data->identity, identity, identity_len);
			data->identity_len = identity_len;
		}
	}

	if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore "
			   "(lifetime=%ld now=%ld)", lifetime, now.sec);
		data->send_new_pac = 2;
		/*
		 * Allow PAC to be used to allow a PAC update with some level
		 * of server authentication (i.e., do not fall back to full TLS
		 * handshake since we cannot be sure that the peer would be
		 * able to validate server certificate now). However, reject
		 * the authentication since the PAC was not valid anymore. Peer
		 * can connect again with the newly provisioned PAC after this.
		 */
	} else if (lifetime - now.sec < data->pac_key_refresh_time) {
		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key soft timeout; send "
			   "an update if authentication succeeds");
		data->send_new_pac = 1;
	}

	eap_fast_derive_master_secret(pac_key, server_random, client_random,
				      master_secret);

	os_free(buf);

	return 1;
}
Exemple #12
0
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
                                      size_t gtk_elem_len)
{
    u8 gtk[32];
    int keyidx;
    wpa_alg alg;
    size_t gtk_len, keylen, rsc_len;

    if (gtk_elem == NULL) {
        wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE");
        return 0;
    }

    wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
                    gtk_elem, gtk_elem_len);

    if (gtk_elem_len < 10 + 24 || (gtk_elem_len - 10) % 8 ||
            gtk_elem_len - 18 > sizeof(gtk)) {
        wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem "
                   "length %lu", (unsigned long) gtk_elem_len);
        return -1;
    }
    gtk_len = gtk_elem_len - 18;
    if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 10, gtk)) {
        wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
                   "decrypt GTK");
        return -1;
    }

    switch (sm->group_cipher) {
    case WPA_CIPHER_CCMP:
        keylen = 16;
        rsc_len = 6;
        alg = WPA_ALG_CCMP;
        break;
    case WPA_CIPHER_TKIP:
        keylen = 32;
        rsc_len = 6;
        alg = WPA_ALG_TKIP;
        break;
    case WPA_CIPHER_WEP104:
        keylen = 13;
        rsc_len = 0;
        alg = WPA_ALG_WEP;
        break;
    case WPA_CIPHER_WEP40:
        keylen = 5;
        rsc_len = 0;
        alg = WPA_ALG_WEP;
        break;
    default:
        wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
                   sm->group_cipher);
        return -1;
    }

    if (gtk_len < keylen) {
        wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE");
        return -1;
    }

    /* Key Info[1] | Key Length[1] | RSC[8] | Key[5..32]. */

    keyidx = gtk_elem[0] & 0x03;

    if (gtk_elem[1] != keylen) {
        wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
                   "negotiated %lu",
                   gtk_elem[1], (unsigned long) keylen);
        return -1;
    }

    wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
    if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
                       keyidx, 0, gtk_elem + 2, rsc_len, gtk, keylen) <
            0) {
        wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
                   "driver.");
        return -1;
    }

    return 0;
}
Exemple #13
0
static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
			      const u8 *src_addr,
			      const u8 *data, size_t data_len)
{
	struct ft_r0kh_r1kh_resp_frame *frame, f;
	struct ft_remote_r0kh *r0kh;
	int pairwise;

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

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

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

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

	if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN)
	    != 0) {
		wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a "
			   "matching R1KH-ID");
		return -1;
	}

	/* TODO: verify that <nonce,s1kh_id> matches with a pending request
	 * and call this requests callback function to finish request
	 * processing */

	pairwise = le_to_host16(f.pairwise);
	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
		    f.nonce, sizeof(f.nonce));
	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
		   MACSTR " pairwise=0x%x",
		   MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
			f.pmk_r1, PMK_LEN);
	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
			f.pmk_r1_name, WPA_PMK_NAME_LEN);

	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
			    pairwise);
	os_memset(f.pmk_r1, 0, PMK_LEN);

	return 0;
}
Exemple #14
0
static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
			      const u8 *src_addr,
			      const u8 *data, size_t data_len)
{
	struct ft_r0kh_r1kh_push_frame *frame, f;
	struct ft_remote_r0kh *r0kh;
	struct os_time now;
	os_time_t tsend;
	int pairwise;

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

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

	r0kh = wpa_auth->conf.r0kh_list;
	while (r0kh) {
		if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
			break;
		r0kh = r0kh->next;
	}
	if (r0kh == NULL) {
		wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
			   "PMK-R0 push source address " MACSTR,
			   MAC2STR(src_addr));
		return -1;
	}

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

	os_get_time(&now);
	tsend = WPA_GET_LE32(f.timestamp);
	if ((now.sec > tsend && now.sec - tsend > 60) ||
	    (now.sec < tsend && tsend - now.sec > 60)) {
		wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid "
			   "timestamp: sender time %d own time %d\n",
			   (int) tsend, (int) now.sec);
		return -1;
	}

	if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN)
	    != 0) {
		wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching "
			   "R1KH-ID (received " MACSTR " own " MACSTR ")",
			   MAC2STR(f.r1kh_id),
			   MAC2STR(wpa_auth->conf.r1_key_holder));
		return -1;
	}

	pairwise = le_to_host16(f.pairwise);
	wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID="
		   MACSTR " pairwise=0x%x",
		   MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1",
			f.pmk_r1, PMK_LEN);
	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name",
			f.pmk_r1_name, WPA_PMK_NAME_LEN);

	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
			    pairwise);
	os_memset(f.pmk_r1, 0, PMK_LEN);

	return 0;
}
Exemple #15
0
static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
					     const struct wpa_eapol_key *key,
					     size_t keydatalen, int key_info,
					     size_t extra_len, u16 ver,
					     struct wpa_gtk_data *gd)
{
	size_t maxkeylen;
	u8 ek[32];

	gd->gtk_len = WPA_GET_BE16(key->key_length);
	maxkeylen = keydatalen;
	if (keydatalen > extra_len) {
		wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:"
			   " key_data_length=%lu > extra_len=%lu",
			   (unsigned long) keydatalen,
			   (unsigned long) extra_len);
		return -1;
	}
	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
		if (maxkeylen < 8) {
			wpa_printf(MSG_INFO, "WPA: Too short maxkeylen (%lu)",
				   (unsigned long) maxkeylen);
			return -1;
		}
		maxkeylen -= 8;
	}

	if (wpa_supplicant_check_group_cipher(sm->group_cipher,
					      gd->gtk_len, maxkeylen,
					      &gd->key_rsc_len, &gd->alg))
		return -1;

	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
		WPA_KEY_INFO_KEY_INDEX_SHIFT;
	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
		os_memcpy(ek, key->key_iv, 16);
		os_memcpy(ek + 16, sm->ptk.kek, 16);
		if (keydatalen > sizeof(gd->gtk)) {
			wpa_printf(MSG_WARNING, "WPA: RC4 key data "
				   "too long (%lu)",
				   (unsigned long) keydatalen);
			return -1;
		}
		os_memcpy(gd->gtk, key + 1, keydatalen);
		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
			wpa_printf(MSG_ERROR, "WPA: RC4 failed");
			return -1;
		}
	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
		if (keydatalen % 8) {
			wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP "
				   "len %lu", (unsigned long) keydatalen);
			return -1;
		}
		if (maxkeylen > sizeof(gd->gtk)) {
			wpa_printf(MSG_WARNING, "WPA: AES-WRAP key data "
				   "too long (keydatalen=%lu maxkeylen=%lu)",
				   (unsigned long) keydatalen,
				   (unsigned long) maxkeylen);
			return -1;
		}
		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,
			       (const u8 *) (key + 1), gd->gtk)) {
			wpa_printf(MSG_WARNING, "WPA: AES unwrap "
				   "failed - could not decrypt GTK");
			return -1;
		}
	} else {
		wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d",
			   ver);
		return -1;
	}
	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
		sm, !!(key_info & WPA_KEY_INFO_TXRX));
	return 0;
}
Exemple #16
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 #17
0
static int test_nist_key_wrap_ad(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;
	int fail;

	printf("NIST KW AD 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;
		fail = 0;
		pos = os_strchr(buf, '=');
		if (pos == NULL) {
			if (os_strncmp(buf, "FAIL", 4) == 0) {
				fail = 1;
				goto skip_val_parse;
			}
			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, "C") == 0) {
			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;
			continue;
		}

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

			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;

			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_unwrap(k, k_len, (c_len / 8) - 1, c, result)) {
			if (fail) {
				printf("OK (fail reported)\n");
				ok++;
				continue;
			}
			printf("aes_unwrap() failed\n");
			ret++;
			continue;
		}

		if (fail) {
			printf("FAIL (mismatch not reported)\n");
			ret++;
		} else if (os_memcmp(p, result, p_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 #18
0
/**
 * cckm_egtk_to_gtk - Calculate GTK from Encrypted GTK
 * @cckm_rn: Association Request Numner
 * @gtk: Length of BTK
 * @gtk_len: Length of GTK
 *
 * GTK = RC4(RN | PTK-802.1X-Encrypt-Key, EGTK)
 * GTK = AES-Keywrap(PTK-802.1X-Encrypt-Key, EGTK)
 * - where PTK-802.1X-Encrypt-Key is the key as defined in Section 0
 * - Note that while the IV is not transmitted in the clear, its encrypted
 *   value is included in the EGTK. Thus, the EGTK length shall be the GTK
 *   key length plus 8 octets (e.g. the IV length). More explicitly, if the
 *   broadcast cipher is TKIP, while the GTK is 32 octets, the EGTK shall
 *   be 40 octets; similarly for AESCCMP, the GTK is 16 octets while the
 *   EGTK shall be 24 octets.
 */
static int cckm_install_gtk(struct wpa_sm *sm, u32 cckm_rn, u8 *gtk,
		int gtk_len, int keyidx, const u8 *key_rsc, int key_rsc_len)
{
	u8 gtk_buf[32];
	enum wpa_alg alg;

	switch (sm->group_cipher) {
		case WPA_CIPHER_CCMP:
			alg = WPA_ALG_CCMP;
			break;
		case WPA_CIPHER_TKIP:
			alg = WPA_ALG_TKIP;
			break;
		case WPA_CIPHER_NONE:
			wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: "
					"NONE - do not use pairwise keys");
			return 0;
		default:
			wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d",
					sm->pairwise_cipher);
			return -1;
	}

	if (sm->group_cipher == WPA_CIPHER_CCMP) {
		gtk_len -= 8;
		if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk, gtk_buf)) {
			wpa_printf(MSG_WARNING, "WPA: AES unwrap "
					"failed - could not decrypt GTK");
			return -1;
		}
		gtk = gtk_buf;
	} else if (sm->group_cipher == WPA_CIPHER_TKIP) {
		u8 data[20];

		WPA_PUT_LE32(data, cckm_rn);
		os_memcpy(data + 4, &sm->ptk.kek, sizeof(sm->ptk.kek));
		wpa_hexdump_key(MSG_DEBUG, "EGTK-Data", data, sizeof(data));

		rc4_skip(data, sizeof(data), 256, gtk, gtk_len);

		/* Swap Tx/Rx keys for Michael MIC */
		os_memcpy(gtk_buf, gtk, 16);
		os_memcpy(gtk_buf + 16, gtk + 24, 8);
		os_memcpy(gtk_buf + 24, gtk + 16, 8);
		gtk = gtk_buf;
	}

	wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gtk, gtk_len);
	wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver "
			"(keyidx=%d tx=%d len=%d).", keyidx, 0, gtk_len);
	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, key_rsc_len);

	if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
				keyidx, 0, key_rsc, key_rsc_len,
				gtk, gtk_len) < 0) {
		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to "
				"the driver.");
		return -1;
	}

	return 0;
}
Exemple #19
0
int
yacl_aes_unwrap(const uint8_t *kek, size_t kek_len,
                const uint8_t *cipher, uint8_t *plain)
{
  return aes_unwrap(kek, kek_len, 4, cipher, plain);
}