/** * @brief Computes MIC * * This function computes the MIC according to CCM. * * The key was initialized in other functions before. * * @param[in] buffer Input data (frame, not padded yet) * @param[out] mic Computed MIC of size AES_BLOCKSIZE * @param[in] nonce The nonce: Initialization Vector (IV) as used in * cryptography; the ZigBee nonce are the bytes 2...14 * of this nonce * @param[in] hdr_len Size of plain text header in bytes (may be 0) * @param[in] pld_len Length of payload in bytes (may be 0) */ void compute_mic(uint8_t *buffer, uint8_t *mic, uint8_t *nonce, uint8_t hdr_len, uint8_t pld_len) { sal_aes_setup(NULL, AES_MODE_ECB, AES_DIR_ENCRYPT); #if (SAL_TYPE == AT86RF2xx) sal_aes_wrrd(nonce, NULL); #else sal_aes_exec(nonce); #endif sal_aes_setup(NULL, AES_MODE_CBC, AES_DIR_ENCRYPT); if (hdr_len) { uint8_t locbuf[AES_BLOCKSIZE]; uint8_t firstlen; firstlen = MIN(AES_BLOCKSIZE - 2, hdr_len); /* Prepend L(a). */ locbuf[0] = 0; locbuf[1] = hdr_len; memcpy(locbuf + 2, buffer, firstlen); encrypt_with_padding(locbuf, firstlen + 2); if (firstlen < hdr_len) { /* No padding up to now since firstlen is AES_BLOCKSIZE *- 2. */ encrypt_with_padding(buffer + firstlen, hdr_len - firstlen); } } encrypt_with_padding(buffer + hdr_len, pld_len); sal_aes_read(mic); }
void encrypt_pldmic(uint8_t *buffer, uint8_t *nonce, uint8_t mic_len, uint8_t pld_len) { uint8_t ctr; uint8_t i; uint8_t keystream[AES_BLOCKSIZE]; uint8_t *keystreamptr; int spld_len; spld_len = (int)pld_len; /* max. value: 0x7f */ sal_aes_setup(NULL, AES_MODE_ECB, AES_DIR_ENCRYPT); ctr = 0; while (spld_len > 0) { /* Compute the keystream block. */ nonce[AES_BLOCKSIZE - 1] = ++ctr; sal_aes_exec(nonce); sal_aes_read(keystream); /* En/decrypt payload. */ for (i = MIN(spld_len, AES_BLOCKSIZE), keystreamptr = keystream; i--; /* */) { *buffer++ ^= *keystreamptr++; } spld_len -= AES_BLOCKSIZE; } /* En/decrypt MIC. */ if (mic_len) { /* Prepare the keystream for MIC. */ nonce[AES_BLOCKSIZE - 1] = 0; sal_aes_exec(nonce); sal_aes_read(keystream); for (i = mic_len, keystreamptr = keystream; i--; /* */) { *buffer++ ^= *keystreamptr++; } } }
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { int retval = 0; switch (keybits) { case 128: sal_aes_setup((uint8_t *)key, AES_MODE_ECB, AES_DIR_DECRYPT); break; default: retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; break; } return retval; }
void sal_aes_dec_key(uint8_t dir) { uint8_t i; if(dir==AES_DIR_ENCRYPT) { aes_buf[0]=AES_MODE_KEY; for(i=1;i<AES_KEYSIZE;i++) { aes_buf[i]=0x00; } hal_sram_write(AES_CON, AES_BLOCKSIZE+1, aes_buf); hal_sram_read(AES_STATE_KEY, AES_KEYSIZE, dec_key); setup_flag = true; } else if((dir==AES_DIR_DECRYPT)&&setup_flag) { sal_aes_setup(dec_key); setup_flag=false; } }
/*************************************************************************//** *****************************************************************************/ void PHY_EncryptReq(uint8_t *text, uint8_t *key) { sal_aes_setup(key, AES_MODE_ECB, AES_DIR_ENCRYPT); sal_aes_exec(text); sal_aes_read(text); }
/** * @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 Encrypts and decrypts payload and MIC * * This function perform encryption and decryption of the payload and the MIC. * * @param[in] buffer Input data (frame, not padded yet) * @param[in] nonce The nonce * @param[in] mic_len Size of MIC in bytes (may be 0) * @param[in] pld_len Length of payload in bytes (may be 0) */ void encrypt_pldmic(uint8_t *buffer, uint8_t *nonce, uint8_t mic_len, uint8_t pld_len) { uint8_t ctr; uint8_t i; uint8_t keystream[AES_BLOCKSIZE]; uint8_t *keystreamptr; sal_aes_setup(NULL, AES_MODE_ECB, AES_DIR_ENCRYPT); /* Init first keystream block. */ nonce[AES_BLOCKSIZE - 1] = ctr = 1; if (pld_len > 0) { sal_aes_wrrd(nonce, NULL); } while (true) { /* Compute next keystream block and get the previous one. */ if (pld_len <= AES_BLOCKSIZE) { /* Last block */ if (mic_len) { /* Prepare the keystream for MIC. */ nonce[AES_BLOCKSIZE - 1] = 0; sal_aes_wrrd(nonce, keystream); } else { sal_aes_read(keystream); } } else { /* Prepare the next keystream block. */ nonce[AES_BLOCKSIZE - 1] = ++ctr; sal_aes_wrrd(nonce, keystream); } /* En/decrypt payload. */ for (i = MIN(pld_len, AES_BLOCKSIZE), keystreamptr = keystream; i--; /* */) { *buffer++ ^= *keystreamptr++; } if (pld_len <= AES_BLOCKSIZE) { break; } pld_len -= AES_BLOCKSIZE; } /* En/decrypt MIC. */ if (mic_len) { sal_aes_read(keystream); for (i = mic_len, keystreamptr = keystream; i--; /* */) { *buffer++ ^= *keystreamptr++; } } }
/** * @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); }