示例#1
0
ThreadError Mac::ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeighbor)
{
    ThreadError error = kThreadError_None;
    uint8_t securityLevel;
    uint32_t frameCounter;
    uint8_t nonce[kNonceSize];
    uint8_t tag[Frame::kMaxMicSize];
    uint8_t tagLength;
    uint8_t keyid;
    uint32_t keySequence;
    const uint8_t *macKey;
    Crypto::AesCcm aesCcm;

    mReceiveFrame.SetSecurityValid(false);

    if (mReceiveFrame.GetSecurityEnabled() == false)
    {
        ExitNow();
    }

    VerifyOrExit(aNeighbor != NULL, error = kThreadError_Security);

    mReceiveFrame.GetSecurityLevel(securityLevel);
    mReceiveFrame.GetFrameCounter(frameCounter);

    GenerateNonce(aSrcAddr.mExtAddress, frameCounter, securityLevel, nonce);

    tagLength = mReceiveFrame.GetFooterLength() - Frame::kFcsSize;

    mReceiveFrame.GetKeyId(keyid);
    keyid--;

    if (keyid == (mKeyManager.GetCurrentKeySequence() & 0x7f))
    {
        // same key index
        keySequence = mKeyManager.GetCurrentKeySequence();
        macKey = mKeyManager.GetCurrentMacKey();
        VerifyOrExit(aNeighbor->mPreviousKey == true || frameCounter >= aNeighbor->mValid.mLinkFrameCounter,
                     error = kThreadError_Security);
    }
    else if (aNeighbor->mPreviousKey &&
             mKeyManager.IsPreviousKeyValid() &&
             keyid == (mKeyManager.GetPreviousKeySequence() & 0x7f))
    {
        // previous key index
        keySequence = mKeyManager.GetPreviousKeySequence();
        macKey = mKeyManager.GetPreviousMacKey();
        VerifyOrExit(frameCounter >= aNeighbor->mValid.mLinkFrameCounter, error = kThreadError_Security);
    }
    else if (keyid == ((mKeyManager.GetCurrentKeySequence() + 1) & 0x7f))
    {
        // next key index
        keySequence = mKeyManager.GetCurrentKeySequence() + 1;
        macKey = mKeyManager.GetTemporaryMacKey(keySequence);
    }
    else
    {
        for (Receiver *receiver = mReceiveHead; receiver; receiver = receiver->mNext)
        {
            receiver->HandleReceivedFrame(mReceiveFrame, kThreadError_Security);
        }

        ExitNow(error = kThreadError_Security);
    }

    aesCcm.SetKey(macKey, 16);
    aesCcm.Init(mReceiveFrame.GetHeaderLength(), mReceiveFrame.GetPayloadLength(),
                tagLength, nonce, sizeof(nonce));
    aesCcm.Header(mReceiveFrame.GetHeader(), mReceiveFrame.GetHeaderLength());
    aesCcm.Payload(mReceiveFrame.GetPayload(), mReceiveFrame.GetPayload(), mReceiveFrame.GetPayloadLength(),
                   false);
    aesCcm.Finalize(tag, &tagLength);

    VerifyOrExit(memcmp(tag, mReceiveFrame.GetFooter(), tagLength) == 0, error = kThreadError_Security);

    if (keySequence > mKeyManager.GetCurrentKeySequence())
    {
        mKeyManager.SetCurrentKeySequence(keySequence);
    }

    if (keySequence == mKeyManager.GetCurrentKeySequence())
    {
        aNeighbor->mPreviousKey = false;
    }

    aNeighbor->mValid.mLinkFrameCounter = frameCounter + 1;

    mReceiveFrame.SetSecurityValid(true);

exit:
    return error;
}