static AJ_Status EncryptMessage(AJ_Message* msg) { AJ_IOBuffer* ioBuf = &msg->bus->sock.tx; AJ_Status status; uint8_t key[16]; uint8_t nonce[5]; uint8_t role = AJ_ROLE_KEY_UNDEFINED; uint32_t mlen = MessageLen(msg); uint32_t hlen = mlen - msg->hdr->bodyLen; /* * Check there is room to append the MAC */ if (AJ_IO_BUF_SPACE(ioBuf) < MAC_LENGTH) { return AJ_ERR_RESOURCES; } msg->hdr->bodyLen += MAC_LENGTH; ioBuf->writePtr += MAC_LENGTH; /* * Use the group key for multicast and broadcast signals the session key otherwise. */ if ((msg->hdr->msgType == AJ_MSG_SIGNAL) && !msg->destination) { status = AJ_GetGroupKey(NULL, key); } else { status = AJ_GetSessionKey(msg->destination, key, &role); } if (status != AJ_OK) { AJ_ErrPrintf(("Encryption required but peer %s is not authenticated", msg->destination)); status = AJ_ERR_SECURITY; } else { InitNonce(msg, role, nonce); status = AJ_Encrypt_CCM(key, ioBuf->bufStart, mlen, hlen, MAC_LENGTH, nonce, sizeof(nonce)); } return status; }
AJ_Status AJ_PeerHandleGenSessionKeyReply(AJ_Message* msg) { AJ_Status status; /* * For 12 bytes of verifier, we need at least 12 * 2 characters * to store its representation in hex (24 octets + 1 octet for \0). * However, the KeyGen function demands a bigger buffer * (to store 16 bytes key in addition to the 12 bytes verifier). * Hence we allocate, the maximum of (12 * 2 + 1) and (16 + 12). */ char verifier[VERIFIER_LEN + AES_KEY_LEN]; char* nonce; char* remVerifier; /* * Check we are in an auth conversation with the sender */ status = CheckAuthPeer(msg); if (status != AJ_OK) { return status; } if (msg->hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_SECURITY; } else { AJ_UnmarshalArgs(msg, "ss", &nonce, &remVerifier); status = KeyGen(msg->sender, AJ_ROLE_KEY_INITIATOR, authContext.nonce, nonce, (uint8_t*)verifier, sizeof(verifier)); if (status == AJ_OK) { /* * Check verifier strings match as expected */ if (strcmp(remVerifier, verifier) != 0) { status = AJ_ERR_SECURITY; } } if (status == AJ_OK) { AJ_Arg key; AJ_Message call; uint8_t groupKey[AES_KEY_LEN]; /* * Group keys are exchanged via an encrypted message */ AJ_MarshalMethodCall(msg->bus, &call, AJ_METHOD_EXCHANGE_GROUP_KEYS, msg->sender, 0, AJ_FLAG_ENCRYPTED, CALL_TIMEOUT); AJ_GetGroupKey(NULL, groupKey); AJ_MarshalArg(&call, AJ_InitArg(&key, AJ_ARG_BYTE, AJ_ARRAY_FLAG, groupKey, sizeof(groupKey))); status = AJ_DeliverMsg(&call); } } if (status != AJ_OK) { PeerAuthComplete(status); } return AJ_OK; }
AJ_Status AJ_PeerHandleExchangeGroupKeys(AJ_Message* msg, AJ_Message* reply) { AJ_Status status; AJ_Arg key; AJ_UnmarshalArg(msg, &key); /* * We expect the key to be 16 bytes */ if (key.len != AES_KEY_LEN) { status = AJ_ERR_INVALID; } else { status = AJ_SetGroupKey(msg->sender, key.val.v_byte); } if (status == AJ_OK) { uint8_t groupKey[AES_KEY_LEN]; AJ_MarshalReplyMsg(msg, reply); AJ_GetGroupKey(NULL, groupKey); status = AJ_MarshalArg(reply, AJ_InitArg(&key, AJ_ARG_BYTE, AJ_ARRAY_FLAG, groupKey, sizeof(groupKey))); } else { status = AJ_MarshalErrorMsg(msg, reply, AJ_ErrRejected); } return status; }
static AJ_Status DecryptMessage(AJ_Message* msg) { AJ_IOBuffer* ioBuf = &msg->bus->sock.rx; AJ_Status status; uint8_t key[16]; uint8_t nonce[5]; uint8_t role = AJ_ROLE_KEY_UNDEFINED; uint32_t mlen = MessageLen(msg); uint32_t hLen = mlen - msg->hdr->bodyLen; /* * TODO - handle case where msg endianess is different than the host endianess */ if (msg->hdr->endianess != HOST_ENDIANESS) { return AJ_ERR_SECURITY; } /* * Use the group key for multicast and broadcast signals the session key otherwise. */ if ((msg->hdr->msgType == AJ_MSG_SIGNAL) && !msg->destination) { status = AJ_GetGroupKey(msg->sender, key); } else { status = AJ_GetSessionKey(msg->sender, key, &role); /* * We use the oppsite role when decrypting. */ role ^= 3; } if (status != AJ_OK) { status = AJ_ERR_SECURITY; } else { InitNonce(msg, role, nonce); status = AJ_Decrypt_CCM(key, ioBuf->bufStart, mlen - MAC_LENGTH, hLen, MAC_LENGTH, nonce, sizeof(nonce)); } return status; }