Beispiel #1
0
/**
 * @brief Secure one block with CCM*
 *
 * This functions secures one block with CCM* according to 802.15.4.
 *
 * @param[in,out] buffer Input: plaintext header and payload concatenated;
 *                       for encryption: MUST HAVE 'AES_BLOCKSIZE'
 *                       BYTES SPACE AT THE END FOR THE MIC!
 *                       Output: frame secured (with MIC at end)/unsecured
 * @param[in]  nonce   The nonce: Initialization Vector (IV) as used in
 *                     cryptography; the ZigBee nonce (13 bytes long)
 *                     are the bytes 2...14 of this nonce
 * @param[in] key The key to be used; if NULL, use the current key
 * @param[in] hdr_len Length of plaintext header (will not be encrypted)
 * @param[in] pld_len Length of payload to be encrypted; if 0, then only MIC
 *                    authentication implies
 * @param[in] sec_level Security level according to IEEE 802.15.4,
 *                    7.6.2.2.1, Table 95:
 *                    - the value may be 0 ... 7;
 *                    - the two LSBs contain the MIC length in bytes
 *                      (0, 4, 8 or 16);
 *                    - bit 2 indicates whether encryption applies or not
 * @param[in] aes_dir AES_DIR_ENCRYPT if secure, AES_DIR_DECRYPT if unsecure
 *
 * @return STB CCM Status
 */
stb_ccm_t stb_ccm_secure(uint8_t *buffer,
                         uint8_t nonce[AES_BLOCKSIZE],
                                 uint8_t *key,
                         uint8_t hdr_len,
                         uint8_t pld_len,
                         uint8_t sec_level,
                         uint8_t aes_dir)
{
    uint8_t nonce_0;    /* nonce[0] for MIC computation. */
    uint8_t mic_len;
    uint8_t enc_flag;

    if (stb_restart_required)
    {
        sal_aes_restart();
        stb_restart_required = false;
    }

    if (sec_level & 3)
    {
        mic_len = 1 << ((sec_level & 3) + 1);
    }
    else
    {
        mic_len = 0;
    }

    enc_flag = sec_level & 4;

    /* Test on correct parameters. */

    if ((sec_level & ~0x7) ||
        (buffer == NULL) ||
        (nonce == NULL) ||
        ((uint16_t)pld_len + (uint16_t)hdr_len + (uint16_t)mic_len > aMaxPHYPacketSize)
       )
    {
        sal_aes_clean_up();
        return (STB_CCM_ILLPARM);
    }

    if (key_change && (key == NULL))
    {
        sal_aes_clean_up();
        return (STB_CCM_KEYMISS);   /* Initial call, but no key given. */
    }

    /* Setup key if necessary. */

    if(!key_change && key != NULL)    /* There was some previous key. */
    {
        uint8_t i;

        /* Test on changed key. */
        for (i = AES_BLOCKSIZE; i--; /* */)
        {
            key_change |= (last_key[i] ^ key[i]);
        }
    }

    if (key_change)
    {
        /*
         * Key must be non-NULL because of test above, and
         * ECB encryption is always the initial encryption mode.
         */
        sal_aes_setup(key, AES_MODE_ECB, AES_DIR_ENCRYPT);
        memcpy(last_key, key, AES_KEYSIZE);
        key_change = false;
    }

    /* Prepare nonce. */

    nonce[0] = 1;   /* Always 2 bytes for length field. */

    if (mic_len > 0)
    {
        nonce[0] |= ((mic_len - 2) >> 1) << 3;
    }
/**
 * @brief Secure one block with CCM*
 *
 * This functions secures one block with CCM* according to 802.15.4.
 *
 * @param[in,out] buffer Input: plaintext header and payload concatenated;
 *                       for encryption: MUST HAVE 'AES_BLOCKSIZE'
 *                       BYTES SPACE AT THE END FOR THE MIC!
 *                       Output: frame secured (with MIC at end)/unsecured
 * @param[in]  nonce   The nonce: Initialization Vector (IV) as used in
 *                     cryptography; the ZigBee nonce (13 bytes long)
 *                     are the bytes 2...14 of this nonce
 * @param[in] key The key to be used; if NULL, use the current key
 * @param[in] hdr_len Length of plain text header (will not be encrypted)
 * @param[in] pld_len Length of payload to be encrypted; if 0, then only MIC
 *                    authentication implies
 * @param[in] sec_level Security level according to IEEE 802.15.4,
 *                    7.6.2.2.1, Table 95:
 *                    - the value may be 0 ... 7;
 *                    - the two LSBs contain the MIC length in bytes
 *                      (0, 4, 8 or 16);
 *                    - bit 2 indicates whether encryption applies or not
 * @param[in] aes_dir AES_DIR_ENCRYPT if secure, AES_DIR_DECRYPT if unsecured
 *
 * @return STB CCM Status
 */
stb_ccm_t stb_ccm_secure(uint8_t *buffer,
		uint8_t nonce[AES_BLOCKSIZE],
		uint8_t *key,
		uint8_t hdr_len,
		uint8_t pld_len,
		uint8_t sec_level,
		uint8_t aes_dir)
{
	uint8_t nonce_0; /* nonce[0] for MIC computation. */
	uint8_t mic_len = 0;
	uint8_t enc_flag = ENCRYPTION_NOT_REQD;

	if (stb_restart_required) {
#if (SAL_TYPE != ATXMEGA_SAL)
		prev_trx_status = tal_trx_status;
		if (tal_trx_status == TRX_SLEEP) {
			tal_trx_wakeup();
		}
#endif
		sal_aes_restart();
		stb_restart_required = false;
	}

	switch (sec_level) {
	case SECURITY_00_LEVEL:
		/* No MIC & No Encryption at Security Level -0 */
		mic_len = LEN_MIC_00;
		break;

	case SECURITY_01_LEVEL:
		/* MIC-32 & No Encryption at Security Level -1 */
		mic_len = LEN_MIC_32;
		break;

	case SECURITY_02_LEVEL:
		/* MIC-64 & No Encryption at Security Level -2 */
		mic_len = LEN_MIC_64;
		break;

	case SECURITY_03_LEVEL:
		/* MIC-128 & No Encryption at Security Level -3 */
		mic_len = LEN_MIC_128;
		break;

	case SECURITY_04_LEVEL:
		/* No MIC & Encryption at Security Level -4 */
		mic_len = LEN_MIC_00;
		enc_flag = ENCRYPTION_REQD;
		break;

	case SECURITY_05_LEVEL:
		/* MIC-32 & Encryption at Security Level -5 */
		mic_len = LEN_MIC_32;
		enc_flag = ENCRYPTION_REQD;
		break;

	case SECURITY_06_LEVEL:
		/* MIC-64 & Encryption at Security Level -6 */
		mic_len = LEN_MIC_64;
		enc_flag = ENCRYPTION_REQD;
		break;

	case SECURITY_07_LEVEL:
		/* MIC-128 & Encryption at Security Level -7 */
		mic_len = LEN_MIC_128;
		enc_flag = ENCRYPTION_REQD;
		break;

	default:
		break;
	}

	/* Test on correct parameters. */

	if ((sec_level & ~0x7) ||
			(buffer == NULL) ||
			(nonce == NULL) ||
			((uint16_t)pld_len + (uint16_t)hdr_len +
			(uint16_t)mic_len > aMaxPHYPacketSize)
			) {
#if (SAL_TYPE != ATXMEGA_SAL)
		TRX_SLEEP();
		sal_aes_clean_up();
#endif
		return (STB_CCM_ILLPARM);
	}

	if (key_change && (key == NULL)) {
#if (SAL_TYPE != ATXMEGA_SAL)
		TRX_SLEEP();
		sal_aes_clean_up();
#endif
		/* Initial call, but no key given. */
		return (STB_CCM_KEYMISS);
	}

	/* Setup key if necessary. */

	if (!key_change && key != NULL) { /* There was some previous key. */
		uint8_t i;

		/* Test on changed key. */
		for (i = AES_BLOCKSIZE; i--; /* */) {
			key_change |= (last_key[i] ^ key[i]);
		}
	}

	if (key_change) {
		/*
		 * Key must be non-NULL because of test above, and
		 * ECB encryption is always the initial encryption mode.
		 */
		sal_aes_setup(key, AES_MODE_ECB, AES_DIR_ENCRYPT);
		memcpy(last_key, key, AES_KEYSIZE);
		key_change = false;
	}

	/* Prepare nonce. */
	nonce[0] = LEN_FIELD; /* Always 2 bytes for length field. */

	if (mic_len > 0) {
		nonce[0] |= (uint8_t)(((mic_len - 2) >> 1) << 3);
	}