| /* |
| * |
| * 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 |