LCOV - code coverage report
Current view: top level - src/utils - Cryptography.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 157 193 81.3 %
Date: 2026-06-14 08:51:17 Functions: 20 23 87.0 %

          Line data    Source code
       1             : #include "Cryptography.h"
       2             : 
       3             : #include <string.h>
       4             : 
       5           1 : RadioLibAES128::RadioLibAES128() {
       6             : 
       7           1 : }
       8             : 
       9             : /*
      10             :  * CMAC streaming API
      11             :  *
      12             :  * Usage:
      13             :  *   RadioLibCMAC_State st;
      14             :  *   RadioLibAES128_initCMACState(&RadioLibAES128Instance, &st);
      15             :  *   RadioLibAES128_updateCMACState(&RadioLibAES128Instance, &st, chunk1, len1);
      16             :  *   RadioLibAES128_updateCMACState(&RadioLibAES128Instance, &st, chunk2, len2);
      17             :  *   uint8_t mac[16];
      18             :  *   RadioLibAES128_finishCMACState(&RadioLibAES128Instance, &st, mac);
      19             :  */
      20             : 
      21           4 : void RadioLibAES128::initCMAC(RadioLibCmacState* st) {
      22           4 :   if(!st) {
      23           0 :     return;
      24             :   }
      25           4 :   memset(st->X, 0x00, RADIOLIB_AES128_BLOCK_SIZE);
      26           4 :   memset(st->buffer, 0x00, RADIOLIB_AES128_BLOCK_SIZE);
      27           4 :   st->buffer_len = 0;
      28           4 :   st->subkeys_generated = false;
      29             : }
      30             : 
      31           4 : void RadioLibAES128::updateCMAC(RadioLibCmacState* st, const uint8_t* data, size_t len) {
      32           4 :   if(!st || (!data && len != 0)) {
      33           0 :     return;
      34             :   }
      35             : 
      36             :   // ensure subkeys are present
      37           4 :   if(!st->subkeys_generated) {
      38           4 :     this->generateSubkeys(st->k1, st->k2);
      39           4 :     st->subkeys_generated = true;
      40             :   }
      41             : 
      42             :   uint8_t tmp[RADIOLIB_AES128_BLOCK_SIZE];
      43           4 :   size_t offset = 0;
      44             : 
      45          12 :   while(len > 0) {
      46             : 
      47             :     // fill buffer up to one full block
      48           8 :     size_t to_copy = RADIOLIB_AES128_BLOCK_SIZE - st->buffer_len;
      49           8 :     if(to_copy > len) {
      50           1 :       to_copy = len;
      51             :     }
      52             : 
      53             :     // copy the data into the buffer
      54           8 :     memcpy(&st->buffer[st->buffer_len], &data[offset], to_copy);
      55           8 :     st->buffer_len += to_copy;
      56           8 :     offset += to_copy;
      57           8 :     len -= to_copy;
      58             : 
      59             :     // if we now have a full block AND there is still more input remaining,
      60             :     // this block is NOT the final one, so process it.
      61           8 :     if(st->buffer_len == RADIOLIB_AES128_BLOCK_SIZE && len > 0) {
      62           5 :       this->blockXor(tmp, st->buffer, st->X);
      63           5 :       this->encryptECB(tmp, RADIOLIB_AES128_BLOCK_SIZE, st->X);
      64           5 :       st->buffer_len = 0;
      65             :     }
      66             :   }
      67             : }
      68             : 
      69           4 : void RadioLibAES128::finishCMAC(RadioLibCmacState* st, uint8_t* out) {
      70           4 :   if(!st || !out) {
      71           0 :     return;
      72             :   }
      73             : 
      74             :   // ensure subkeys are present
      75           4 :   if(!st->subkeys_generated) {
      76           0 :     this->generateSubkeys(st->k1, st->k2);
      77           0 :     st->subkeys_generated = true;
      78             :   }
      79             : 
      80             :   uint8_t last[RADIOLIB_AES128_BLOCK_SIZE];
      81             :   uint8_t Y[RADIOLIB_AES128_BLOCK_SIZE];
      82             : 
      83           4 :   if(st->buffer_len == RADIOLIB_AES128_BLOCK_SIZE) {
      84           2 :     this->blockXor(last, st->buffer, st->k1);
      85             :   } else {
      86           2 :     memset(last, 0x00, RADIOLIB_AES128_BLOCK_SIZE);
      87           2 :     if(st->buffer_len > 0) {
      88           1 :       memcpy(last, st->buffer, st->buffer_len);
      89             :     }
      90           2 :     last[st->buffer_len] = 0x80;
      91           2 :     this->blockXor(last, last, st->k2);
      92             :   }
      93             : 
      94           4 :   this->blockXor(Y, last, st->X);
      95           4 :   this->encryptECB(Y, RADIOLIB_AES128_BLOCK_SIZE, out);
      96             : }
      97             : 
      98           4 : void RadioLibAES128::generateCMAC(const uint8_t* in, size_t len, uint8_t* cmac) {
      99             :   RadioLibCmacState st;
     100           4 :   this->initCMAC(&st);
     101           4 :   this->updateCMAC(&st, in, len);
     102           4 :   this->finishCMAC(&st, cmac);
     103           4 : }
     104             : 
     105           0 : bool RadioLibAES128::verifyCMAC(const uint8_t* in, size_t len, const uint8_t* cmac) {
     106             :   uint8_t cmacReal[RADIOLIB_AES128_BLOCK_SIZE];
     107           0 :   this->generateCMAC(in, len, cmacReal);
     108           0 :   for(size_t i = 0; i < RADIOLIB_AES128_BLOCK_SIZE; i++) {
     109           0 :     if((cmacReal[i] != cmac[i])) {
     110           0 :       return(false);
     111             :     }
     112             :   }
     113           0 :   return(true);
     114             : }
     115             : 
     116          17 : void RadioLibAES128::blockXor(uint8_t* dst, const uint8_t* a, const uint8_t* b) {
     117         289 :   for(uint8_t j = 0; j < RADIOLIB_AES128_BLOCK_SIZE; j++) {
     118         272 :     dst[j] = a[j] ^ b[j];
     119             :   }
     120          17 : }
     121             : 
     122           8 : void RadioLibAES128::blockLeftshift(uint8_t* dst, const uint8_t* src) {
     123           8 :   uint8_t ovf = 0x00;
     124         136 :   for(int8_t i = RADIOLIB_AES128_BLOCK_SIZE - 1; i >= 0; i--) {
     125         128 :     dst[i] = src[i] << 1;
     126         128 :     dst[i] |= ovf;
     127         128 :     ovf = (src[i] & 0x80) ? 1 : 0;
     128             :   }
     129           8 : }
     130             : 
     131           4 : void RadioLibAES128::generateSubkeys(uint8_t* key1, uint8_t* key2) {
     132           4 :   const uint8_t const_Zero[] = {
     133             :     0x00, 0x00, 0x00, 0x00,
     134             :     0x00, 0x00, 0x00, 0x00,
     135             :     0x00, 0x00, 0x00, 0x00,
     136             :     0x00, 0x00, 0x00, 0x00
     137             :   };
     138             : 
     139           4 :   const uint8_t const_Rb[] = {
     140             :     0x00, 0x00, 0x00, 0x00,
     141             :     0x00, 0x00, 0x00, 0x00,
     142             :     0x00, 0x00, 0x00, 0x00,
     143             :     0x00, 0x00, 0x00, 0x87
     144             :   };
     145             : 
     146             :   uint8_t L[RADIOLIB_AES128_BLOCK_SIZE];
     147           4 :   this->encryptECB(const_Zero, RADIOLIB_AES128_BLOCK_SIZE, L);
     148           4 :   this->blockLeftshift(key1, L);
     149           4 :   if(L[0] & 0x80) {
     150           0 :     this->blockXor(key1, key1, const_Rb);
     151             :   }
     152             : 
     153           4 :   this->blockLeftshift(key2, key1);
     154           4 :   if(key1[0] & 0x80) {
     155           4 :     this->blockXor(key2, key2, const_Rb);
     156             :   }
     157           4 : }
     158             : 
     159             : #if !RADIOLIB_CUSTOM_AES128
     160             : 
     161             : // AES lookup tables
     162             : static const uint8_t aesSbox[] RADIOLIB_NONVOLATILE = {
     163             :     0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
     164             :     0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
     165             :     0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
     166             :     0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
     167             :     0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
     168             :     0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
     169             :     0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
     170             :     0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
     171             :     0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
     172             :     0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
     173             :     0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
     174             :     0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
     175             :     0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
     176             :     0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
     177             :     0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
     178             :     0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
     179             :     0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
     180             :     0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
     181             :     0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
     182             :     0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
     183             :     0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
     184             :     0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
     185             :     0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
     186             :     0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
     187             :     0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
     188             :     0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
     189             :     0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
     190             :     0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
     191             :     0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
     192             :     0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
     193             :     0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
     194             :     0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
     195             : };
     196             : 
     197             : static const uint8_t aesSboxInv[] RADIOLIB_NONVOLATILE = {
     198             :     0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
     199             :     0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
     200             :     0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
     201             :     0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
     202             :     0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
     203             :     0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
     204             :     0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
     205             :     0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
     206             :     0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
     207             :     0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
     208             :     0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
     209             :     0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
     210             :     0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
     211             :     0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
     212             :     0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
     213             :     0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
     214             :     0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
     215             :     0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
     216             :     0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
     217             :     0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
     218             :     0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
     219             :     0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
     220             :     0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
     221             :     0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
     222             :     0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
     223             :     0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
     224             :     0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
     225             :     0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
     226             :     0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
     227             :     0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
     228             :     0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
     229             :     0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
     230             : };
     231             : 
     232             : static const uint8_t aesRcon[] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
     233             : 
     234           1 : RadioLibSoftwareAES128::RadioLibSoftwareAES128() : RadioLibAES128() {
     235             : 
     236           1 : }
     237             : 
     238           4 : void RadioLibSoftwareAES128::init(uint8_t* key) {
     239           4 :   this->keyPtr = key;
     240           4 :   this->keyExpansion(this->roundKey, key);
     241           4 : }
     242             : 
     243          13 : size_t RadioLibSoftwareAES128::encryptECB(const uint8_t* in, size_t len, uint8_t* out) {
     244          13 :   size_t num_blocks = len / RADIOLIB_AES128_BLOCK_SIZE;
     245          13 :   if(len % RADIOLIB_AES128_BLOCK_SIZE) {
     246           0 :     num_blocks++;
     247             :   }
     248             : 
     249          13 :   memset(out, 0x00, RADIOLIB_AES128_BLOCK_SIZE * num_blocks);
     250          13 :   memcpy(out, in, len);
     251             : 
     252          26 :   for(size_t i = 0; i < num_blocks; i++) {
     253          13 :     this->cipher((state_t*)(out + (RADIOLIB_AES128_BLOCK_SIZE * i)), this->roundKey);
     254             :   }
     255             : 
     256          13 :   return(num_blocks*RADIOLIB_AES128_BLOCK_SIZE);
     257             : }
     258             : 
     259           0 : size_t RadioLibSoftwareAES128::decryptECB(const uint8_t* in, size_t len, uint8_t* out) {
     260           0 :   size_t num_blocks = len / RADIOLIB_AES128_BLOCK_SIZE;
     261           0 :   if(len % RADIOLIB_AES128_BLOCK_SIZE) {
     262           0 :     num_blocks++;
     263             :   }
     264             : 
     265           0 :   memset(out, 0x00, RADIOLIB_AES128_BLOCK_SIZE * num_blocks);
     266           0 :   memcpy(out, in, len);
     267             : 
     268           0 :   for(size_t i = 0; i < num_blocks; i++) {
     269           0 :     this->decipher((state_t*)(out + (RADIOLIB_AES128_BLOCK_SIZE * i)), this->roundKey);
     270             :   }
     271             : 
     272           0 :   return(num_blocks*RADIOLIB_AES128_BLOCK_SIZE);
     273             : }
     274             : 
     275           4 : void RadioLibSoftwareAES128::keyExpansion(uint8_t* roundKey, const uint8_t* key) {
     276             :   uint8_t tmp[4];
     277             : 
     278             :   // the first round key is the key itself
     279          20 :   for(uint8_t i = 0; i < RADIOLIB_AES128_N_K; i++) {
     280          80 :     for(uint8_t j = 0; j < 4; j++) {
     281          64 :       roundKey[(i * 4) + j] = key[(i * 4) + j];
     282             :     }
     283             :   }
     284             : 
     285             :   // All other round keys are found from the previous round keys.
     286         164 :   for(uint8_t i = RADIOLIB_AES128_N_K; i < RADIOLIB_AES128_N_B * (RADIOLIB_AES128_N_R + 1); ++i) {
     287         160 :     uint8_t j = (i - 1) * 4;
     288         800 :     for(uint8_t k = 0; k < 4; k++) {
     289         640 :       tmp[k] = roundKey[j + k];
     290             :     }
     291             : 
     292         160 :     if(i % RADIOLIB_AES128_N_K == 0) {
     293          40 :       this->rotWord(tmp);
     294          40 :       this->subWord(tmp);
     295          40 :       tmp[0] = tmp[0] ^ aesRcon[i/RADIOLIB_AES128_N_K];
     296             :     }
     297             : 
     298         160 :     j = i * 4;
     299         160 :     uint8_t k = (i - RADIOLIB_AES128_N_K) * 4;
     300         800 :     for(uint8_t l = 0; l < 4; l++) {
     301         640 :       roundKey[j + l] = roundKey[k + l] ^ tmp[l];
     302             :     }
     303             :   }
     304           4 : }
     305             : 
     306          13 : void RadioLibSoftwareAES128::cipher(state_t* state, uint8_t* roundKey) {
     307          13 :   this->addRoundKey(0, state, roundKey);
     308         130 :   for(uint8_t round = 1; round < RADIOLIB_AES128_N_R; round++) {
     309         117 :     this->subBytes(state, aesSbox);
     310         117 :     this->shiftRows(state, false);
     311         117 :     this->mixColumns(state, false);
     312         117 :     this->addRoundKey(round, state, roundKey);
     313             :   }
     314             : 
     315          13 :   this->subBytes(state, aesSbox);
     316          13 :   this->shiftRows(state, false);
     317          13 :   this->addRoundKey(RADIOLIB_AES128_N_R, state, roundKey);
     318          13 : }
     319             : 
     320             : 
     321           0 : void RadioLibSoftwareAES128::decipher(state_t* state, uint8_t* roundKey) {
     322           0 :   this->addRoundKey(RADIOLIB_AES128_N_R, state, roundKey);
     323           0 :   for(uint8_t round = RADIOLIB_AES128_N_R - 1; round > 0; --round) {
     324           0 :     this->shiftRows(state, true);
     325           0 :     this->subBytes(state, aesSboxInv);
     326           0 :     this->addRoundKey(round, state, roundKey);
     327           0 :     this->mixColumns(state, true);
     328             :   }
     329             : 
     330           0 :   this->shiftRows(state, true);
     331           0 :   this->subBytes(state, aesSboxInv);
     332           0 :   this->addRoundKey(0, state, roundKey);
     333           0 : }
     334             : 
     335          40 : void RadioLibSoftwareAES128::subWord(uint8_t* word) {
     336         200 :   for(size_t i = 0; i < 4; i++) {
     337         160 :     uint8_t* ptr = const_cast<uint8_t*>(&aesSbox[word[i]]);
     338         160 :     word[i] = RADIOLIB_NONVOLATILE_READ_BYTE(ptr);
     339             :   }
     340          40 : }
     341             : 
     342          40 : void RadioLibSoftwareAES128::rotWord(uint8_t* word) {
     343             :   uint8_t tmp[4];
     344          40 :   memcpy(tmp, word, 4);
     345         200 :   for(size_t i = 0; i < 4; i++) {
     346         160 :     word[i] = tmp[(i + 1) % 4];
     347             :   }
     348          40 : }
     349             : 
     350         130 : void RadioLibSoftwareAES128::subBytes(state_t* state, const uint8_t* box) {
     351         650 :   for(size_t row = 0; row < 4; row++) {
     352        2600 :     for(size_t col = 0; col < 4; col++) {
     353        2080 :       uint8_t* ptr = const_cast<uint8_t*>(&box[(*state)[col][row]]);
     354        2080 :       (*state)[col][row] = RADIOLIB_NONVOLATILE_READ_BYTE(ptr);
     355             :     }
     356             :   }
     357         130 : }
     358             : 
     359         130 : void RadioLibSoftwareAES128::shiftRows(state_t* state, bool inv) {
     360             :   uint8_t tmp[4];
     361         520 :   for(size_t row = 1; row < 4; row++) {
     362        1950 :     for(size_t col = 0; col < 4; col++) {
     363        1560 :       if(!inv) {
     364        1560 :         tmp[col] = (*state)[(row + col) % 4][row];
     365             :       } else {
     366           0 :         tmp[(row + col) % 4] = (*state)[col][row];
     367             :       }
     368             :     }
     369        1950 :     for(size_t col = 0; col < 4; col++) {
     370        1560 :       (*state)[col][row] = tmp[col];
     371             :     }
     372             :   }
     373         130 : }
     374             : 
     375         117 : void RadioLibSoftwareAES128::mixColumns(state_t* state, bool inv) {
     376             :   uint8_t tmp[4];
     377         117 :   uint8_t matmul[][4] = {
     378             :     { 0x02, 0x03, 0x01, 0x01 },
     379             :     { 0x01, 0x02, 0x03, 0x01 },
     380             :     { 0x01, 0x01, 0x02, 0x03 },
     381             :     { 0x03, 0x01, 0x01, 0x02 }
     382             :   };
     383         117 :   if(inv) {
     384           0 :     uint8_t matmul_inv[][4] = {
     385             :       { 0x0e, 0x0b, 0x0d, 0x09 },
     386             :       { 0x09, 0x0e, 0x0b, 0x0d },
     387             :       { 0x0d, 0x09, 0x0e, 0x0b },
     388             :       { 0x0b, 0x0d, 0x09, 0x0e }
     389             :     };
     390           0 :     memcpy(matmul, matmul_inv, sizeof(matmul_inv));
     391             :   }
     392             : 
     393         585 :   for(size_t col = 0; col < 4; col++) {
     394        2340 :     for(size_t row = 0; row < 4; row++) {
     395        1872 :       tmp[row] = (*state)[col][row];
     396             :     }
     397        2340 :     for(size_t i = 0; i < 4; i++) {
     398        1872 :       (*state)[col][i] = 0x00;
     399        9360 :       for(size_t j = 0; j < 4; j++) {
     400        7488 :         (*state)[col][i] ^= mul(matmul[i][j], tmp[j]);
     401             :       }
     402             :     }
     403             :   }
     404         117 : }
     405             : 
     406        7488 : uint8_t RadioLibSoftwareAES128::mul(uint8_t a, uint8_t b) {
     407             :   uint8_t sb[4];
     408        7488 :   uint8_t out = 0;
     409        7488 :   sb[0] = b;
     410       29952 :   for(size_t i = 1; i < 4; i++) {
     411       22464 :     sb[i] = sb[i - 1] << 1;
     412       22464 :     if (sb[i - 1] & 0x80) {
     413       11032 :       sb[i] ^= 0x1b;
     414             :     }
     415             :   }
     416       37440 :   for(size_t i = 0; i < 4; i++) {
     417       29952 :     if(a >> i & 0x01) {
     418        9360 :       out ^= sb[i];
     419             :     }
     420             :   }
     421        7488 :   return(out);
     422             : }
     423             : 
     424         143 : void RadioLibSoftwareAES128::addRoundKey(uint8_t round, state_t* state, const uint8_t* roundKey) {
     425         715 :   for(size_t row = 0; row < 4; row++) {
     426        2860 :     for(size_t col = 0; col < 4; col++) {
     427        2288 :       (*state)[row][col] ^= roundKey[(round * RADIOLIB_AES128_N_B * 4) + (row * RADIOLIB_AES128_N_B) + col];
     428             :     }
     429             :   }
     430         143 : }
     431             : 
     432             : #endif

Generated by: LCOV version 1.14