blob: a0e138e7c50185d8f78ca90312577f1535d9d266 [file] [log] [blame]
/*
*
* Copyright (c) 2017 Nest Labs, Inc.
* 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
* Supporting code for testing Weave key export.
*
*/
#include <Weave/Core/WeaveCore.h>
#include <Weave/Support/NestCerts.h>
#include <Weave/Profiles/security/WeaveAccessToken.h>
#include <Weave/Profiles/security/WeaveDummyGroupKeyStore.h>
#include "WeaveKeyExportClient.h"
// This code is only available in contexts that support malloc and system time.
#if HAVE_MALLOC && HAVE_FREE && HAVE_TIME_H
#include <time.h>
#include <stdlib.h>
namespace nl {
namespace Weave {
namespace Profiles {
namespace Security {
namespace KeyExport {
class SimulatedDeviceGroupKeyStore : public nl::Weave::Profiles::Security::AppKeys::DummyGroupKeyStore
{
public:
virtual WEAVE_ERROR RetrieveGroupKey(uint32_t keyId, WeaveGroupKey& key)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
// Only support the fabric secret.
VerifyOrExit(keyId == WeaveKeyId::kFabricSecret, err = WEAVE_ERROR_INVALID_KEY_ID);
// Return a fixed key value.
memset(&key, 0, sizeof(key));
key.KeyId = keyId;
key.KeyLen = nl::Weave::Profiles::Security::AppKeys::kWeaveFabricSecretSize;
for (uint8_t i = 0; i < key.KeyLen; i++)
key.Key[i] = i;
exit:
return err;
}
};
class SimulatedDeviceKeyExportDelegate : public WeaveKeyExportDelegate
{
public:
SimulatedDeviceKeyExportDelegate(const uint8_t *deviceCert, uint16_t deviceCertLen,
const uint8_t *devicePrivKey, uint16_t devicePrivKeyLen,
const uint8_t *rootCert, uint16_t rootCertLen)
{
mDeviceCert = deviceCert;
mDeviceCertLen = deviceCertLen;
mDevicePrivKey = devicePrivKey;
mDevicePrivKeyLen = devicePrivKeyLen;
mRootCert = rootCert;
mRootCertLen = rootCertLen;
}
virtual WEAVE_ERROR GetNodeCertSet(bool isInitiator, WeaveCertificateSet& certSet)
{
WEAVE_ERROR err;
WeaveCertificateData *cert;
VerifyOrExit(!isInitiator, err = WEAVE_ERROR_INVALID_ARGUMENT);
err = certSet.Init(10, 4096);
SuccessOrExit(err);
err = certSet.LoadCert(mDeviceCert, mDeviceCertLen, 0, cert);
SuccessOrExit(err);
exit:
if (err != WEAVE_NO_ERROR)
{
certSet.Release();
}
return err;
}
virtual WEAVE_ERROR ReleaseNodeCertSet(bool isInitiator, WeaveCertificateSet& certSet)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
VerifyOrExit(!isInitiator, err = WEAVE_ERROR_INVALID_ARGUMENT);
certSet.Release();
exit:
return err;
}
virtual WEAVE_ERROR GetNodePrivateKey(bool isInitiator, const uint8_t *& weavePrivKey, uint16_t& weavePrivKeyLen)
{
weavePrivKey = mDevicePrivKey;
weavePrivKeyLen = mDevicePrivKeyLen;
return WEAVE_NO_ERROR;
}
virtual WEAVE_ERROR ReleaseNodePrivateKey(bool isInitiator, const uint8_t *& weavePrivKey)
{
return WEAVE_NO_ERROR;
}
virtual WEAVE_ERROR BeginCertValidation(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext)
{
WEAVE_ERROR err;
WeaveCertificateData *cert;
VerifyOrExit(!isInitiator, err = WEAVE_ERROR_INVALID_ARGUMENT);
err = certSet.Init(10, 4096);
SuccessOrExit(err);
// Initialize the validation context.
memset(&validContext, 0, sizeof(validContext));
validContext.EffectiveTime = SecondsSinceEpochToPackedCertTime(time(NULL));
validContext.RequiredKeyUsages = kKeyUsageFlag_DigitalSignature;
validContext.ValidateFlags = kValidateFlag_IgnoreNotAfter;
// Load the Nest Production Device CA certificate so that it is available for chain validation.
err = certSet.LoadCert(mRootCert, mRootCertLen, kDecodeFlag_IsTrusted, cert);
SuccessOrExit(err);
exit:
return err;
}
virtual WEAVE_ERROR HandleCertValidationResult(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext,
const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo, uint32_t requestedKeyId)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
VerifyOrExit(requestedKeyId == WeaveKeyId::kClientRootKey, err = WEAVE_ERROR_INVALID_KEY_ID);
exit:
return err;
}
virtual WEAVE_ERROR EndCertValidation(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
VerifyOrExit(!isInitiator, err = WEAVE_ERROR_INVALID_ARGUMENT);
certSet.Release();
exit:
return err;
}
virtual WEAVE_ERROR ValidateUnsignedKeyExportMessage(bool isInitiator, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo, uint32_t requestedKeyId)
{
// Should never be called.
return WEAVE_ERROR_INCORRECT_STATE;
}
private:
const uint8_t *mDeviceCert;
uint16_t mDeviceCertLen;
const uint8_t *mDevicePrivKey;
uint16_t mDevicePrivKeyLen;
const uint8_t *mRootCert;
uint16_t mRootCertLen;
};
WEAVE_ERROR SimulateDeviceKeyExport(const uint8_t *deviceCert, uint16_t deviceCertLen,
const uint8_t *devicePrivKey, uint16_t devicePrivKeyLen,
const uint8_t *trustRootCert, uint16_t trustRootCertLen,
const uint8_t *exportReq, uint16_t exportReqLen,
uint8_t *exportRespBuf, uint16_t exportRespBufSize, uint16_t& exportRespLen,
bool& respIsReconfig)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
SimulatedDeviceKeyExportDelegate keyExportDelegate(deviceCert, deviceCertLen, devicePrivKey, devicePrivKeyLen, trustRootCert, trustRootCertLen);
SimulatedDeviceGroupKeyStore keyStore;
WeaveKeyExport keyExportObj;
keyExportObj.Init(&keyExportDelegate, &keyStore);
keyExportObj.SetAllowedConfigs(kKeyExportSupportedConfig_All);
exportRespLen = 0;
respIsReconfig = false;
// Call the key export object to process the key export request.
err = keyExportObj.ProcessKeyExportRequest(exportReq, exportReqLen, NULL, NULL);
if (err == WEAVE_ERROR_KEY_EXPORT_RECONFIGURE_REQUIRED)
{
// Call the key export object to generate a key export reconfigure message.
err = keyExportObj.GenerateKeyExportReconfigure(exportRespBuf, exportRespBufSize, exportRespLen);
SuccessOrExit(err);
respIsReconfig = true;
}
else
{
SuccessOrExit(err);
// Call the key export object to generate a key export response message.
err = keyExportObj.GenerateKeyExportResponse(exportRespBuf, exportRespBufSize, exportRespLen);
SuccessOrExit(err);
}
exit:
keyExportObj.Reset();
return err;
}
} // namespace KeyExport
} // namespace Security
} // namespace Profiles
} // namespace Weave
} // namespace nl
#endif // HAVE_MALLOC && HAVE_FREE && HAVE_TIME_H