uint8_t aes_decr(const void* in, void* out, uint32_t length, uint8_t mac_len) { /* verify parameters */ if(mac_len>AES_BLOCK_SIZE) return 1; if(length<=mac_len) return 2; /* calculate payload length */ length -= mac_len; /* re-create IV from end of packet */ memcpy(&g_encrypt.in, ((uint8_t*)in) + length, mac_len); /* pad IV with 0xFF if needed to generate IV block */ if(mac_len<AES_BLOCK_SIZE) memset(&g_encrypt.in[mac_len], 0xFF, AES_BLOCK_SIZE-mac_len); /* decrypt data */ aes_process((uint8_t*)in, (uint8_t*)out, length); /* verify signature */ if(memcmp(aes_sign(out, length), ((uint8_t*)in) + length, mac_len)==0) { /* reset signature in output */ memset(((uint8_t*)out) + length, 0xFF, mac_len); return 0; } else { /* erase broken payload */ memset(out, 0, length); return 3; } }
s8t processIncomingMsg_USM(u8t* const input, const u16t input_len, u16t* pos, message_v3_t* request) { /* If the value of the msgAuthoritativeEngineID field in the securityParameters is unknown, return usmStatsUnknownEngineIDs */ TRY(decode_USM_parameters(input, input_len, pos, request)); if (request->msgAuthoritativeEngineID.len != getEngineID()->len || memcmp(request->msgAuthoritativeEngineID.ptr, getEngineID()->ptr, getEngineID()->len)) { TRY(report(request, &usmStatsUnknownEngineIDs, &usmStatsUnknownEngineIDCounter)); return ERR_USM; } /* check user name */ if (request->msgUserName.len != strlen((char*)getUserName()) || memcmp(request->msgUserName.ptr, getUserName(), request->msgUserName.len) != 0) { TRY(report(request, &usmStatsUnknownUserNames, &usmStatsUnknownUserNamesCounter)); return ERR_USM; } if (request->msgFlags & FLAG_AUTH) { #if ENABLE_AUTH /* The timeliness check is only performed if authentication is applied to the message */ if (request->msgAuthenticationParameters.len != 12 || isBadHMAC(input, input_len, request) != ERR_NO_ERROR) { TRY(report(request, &usmStatsWrongDigests, &usmStatsWrongDigestsCounter)); return ERR_USM; } #else return FAILURE; #endif } if (request->msgAuthoritativeEngineBoots != getMsgAuthoritativeEngineBoots() || abs(request->msgAuthoritativeEngineTime - getSysUpTime()) < TIME_WINDOW) { TRY(report(request, &usmStatsNotInTimeWindows, &usmStatsNotInTimeWindowsCounter)); return ERR_USM; } if (request->msgFlags & FLAG_PRIV) { #if ENABLE_PRIVACY if (request->msgPrivacyParameters.len != 8) { TRY(report(request, &usmStatsDecryptionErrors, &usmStatsDecryptionErrorsCounter)); return ERR_USM; } /* init IV */ u8t iv[16]; convert_2_octets(iv, request->msgAuthoritativeEngineBoots); convert_2_octets(iv + 4, request->msgAuthoritativeEngineTime); memcpy(iv + 8, request->msgPrivacyParameters.ptr, 8); /* decode the Scoped PDU */ aes_process(getPrivKul(), iv, input + *pos, input + *pos, input_len - *pos, AES_DECRYPT); #else return FAILURE; #endif } return 0; }
// One-time setup on factory install void memory_setup(void) { if (memory_read_setup()) { memory_erase(); #ifndef TESTING // Lock Config Memory: OP MODE PARAMETER1 PARAMETER2 const uint8_t ataes_cmd[] = {0x0D, 0x02, 0x00, 0x00, 0x00, 0x00}; // Return packet [Count(1) || Return Code (1) || CRC (2)] uint8_t ataes_ret[4] = {0}; aes_process(ataes_cmd, sizeof(ataes_cmd), ataes_ret, 4); #endif memory_write_setup(0x00); } else { memory_mempass(); } }
uint8_t aes_encr(const void* in, void* out, uint32_t length, uint8_t mac_len) { /* verify parameters */ if(mac_len>AES_BLOCK_SIZE) return 1; if(length<=mac_len) return 2; /* calculate payload length */ length -= mac_len; /* sign payload to create IV */ memcpy(&g_encrypt.in, aes_sign(in, length), mac_len); /* pad IV with 0xFF if needed to generate IV block */ if(mac_len<AES_BLOCK_SIZE) memset(&g_encrypt.in[mac_len], 0xFF, AES_BLOCK_SIZE-mac_len); /* copy IV to payload end */ memcpy((uint8_t*)out + length, &g_encrypt.in, mac_len); /* encrypt data */ aes_process((uint8_t*)in, (uint8_t*)out, length); return 0; }
static s8t encode_USM_parameters(message_v3_t* message, u8t* output, u16t buf_len, s16t* pos) { if (message->msgFlags & FLAG_PRIV) { #if ENABLE_PRIVACY u8t iv[16]; /* IV */ convert_2_octets(iv, message->msgAuthoritativeEngineBoots); convert_2_octets(iv + 4, message->msgAuthoritativeEngineTime); /* privace parameters */ convert_2_octets(message->msgPrivacyParameters.ptr, getLPrivacyParameters()); convert_2_octets(message->msgPrivacyParameters.ptr, getHPrivacyParameters()); memcpy(iv + 8, message->msgPrivacyParameters.ptr, 8); aes_process(getPrivKul(), iv, output + *pos, output + *pos, buf_len - *pos, AES_ENCRYPT); TRY(ber_encode_type_length(output, pos, BER_TYPE_OCTET_STRING, buf_len - *pos)); #else return FAILURE; #endif } s16t tmpPos = *pos; TRY(ber_encode_fixed_string(output, pos, message->msgPrivacyParameters.ptr, message->msgPrivacyParameters.len)); TRY(ber_encode_fixed_string(output, pos, message->msgAuthenticationParameters.ptr, message->msgAuthenticationParameters.len)); message->msgAuthenticationParameters.ptr = &output[*pos + 2]; TRY(ber_encode_fixed_string(output, pos, message->msgUserName.ptr, message->msgUserName.len)); TRY(ber_encode_integer(output, pos, BER_TYPE_INTEGER, message->msgAuthoritativeEngineTime)); TRY(ber_encode_integer(output, pos, BER_TYPE_INTEGER, message->msgAuthoritativeEngineBoots)); TRY(ber_encode_fixed_string(output, pos, message->msgAuthoritativeEngineID.ptr, message->msgAuthoritativeEngineID.len)); TRY(ber_encode_type_length(output, pos, BER_TYPE_SEQUENCE, tmpPos - *pos)); TRY(ber_encode_type_length(output, pos, BER_TYPE_OCTET_STRING, tmpPos - *pos)); return 0; }
s8t processIncomingMsg_USM(u8t* const input, const u16t input_len, u16t* pos, message_v3_t* request) { /* If the value of the msgAuthoritativeEngineID field in the securityParameters is unknown, return usmStatsUnknownEngineIDs */ TRY(decode_USM_parameters(input, input_len, pos, request)); if (request->msgAuthoritativeEngineID.len != getEngineID()->len || memcmp(request->msgAuthoritativeEngineID.ptr, getEngineID()->ptr, getEngineID()->len)) { TRY(report(request, &usmStatsUnknownEngineIDs, &usmStatsUnknownEngineIDCounter)); #if PDEBUG printf("USM Modul: Error! Wrong Engine ID!\n"); #endif return ERR_USM; } /* check user name */ if (request->msgUserName.len != strlen((char*)getUserName()) || memcmp(request->msgUserName.ptr, getUserName(), request->msgUserName.len) != 0) { TRY(report(request, &usmStatsUnknownUserNames, &usmStatsUnknownUserNamesCounter)); #if PDEBUG printf("USM Modul: Error! Wrong Username\n"); #endif return ERR_USM; } /*sz*/ #if ENABLE_AUTH if (!(request->msgFlags & FLAG_AUTH)) { #if PDEBUG printf("USM Modul: Error! User needs Authentication\n"); #endif TRY(report(request, &usmStatsUnsupportedSecurityLevel, &usmStatsUnsupportedSecurityLevelCounter)); return ERR_USM; } #endif /*sz*/ if (request->msgFlags & FLAG_AUTH) { #if ENABLE_AUTH /* The timeliness check is only performed if authentication is applied to the message */ if (request->msgAuthenticationParameters.len != 12 || isBadHMAC(input, input_len, request) != ERR_NO_ERROR) { #ifndef DISABLE_HMAC TRY(report(request, &usmStatsWrongDigests, &usmStatsWrongDigestsCounter)); #if PDEBUG printf("USM Modul: Error! Authentication Failed!\n"); #endif return ERR_USM; #endif /* Disable HMAC */ } #else return FAILURE; #endif } #if ENABLE_AUTH /*sz*/ #if PDEBUG printf("Checking Engine Time getsysuptime()/100: %d\n",(getSysUpTime()/100)); printf("Request EngineTime:%d\n", request->msgAuthoritativeEngineTime); printf("RequestTime - getSysUpTime/100: %d \n", (request->msgAuthoritativeEngineTime - (getSysUpTime()/100))); printf("abs of RequestTime - getSysUpTime/100: %d \n",(abs(request->msgAuthoritativeEngineTime - (getSysUpTime()/100)))); printf("Checking if it is in the time window (1 if it is not!!!) %d\n", (abs(request->msgAuthoritativeEngineTime - (getSysUpTime()/100)) > TIME_WINDOW)); if (request->msgAuthoritativeEngineBoots == 0){ printf("USM Modul: request->msgAuthoritativeEngineBoots == 0\n"); } if (request->msgAuthoritativeEngineBoots != getMsgAuthoritativeEngineBoots()){ printf("USM Modul: request->msgAuthoritativeEngineBoots != getMsgAuthoritativeEngineBoots()\n"); } if (abs(request->msgAuthoritativeEngineTime - getSysUpTime()) < TIME_WINDOW){ printf("USM Modul: abs(request->msgAuthoritativeEngineTime - getSysUpTime()) < TIME_WINDOW\n"); } if (getMsgAuthoritativeEngineBoots()>=2147483647){ printf("USM Modul: getMsgAuthoritativeEngineBoots()>=2147483647\n"); } #endif #if DISABLE_MAET == 0 if (request->msgAuthoritativeEngineBoots != getMsgAuthoritativeEngineBoots() || abs(request->msgAuthoritativeEngineTime - (getSysUpTime()/100)) > TIME_WINDOW || getMsgAuthoritativeEngineBoots()>=2147483647){ #endif #if DISABLE_MAET == 1 if (request->msgAuthoritativeEngineBoots != getMsgAuthoritativeEngineBoots() || getMsgAuthoritativeEngineBoots()>=2147483647){ #endif /*sz*/ /* Changed not working abs(request->msgAuthoritativeEngineTime - getSysUpTime()) < TIME_WINDOW)*/ /* to line above. /* added line getMsgAuthoritativeEngineBoots()>=2147483647 in if above */ /* to stop the SNMP Agent when the maximum snmpEngineBoots is reached*/ /* and send an Not in Time Window Message back.*/ /*sz*/ TRY(report(request, &usmStatsNotInTimeWindows, &usmStatsNotInTimeWindowsCounter)); return ERR_USM; } /*sz*/ #endif /*#if ENABLE_AUTH*/ /*sz*/ #if ENABLE_PRIVACY if (!(request->msgFlags & FLAG_PRIV)) { #if PDEBUG printf("USM Modul: Error! User needs Privacy\n"); #endif TRY(report(request, &usmStatsUnsupportedSecurityLevel, &usmStatsUnsupportedSecurityLevelCounter)); return ERR_USM; } #endif /*sz*/ if (request->msgFlags & FLAG_PRIV) { #if ENABLE_PRIVACY if (request->msgPrivacyParameters.len != 8) { TRY(report(request, &usmStatsDecryptionErrors, &usmStatsDecryptionErrorsCounter)); return ERR_USM; } /* init IV */ u8t iv[16]; convert_2_octets(iv, request->msgAuthoritativeEngineBoots); convert_2_octets(iv + 4, request->msgAuthoritativeEngineTime); memcpy(iv + 8, request->msgPrivacyParameters.ptr, 8); /* decode the Scoped PDU */ aes_process(getPrivKul(), iv, input + *pos, input + *pos, input_len - *pos, AES_DECRYPT); #else return FAILURE; #endif } return 0; } static s8t encode_USM_parameters(message_v3_t* message, u8t* output, u16t buf_len, s16t* pos) { if (message->msgFlags & FLAG_PRIV) { #if ENABLE_PRIVACY u8t iv[16]; /* IV */ convert_2_octets(iv, message->msgAuthoritativeEngineBoots); convert_2_octets(iv + 4, message->msgAuthoritativeEngineTime); /* privace parameters */ convert_2_octets(message->msgPrivacyParameters.ptr, getLPrivacyParameters()); convert_2_octets(message->msgPrivacyParameters.ptr, getHPrivacyParameters()); memcpy(iv + 8, message->msgPrivacyParameters.ptr, 8); aes_process(getPrivKul(), iv, output + *pos, output + *pos, buf_len - *pos, AES_ENCRYPT); TRY(ber_encode_type_length(output, pos, BER_TYPE_OCTET_STRING, buf_len - *pos)); #else return FAILURE; #endif } s16t tmpPos = *pos; TRY(ber_encode_fixed_string(output, pos, message->msgPrivacyParameters.ptr, message->msgPrivacyParameters.len)); TRY(ber_encode_fixed_string(output, pos, message->msgAuthenticationParameters.ptr, message->msgAuthenticationParameters.len)); message->msgAuthenticationParameters.ptr = &output[*pos + 2]; TRY(ber_encode_fixed_string(output, pos, message->msgUserName.ptr, message->msgUserName.len)); TRY(ber_encode_integer(output, pos, BER_TYPE_INTEGER, message->msgAuthoritativeEngineTime)); TRY(ber_encode_integer(output, pos, BER_TYPE_INTEGER, message->msgAuthoritativeEngineBoots)); TRY(ber_encode_fixed_string(output, pos, message->msgAuthoritativeEngineID.ptr, message->msgAuthoritativeEngineID.len)); TRY(ber_encode_type_length(output, pos, BER_TYPE_SEQUENCE, tmpPos - *pos)); TRY(ber_encode_type_length(output, pos, BER_TYPE_OCTET_STRING, tmpPos - *pos)); return 0; } s8t prepareOutgoingMsg_USM(message_v3_t* message, u8t* output, u16t output_len, s16t* pos) { memcpy(&message->msgAuthoritativeEngineID, getEngineID(), sizeof(ptr_t)); message->msgAuthoritativeEngineBoots = getMsgAuthoritativeEngineBoots(); message->msgAuthoritativeEngineTime = getSysUpTime()/100; encode_USM_parameters(message, output, output_len, pos); return 0; }