----------------------------------------------------------------------------- Generate authentication data from a security-encrypted message -----------------------------------------------------------------------------
| 45 | // Generate authentication data from a security-encrypted message |
| 46 | //----------------------------------------------------------------------------- |
| 47 | bool GenerateAuthentication |
| 48 | ( |
| 49 | uint8 const* _data, // Starting from the command class command |
| 50 | uint32 const _length, |
| 51 | Driver *driver, |
| 52 | uint8 const _sendingNode, |
| 53 | uint8 const _receivingNode, |
| 54 | uint8 *iv, |
| 55 | uint8* _authentication // 8-byte buffer that will be filled with the authentication data |
| 56 | ) |
| 57 | { |
| 58 | // Build a buffer containing a 4-byte header and the encrypted |
| 59 | // message data, padded with zeros to a 16-byte boundary. |
| 60 | uint8 buffer[256]; |
| 61 | uint8 tmpauth[16]; |
| 62 | memset(buffer, 0, 256); |
| 63 | memset(tmpauth, 0, 16); |
| 64 | buffer[0] = _data[0]; // Security command class command |
| 65 | buffer[1] = _sendingNode; |
| 66 | buffer[2] = _receivingNode; |
| 67 | buffer[3] = _length - 19; // Subtract 19 to account for the 9 security command class bytes that come before and after the encrypted data |
| 68 | memcpy( &buffer[4], &_data[9], _length-19 ); // Encrypted message |
| 69 | |
| 70 | uint8 bufsize = _length - 19 + 4; /* the size of buffer */ |
| 71 | #ifdef DEBUG |
| 72 | PrintHex("Raw Auth (minus IV)", buffer, bufsize); |
| 73 | Log::Write(LogLevel_Debug, _receivingNode, "Raw Auth (Minus IV) Size: %d (%d)", bufsize, bufsize+16); |
| 74 | #endif |
| 75 | |
| 76 | aes_mode_reset(driver->GetAuthKey()); |
| 77 | /* encrypt the IV with ecb */ |
| 78 | if (aes_ecb_encrypt(iv, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) { |
| 79 | Log::Write(LogLevel_Warning, _receivingNode, "Failed Initial ECB Encrypt of Auth Packet"); |
| 80 | return false; |
| 81 | } |
| 82 | |
| 83 | /* our temporary holding var */ |
| 84 | uint8 encpck[16]; |
| 85 | |
| 86 | int block = 0; |
| 87 | /* reset our encpck temp var */ |
| 88 | memset(encpck, 0, 16); |
| 89 | /* now xor the buffer with our encrypted IV */ |
| 90 | for (int i = 0; i < bufsize; i++) { |
| 91 | encpck[block] = buffer[i]; |
| 92 | block++; |
| 93 | /* if we hit a blocksize, then encrypt */ |
| 94 | if (block == 16) { |
| 95 | for (int j = 0; j < 16; j++) { |
| 96 | /* here we do our xor */ |
| 97 | tmpauth[j] = encpck[j] ^ tmpauth[j]; |
| 98 | /* and reset encpck for good measure */ |
| 99 | encpck[j] = 0; |
| 100 | } |
| 101 | /* reset our block counter back to 0 */ |
| 102 | block = 0; |
| 103 | aes_mode_reset(driver->GetAuthKey()); |
| 104 | if (aes_ecb_encrypt(tmpauth, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) { |
no test coverage detected