summaryrefslogtreecommitdiff
path: root/SmartDeviceLink/private/SDLSecurityQueryPayload.m
diff options
context:
space:
mode:
Diffstat (limited to 'SmartDeviceLink/private/SDLSecurityQueryPayload.m')
-rw-r--r--SmartDeviceLink/private/SDLSecurityQueryPayload.m166
1 files changed, 166 insertions, 0 deletions
diff --git a/SmartDeviceLink/private/SDLSecurityQueryPayload.m b/SmartDeviceLink/private/SDLSecurityQueryPayload.m
new file mode 100644
index 000000000..744e1770a
--- /dev/null
+++ b/SmartDeviceLink/private/SDLSecurityQueryPayload.m
@@ -0,0 +1,166 @@
+//
+// SDLSecurityQueryPayload.m
+// SmartDeviceLink
+//
+// Created by Frank Elias on 7/28/21.
+// Copyright © 2021 smartdevicelink. All rights reserved.
+//
+
+#import "SDLSecurityQueryPayload.h"
+
+#import "SDLLogMacros.h"
+
+const NSUInteger SECURITY_QUERY_HEADER_SIZE = 12;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation SDLSecurityQueryPayload
+
+- (nullable instancetype)initWithData:(NSData *)data {
+ if (data == nil || data.length < SECURITY_QUERY_HEADER_SIZE) {
+ SDLLogE(@"Security Payload error: not enough data to form Security Query header. Data length: %lu", (unsigned long)data.length);
+ return nil;
+ }
+
+ self = [super init];
+ if (!self) { return nil; }
+
+ @try {
+ // Setup our pointers for data access
+ Byte *bytePointer = (UInt8 *)data.bytes;
+ UInt32 *ui32Pointer = (UInt32 *)data.bytes;
+
+ // Extract the parts
+ UInt8 queryType = bytePointer[0];
+
+ self.queryType = queryType;
+
+ // Extract the 24 bit query ID in the last 24 bits of the first 32 bits.
+ UInt32 queryID = ui32Pointer[0];
+ queryID = CFSwapInt32BigToHost(queryID) & 0x00FFFFFF;
+ self.queryID = queryID;
+
+ // Extract the 32 bit sequence number from the data after the first 32 bits.
+ UInt32 sequenceNumber = ui32Pointer[1];
+ sequenceNumber = CFSwapInt32BigToHost(sequenceNumber);
+ self.sequenceNumber = sequenceNumber;
+
+ // Extract the 32 bit json data size from the data after the first 64 bits
+ UInt32 jsonDataSize = ui32Pointer[2];
+ jsonDataSize = CFSwapInt32BigToHost(jsonDataSize);
+
+ // Extract the JSON data after the header (96 bits) based on the JSON data size
+ NSData *jsonData = nil;
+ NSUInteger offsetOfJSONData = SECURITY_QUERY_HEADER_SIZE;
+ if (jsonDataSize > 0 && jsonDataSize <= (data.length - SECURITY_QUERY_HEADER_SIZE)) {
+ jsonData = [data subdataWithRange:NSMakeRange(offsetOfJSONData, jsonDataSize)];
+ }
+ self.jsonData = jsonData;
+
+ // Extract the binary data after the header (96 bits) and the JSON data to the end
+ NSData *binaryData = nil;
+ NSUInteger offsetOfBinaryData = SECURITY_QUERY_HEADER_SIZE + jsonDataSize;
+ NSUInteger binaryDataSize = data.length - jsonDataSize - SECURITY_QUERY_HEADER_SIZE;
+ if (binaryDataSize > 0) {
+ binaryData = [data subdataWithRange:NSMakeRange(offsetOfBinaryData, binaryDataSize)];
+ }
+ self.binaryData = binaryData;
+
+ } @catch (NSException *e) {
+ SDLLogE(@"SDLSecurityQueryPayload init error: %@", e);
+ return nil;
+ }
+
+ return self;
+}
+
+- (instancetype)initWithQueryType:(SDLSecurityQueryType)queryType queryID:(SDLSecurityQueryId)queryID sequenceNumber:(UInt32)sequenceNumber jsonData:(nullable NSData *)jsonData binaryData:(nullable NSData *)binaryData {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _queryType = queryType;
+ _queryID = queryID;
+ _sequenceNumber = sequenceNumber;
+ _jsonData = jsonData;
+ _binaryData = binaryData;
+
+ return self;
+}
+
++ (nullable id)securityPayloadWithData:(NSData *)data {
+ return [[SDLSecurityQueryPayload alloc] initWithData:data];
+}
+
+- (NSData *)convertToData {
+ // From the properties, create a data buffer
+ // Query Type - first 8 bits
+ // Query ID - next 24 bits
+ // Sequence Number - next 32 bits
+ // JSON size - next 32 bits
+ UInt8 headerBuffer[SECURITY_QUERY_HEADER_SIZE];
+ *(UInt32 *)&headerBuffer[0] = CFSwapInt32HostToBig(self.queryID);
+ *(UInt32 *)&headerBuffer[4] = CFSwapInt32HostToBig(self.sequenceNumber);
+ *(UInt32 *)&headerBuffer[8] = CFSwapInt32HostToBig((UInt32)self.jsonData.length);
+ headerBuffer[0] &= 0xFF;
+ headerBuffer[0] |= self.queryType;
+
+ // Serialize the header. Append the json data, then the binary data
+ NSUInteger jsonDataSize = self.jsonData.length;
+ NSUInteger binaryDataSize = self.binaryData.length;
+ NSUInteger size = SECURITY_QUERY_HEADER_SIZE + jsonDataSize + binaryDataSize;
+ NSMutableData *dataOut = [NSMutableData dataWithCapacity:size];
+ [dataOut appendBytes:&headerBuffer length:12];
+ [dataOut appendData:self.jsonData];
+ [dataOut appendData:self.binaryData];
+
+ return dataOut;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"Security Query Header: %@, %@, sequenceNumber: %lu, json size: %lu bytes, binary size: %lu bytes", [self descriptionForQueryID], [self descriptionForQueryType], (unsigned long)self.sequenceNumber, (unsigned long)self.jsonData.length, (unsigned long)self.binaryData.length];
+}
+
+- (NSString *)descriptionForQueryID {
+ NSString *queryIdDescription;
+ switch (self.queryID) {
+ case SDLSecurityQueryIdSendHandshake:
+ queryIdDescription = @"Send Handshake Data";
+ break;
+ case SDLSecurityQueryIdSendInternalError:
+ queryIdDescription = @"Send Internal Error";
+ break;
+ case SDLSecurityQueryIdInvalid:
+ queryIdDescription = @"Invalid Query ID";
+ break;
+ default:
+ queryIdDescription = @"Unknown Query ID";
+ break;
+ }
+ return [NSString stringWithFormat:@"queryID: %lu - %@", (unsigned long)self.queryID, queryIdDescription];
+}
+
+- (NSString *)descriptionForQueryType {
+ NSString *queryTypeDescription;
+ switch (self.queryType) {
+ case SDLSecurityQueryTypeRequest:
+ queryTypeDescription = @"Request";
+ break;
+ case SDLSecurityQueryTypeResponse:
+ queryTypeDescription = @"Response";
+ break;
+ case SDLSecurityQueryTypeNotification:
+ queryTypeDescription = @"Notification";
+ break;
+ case SDLSecurityQueryTypeInvalid:
+ queryTypeDescription = @"Invalid Query Type";
+ break;
+ default:
+ queryTypeDescription = @"Unknown Query Type";
+ break;
+ }
+ return [NSString stringWithFormat:@"queryType: %lu - %@", (unsigned long)self.queryType, queryTypeDescription];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END