blob: 672ba04e8fd38c5737f095d871d84f369d8a27ab [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements unit tests for the CryptoContext implementation.
*/
#include <errno.h>
#include <stdarg.h>
#include <gtest/gtest.h>
#include <crypto/DefaultSessionKeystore.h>
#include <lib/core/CHIPCore.h>
#include <lib/support/CodeUtils.h>
#include <transport/CryptoContext.h>
using namespace chip;
using namespace Crypto;
TEST(TestSecureSession, SecureChannelInitTest)
{
Crypto::DefaultSessionKeystore sessionKeystore;
CryptoContext channel;
P256Keypair keypair;
EXPECT_EQ(keypair.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR);
P256Keypair keypair2;
EXPECT_EQ(keypair2.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR);
// Test the channel is successfully created with valid parameters
EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan(),
CryptoContext::SessionInfoType::kSessionEstablishment,
CryptoContext::SessionRole::kInitiator),
CHIP_NO_ERROR);
// Test the channel cannot be reinitialized
EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan(),
CryptoContext::SessionInfoType::kSessionEstablishment,
CryptoContext::SessionRole::kInitiator),
CHIP_ERROR_INCORRECT_STATE);
// Test the channel can be initialized with valid salt
const char * salt = "Test Salt";
CryptoContext channel2;
EXPECT_EQ(channel2.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)),
CryptoContext::SessionInfoType::kSessionEstablishment,
CryptoContext::SessionRole::kInitiator),
CHIP_NO_ERROR);
}
TEST(TestSecureSession, SecureChannelEncryptTest)
{
Crypto::DefaultSessionKeystore sessionKeystore;
CryptoContext channel;
const uint8_t plain_text[] = { 0x86, 0x74, 0x64, 0xe5, 0x0b, 0xd4, 0x0d, 0x90, 0xe1, 0x17, 0xa3, 0x2d, 0x4b, 0xd4, 0xe1, 0xe6 };
uint8_t output[128];
PacketHeader packetHeader;
MessageAuthenticationCode mac;
packetHeader.SetSessionId(1);
EXPECT_TRUE(packetHeader.IsEncrypted());
EXPECT_EQ(packetHeader.MICTagLength(), 16);
CryptoContext::NonceStorage nonce;
CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), 0);
P256Keypair keypair;
EXPECT_EQ(keypair.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR);
P256Keypair keypair2;
EXPECT_EQ(keypair2.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR);
// Test uninitialized channel
EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac),
CHIP_ERROR_INVALID_USE_OF_SESSION_KEY);
const char * salt = "Test Salt";
EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)),
CryptoContext::SessionInfoType::kSessionEstablishment,
CryptoContext::SessionRole::kInitiator),
CHIP_NO_ERROR);
// Test initialized channel, but invalid arguments
EXPECT_EQ(channel.Encrypt(nullptr, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT);
EXPECT_EQ(channel.Encrypt(plain_text, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT);
EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT);
// Valid arguments
EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac), CHIP_NO_ERROR);
}
TEST(TestSecureSession, SecureChannelDecryptTest)
{
Crypto::DefaultSessionKeystore sessionKeystore;
CryptoContext channel;
const uint8_t plain_text[] = { 0x86, 0x74, 0x64, 0xe5, 0x0b, 0xd4, 0x0d, 0x90, 0xe1, 0x17, 0xa3, 0x2d, 0x4b, 0xd4, 0xe1, 0xe6 };
uint8_t encrypted[128];
PacketHeader packetHeader;
MessageAuthenticationCode mac;
packetHeader.SetSessionId(1);
EXPECT_TRUE(packetHeader.IsEncrypted());
EXPECT_EQ(packetHeader.MICTagLength(), 16);
CryptoContext::NonceStorage nonce;
CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), 0);
const char * salt = "Test Salt";
P256Keypair keypair;
EXPECT_EQ(keypair.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR);
P256Keypair keypair2;
EXPECT_EQ(keypair2.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR);
EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)),
CryptoContext::SessionInfoType::kSessionEstablishment,
CryptoContext::SessionRole::kInitiator),
CHIP_NO_ERROR);
EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), encrypted, nonce, packetHeader, mac), CHIP_NO_ERROR);
CryptoContext channel2;
uint8_t output[128];
// Uninitialized channel
EXPECT_EQ(channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac),
CHIP_ERROR_INVALID_USE_OF_SESSION_KEY);
EXPECT_EQ(channel2.InitFromKeyPair(sessionKeystore, keypair2, keypair.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)),
CryptoContext::SessionInfoType::kSessionEstablishment,
CryptoContext::SessionRole::kResponder),
CHIP_NO_ERROR);
// Channel initialized, but invalid arguments to decrypt
EXPECT_EQ(channel2.Decrypt(nullptr, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT);
EXPECT_EQ(channel2.Decrypt(encrypted, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT);
EXPECT_EQ(channel2.Decrypt(encrypted, sizeof(encrypted), nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT);
// Valid arguments
EXPECT_EQ(channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac), CHIP_NO_ERROR);
EXPECT_EQ(memcmp(plain_text, output, sizeof(plain_text)), 0);
}