blob: 6366d18e9228fdc0f525a0733178f71362d1e637 [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 implements a Wrapper for C++ implementation of pincode encryption/decryption functionality.
* for pin encryption.
*
*/
#import "NLWeavePasscodeEncryptionSupport.h"
#include <Weave/Profiles/security/WeavePasscodes.h>
using namespace nl::Weave::Profiles::Security::Passcodes;
NSUInteger const NLWeavePasscode_Config1_TEST_ONLY = kPasscode_Config1_TEST_ONLY;
NSUInteger const NLWeavePasscode_Config2 = kPasscode_Config2;
UInt8 const NLWeavePasscodeEncKeyDiversifier[] = { 0x1A, 0x65, 0x5D, 0x96 };
UInt32 const NLWeavePasscodeEncKeyDiversifierSize = sizeof(NLWeavePasscodeEncKeyDiversifier);
UInt8 const NLWeavePasscodeFingerprintKeyDiversifier[] = { 0xD1, 0xA1, 0xD9, 0x6C };
UInt32 const NLWeavePasscodeFingerprintKeyDiversifierSize = sizeof(NLWeavePasscodeFingerprintKeyDiversifier);
UInt32 const NLWeavePasscodeEncryptionKeyLen = kPasscodeEncryptionKeyLen;
UInt32 const NLWeavePasscodeAuthenticationKeyLen = kPasscodeAuthenticationKeyLen;
UInt32 const NLWeavePasscodeFingerprintKeyLen = kPasscodeFingerprintKeyLen;
NSString *const NLPasscodeEncryptionSupportDomain = @"NLPasscodeEncryptionSupportDomain";
@implementation NLWeavePasscodeEncryptionSupport
#pragma mark Public Methods
+ (NSData *) encryptPasscode: (UInt8) config
keyId: (UInt32) keyId
nonce: (UInt32) nonce
passcode: (NSData *) passcode
encKey: (NSData *) encKey
authKey: (NSData *) authKey
fingerprintKey: (NSData *) fingerprintKey
error: (NSError **) errOut {
if (config != NLWeavePasscode_Config1_TEST_ONLY) {
if (![NLWeavePasscodeEncryptionSupport validateKeySize: encKey
authKey: authKey
fingerprintKey: fingerprintKey
error: errOut]) {
return nil;
}
}
NSMutableData * encPasscodeBuff = [[NSMutableData alloc] initWithLength: kPasscodeMaxEncryptedLen];
size_t encPasscodeLen =0;
WEAVE_ERROR err = EncryptPasscode(config, keyId, nonce,
(unsigned char *) [passcode bytes],
[passcode length],
(unsigned char *) [encKey bytes],
(unsigned char *) [authKey bytes],
(unsigned char *) [fingerprintKey bytes],
(unsigned char *) [encPasscodeBuff mutableBytes],
[encPasscodeBuff length],
encPasscodeLen);
if (err != WEAVE_NO_ERROR){
if (errOut) {
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"EncryptPasscode error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainEncryptionFailure
userInfo: userInfo];
}
return nil;
}
[encPasscodeBuff setLength: encPasscodeLen];
return encPasscodeBuff;
}
+ (nullable NSData *) decryptPasscode: (NSData *) encPasscode
config: (UInt8) config
encKey: (NSData *) encKey
authKey: (NSData *) authKey
fingerprintKey: (NSData *) fingerprintKey
error: (NSError **) errOut {
NSMutableData * passcodeBuff = [[NSMutableData alloc] initWithLength: kPasscodePaddedLen];
size_t passcodeLen =0;
if (config != NLWeavePasscode_Config1_TEST_ONLY) {
if (![NLWeavePasscodeEncryptionSupport validateKeySize: encKey
authKey: authKey
fingerprintKey: fingerprintKey
error: errOut]) {
return nil;
}
}
WEAVE_ERROR err = DecryptPasscode((unsigned char *) [encPasscode bytes],
[encPasscode length],
(unsigned char *) [encKey bytes],
(unsigned char *) [authKey bytes],
(unsigned char *) [fingerprintKey bytes],
(unsigned char *) [passcodeBuff mutableBytes],
[passcodeBuff length],
passcodeLen);
if (err != WEAVE_NO_ERROR){
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"DecryptPasscode error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainDecryptionFailure
userInfo: userInfo];
return nil;
}
[passcodeBuff setLength: passcodeLen];
return passcodeBuff;
}
+ (BOOL) isSupportedPasscodeEncryptionConfig: (UInt8) config {
return IsSupportedPasscodeEncryptionConfig(config);
}
+ (BOOL) getEncryptedPasscodeConfig: (NSData *) encPasscode
config: (UInt8 *) configOut
error: (NSError **) errOut {
UInt8 config =0;
WEAVE_ERROR err = GetEncryptedPasscodeConfig((unsigned char *) [encPasscode bytes],
[encPasscode length], config);
if (err != WEAVE_NO_ERROR){
NSString *failureReason =
[NSString stringWithFormat:NSLocalizedString(@"retrieving encrypted config error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidData
userInfo: userInfo];
return FALSE;
}
*configOut = config;
return TRUE;
}
+ (BOOL) getEncryptedPasscodeKeyId: (NSData *) encPasscode
keyId: (UInt32 *) keyIdOut
error: (NSError **) errOut {
UInt32 keyId =0;
WEAVE_ERROR err = GetEncryptedPasscodeKeyId((unsigned char *) [encPasscode bytes],
[encPasscode length], (uint32_t &) keyId);
if (err != WEAVE_NO_ERROR) {
NSString *failureReason =
[NSString stringWithFormat:NSLocalizedString(@"retrieving encrypted config error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidData
userInfo: userInfo];
return FALSE;
}
*keyIdOut = keyId;
return TRUE;
}
+ (BOOL) getEncryptedPasscodeNonce: (NSData *) encPasscode
nonce: (UInt32 *) nonceOut
error: (NSError **) errOut {
UInt32 nonce = 0;
WEAVE_ERROR err = GetEncryptedPasscodeNonce((unsigned char *) [encPasscode bytes],
[encPasscode length], (uint32_t &) nonce);
if (err != WEAVE_NO_ERROR) {
NSString *failureReason =
[NSString stringWithFormat:NSLocalizedString(@"retrieving encrypted passcode nonce: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidData
userInfo: userInfo];
return FALSE;
}
*nonceOut = nonce;
return TRUE;
}
+ (nullable NSData *) getEncryptedPasscodeFingerprint: (NSData *) encPasscode
error: (NSError **) errOut {
NSMutableData * fingerprint = [[NSMutableData alloc] initWithLength: kPasscodeFingerprintLen];
size_t fingerprintLen =0;
WEAVE_ERROR err = GetEncryptedPasscodeFingerprint((unsigned char *) [encPasscode bytes],
[encPasscode length],
(unsigned char *) [fingerprint mutableBytes],
[fingerprint length],
fingerprintLen);
if (err != WEAVE_NO_ERROR){
NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"get fingerprint error: %d", @""), err];
NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey: failureReason };
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidData
userInfo: userInfo];
return nil;
}
[fingerprint setLength: fingerprintLen];
return fingerprint;
}
#pragma mark Private Methods
+ (BOOL) validateKeySize: (NSData *) encKey
authKey: (NSData *) authKey
fingerprintKey: (NSData *) fingerprintKey
error: (NSError **) errOut {
if ([encKey length] != kPasscodeEncryptionKeyLen) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidEncKeySize
userInfo: nil];
}
return FALSE;
}
if ([authKey length] != kPasscodeAuthenticationKeyLen) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidAuthKeySize
userInfo: nil];
}
return FALSE;
}
if ([fingerprintKey length] != kPasscodeFingerprintKeyLen) {
if (errOut) {
*errOut = [NSError errorWithDomain: NLPasscodeEncryptionSupportDomain
code: NLPasscodeEncryptionSupportDomainInvalidFingerprintKeySize
userInfo: nil];
}
return FALSE;
}
return TRUE;
}
@end