Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}