blob: c0f81a9a8b4d70a83eec6a707c9c01f0a5a68751 [file] [log] [blame]
/*
*
* Copyright (c) 2016-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
* This file defines a Wrapper for C++ implementation of key export functionality
* to support pin encryption.
*
*/
#import "NLWeaveKeyExportClient.h"
#import "NLWeaveKeyExportSupport.h"
#include <Weave/Core/WeaveCore.h>
#include <Weave/Core/WeaveKeyIds.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Profiles/security/WeaveKeyExportClient.h>
using namespace nl::Weave::Profiles::Security::KeyExport;
NSString *const NLWeaveKeyExportClientErrorDomain = @"NLWeaveKeyExportClientErrorDomain";
@interface NLWeaveKeyExportClient ()
{
WeaveStandAloneKeyExportClient * _mKeyExportClientCpp;
}
@end
@implementation NLWeaveKeyExportClient
static UInt32 const kMaxPubKeySize = (((WEAVE_CONFIG_MAX_EC_BITS + 7) / 8) + 1) * 2;
static UInt32 const kMaxECDSASigSize = kMaxPubKeySize;
- (nullable NSData *) generateKeyExportRequest: (UInt32) keyId
responderNodeId: (UInt64) responderNodeId
accessToken: (NSData *) accessToken
error: (NSError **) errOut {
WEAVE_ERROR err = WEAVE_NO_ERROR;
uint16_t exportReqLen = 0;
if (accessToken == nil) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLWeaveKeyExportClientErrorDomain
code: NLWeaveKeyExportClientErrorDomainInvalidArgument
userInfo: nil];
}
return nil;
}
size_t exportReqBufSize =
7 // Key export request header size
+ kMaxPubKeySize // Ephemeral public key size
+ kMaxECDSASigSize // Size of bare signature field
+ [accessToken length] // Size equal to at least the total size of the client certificates
+ 1024; // Space for additional signature fields plus encoding overhead
if (exportReqBufSize > UINT16_MAX) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainInvalidExportBufferSize
userInfo:nil];
}
return nil;
}
NSMutableData * exportReqBuf = [[NSMutableData alloc] initWithLength:exportReqBufSize];
err = _mKeyExportClientCpp->GenerateKeyExportRequest((uint32_t) keyId,
(uint64_t) responderNodeId,
(unsigned char *) [accessToken bytes],
[accessToken length],
(unsigned char *) [exportReqBuf mutableBytes],
exportReqBufSize,
exportReqLen);
if (err != WEAVE_NO_ERROR) {
if (errOut) {
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(
@"GenerateKeyExportRequest error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain:NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainKeyExportRequestFailure userInfo: userInfo];
}
return nil;
}
[exportReqBuf setLength: exportReqLen];
return exportReqBuf;
}
- (nullable NSData *) generateKeyExportRequest: (UInt32) keyId
responderNodeId: (UInt64) responderNodeId
clientCert: (NSData *) clientCert
clientKey: (NSData *) clientKey
error: (NSError **) errOut {
WEAVE_ERROR err = WEAVE_NO_ERROR;
uint16_t exportReqLen = 0;
if (clientKey == nil || clientCert){
if (errOut) {
*errOut = [NSError errorWithDomain:NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainInvalidArgument
userInfo:nil];
}
return nil;
}
size_t exportReqBufSize =
7 // Key export request header size
+ kMaxPubKeySize // Ephemeral public key size
+ kMaxECDSASigSize // Size of bare signature field
+ [clientCert length] // Size equal to at least the total size of the client certificates
+ 1024; // Space for additional signature fields plus encoding overhead
if (exportReqBufSize > UINT16_MAX) {
if (errOut) {
*errOut = [NSError errorWithDomain:NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainInvalidExportBufferSize
userInfo:nil];
}
return nil;
}
NSMutableData * exportReqBuf = [[NSMutableData alloc] initWithLength:exportReqBufSize];
err = _mKeyExportClientCpp->GenerateKeyExportRequest((uint32_t) keyId,
(uint64_t) responderNodeId,
(unsigned char *) [clientCert bytes],
[clientCert length],
(unsigned char *) [clientKey bytes],
[clientKey length],
(unsigned char *) [exportReqBuf mutableBytes],
exportReqBufSize,
exportReqLen);
if (err != WEAVE_NO_ERROR) {
if (errOut) {
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(
@"GenerateKeyExportRequest error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain:NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainKeyExportRequestFailure userInfo: userInfo];
}
return nil;
}
[exportReqBuf setLength: exportReqLen];
return exportReqBuf;
}
- (nullable NSData *) processKeyExportResponse: (UInt64) responderNodeId
exportResp: (NSData *) exportResp
error: (NSError **) errOut {
WEAVE_ERROR err = WEAVE_NO_ERROR;
if (exportResp == nil) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLWeaveKeyExportClientErrorDomain
code: NLWeaveKeyExportClientErrorDomainInvalidArgument
userInfo: nil];
}
return nil;
}
// Since the exported key is contained within the export response, a buffer of the same size
// is guaranteed to be sufficient.
size_t exportedKeyBufLen = [exportResp length];
NSMutableData * exportedKeyBuf = [[NSMutableData alloc] initWithLength:exportedKeyBufLen];
uint16_t exportedKeyLen;
uint32_t exportedKeyId;
err = _mKeyExportClientCpp->ProcessKeyExportResponse(
(unsigned char *) [exportResp bytes],
[exportResp length],
(uint64_t) responderNodeId,
(unsigned char *) [exportedKeyBuf mutableBytes],
exportedKeyBufLen,
exportedKeyLen,
exportedKeyId);
if (err != WEAVE_NO_ERROR) {
if (errOut) {
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(
@"ProcessKeyExportResponse error:: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain:NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainKeyExportResponseFailure userInfo: userInfo];
}
return nil;
}
[exportedKeyBuf setLength: exportedKeyLen];
return exportedKeyBuf;
}
- (void) reset {
_mKeyExportClientCpp->Reset();
}
/**
@note
This function can only be called by the ARC runtime
*/
- (void)dealloc
{
_mKeyExportClientCpp->Reset();
delete _mKeyExportClientCpp;
}
- (BOOL) processKeyExportReconfigure: (NSData *) reconfig
error: (NSError **) errOut {
WEAVE_ERROR err = WEAVE_NO_ERROR;
if (reconfig == nil) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLWeaveKeyExportClientErrorDomain
code: NLWeaveKeyExportClientErrorDomainInvalidArgument
userInfo: nil];
}
return false;
}
err = _mKeyExportClientCpp->ProcessKeyExportReconfigure((unsigned char *) [reconfig bytes], [reconfig length]);
if (err != WEAVE_NO_ERROR) {
if (errOut) {
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(
@"ProcessKeyExportResponse error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain:NLWeaveKeyExportClientErrorDomain
code:NLWeaveKeyExportClientErrorDomainProcessReconfiugreFailure userInfo: userInfo];
}
return false;
}
return true;
}
- (BOOL) allowNestDevelopmentDevices {
return _mKeyExportClientCpp->AllowNestDevelopmentDevices();
}
- (void) setAllowNestDevelopmentDevices: (BOOL) nestDev {
_mKeyExportClientCpp->AllowNestDevelopmentDevices(nestDev);
}
- (BOOL) allowSHA1DeviceCertificates {
return _mKeyExportClientCpp->AllowSHA1DeviceCerts();
}
- (void) setAllowSHA1DeviceCertificates: (BOOL) nestDev {
_mKeyExportClientCpp->AllowSHA1DeviceCerts(nestDev);
}
- (instancetype) init {
self = [super init];
if (self) {
_mKeyExportClientCpp = new WeaveStandAloneKeyExportClient();
_mKeyExportClientCpp->Init();
}
return self;
}
@end