Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -27,11 +27,11 @@ OFCharacterSet.m \ OFColor.m \ OFConstantString.m \ OFCountedSet.m \ OFData.m \ - OFData+ASN1DERValue.m \ + OFData+ASN1DERParsing.m \ OFData+CryptoHashing.m \ OFData+MessagePackParsing.m \ OFDate.m \ OFDictionary.m \ OFEnumerator.m \ ADDED src/OFData+ASN1DERParsing.h Index: src/OFData+ASN1DERParsing.h ================================================================== --- src/OFData+ASN1DERParsing.h +++ src/OFData+ASN1DERParsing.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFData.h" +#import "OFASN1Value.h" + +OF_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif +extern int _OFData_ASN1DERParsing_reference; +#ifdef __cplusplus +} +#endif + +@interface OFData (ASN1DERParsing) +/*! + * @brief The data interpreted as ASN.1 in DER representation and parsed as an + * object. + * + * This is either an OFArray (for a sequence), an OFSet (for a set) or an + * OFASN1Value. + */ +@property (readonly, nonatomic) id objectByParsingASN1DER; + +/*! + * @brief Parses the ASN.1 DER representation and returns it as an object. + * + * This is either an OFArray (for a sequence), an OFSet (for a set) or an + * OFASN1Value. + * + * @param depthLimit The maximum depth the parser should accept (defaults to 32 + * if not specified, 0 means no limit (insecure!)) + * @return The ASN.1 DER representation as an object + */ +- (id)objectByParsingASN1DERWithDepthLimit: (size_t)depthLimit; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFData+ASN1DERParsing.m Index: src/OFData+ASN1DERParsing.m ================================================================== --- src/OFData+ASN1DERParsing.m +++ src/OFData+ASN1DERParsing.m @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFData+ASN1DERParsing.h" +#import "OFASN1BitString.h" +#import "OFASN1Boolean.h" +#import "OFASN1Enumerated.h" +#import "OFASN1IA5String.h" +#import "OFASN1Integer.h" +#import "OFASN1NumericString.h" +#import "OFASN1ObjectIdentifier.h" +#import "OFASN1OctetString.h" +#import "OFASN1PrintableString.h" +#import "OFASN1UTF8String.h" +#import "OFASN1Value.h" +#import "OFArray.h" +#import "OFNull.h" +#import "OFSet.h" + +#import "OFInvalidArgumentException.h" +#import "OFInvalidFormatException.h" +#import "OFOutOfRangeException.h" +#import "OFTruncatedDataException.h" + +enum { + ASN1_TAG_CONSTRUCTED_MASK = 0x20 +}; + +int _OFData_ASN1DERParsing_reference; + +static size_t parseObject(OFData *self, id *object, size_t depthLimit); + +static OFArray * +parseSequence(OFData *contents, size_t depthLimit) +{ + OFMutableArray *ret = [OFMutableArray array]; + size_t count = contents.count; + + if (depthLimit == 0) + @throw [OFOutOfRangeException exception]; + + while (count > 0) { + id object; + size_t objectLength; + + objectLength = parseObject(contents, &object, depthLimit); + + count -= objectLength; + contents = [contents subdataWithRange: + of_range(objectLength, count)]; + + [ret addObject: object]; + } + + [ret makeImmutable]; + + return ret; +} + +static OFSet * +parseSet(OFData *contents, size_t depthLimit) +{ + OFMutableSet *ret = [OFMutableSet set]; + size_t count = contents.count; + OFData *previousObjectData = nil; + + if (depthLimit == 0) + @throw [OFOutOfRangeException exception]; + + while (count > 0) { + id object; + size_t objectLength; + OFData *objectData; + + objectLength = parseObject(contents, &object, depthLimit); + objectData = [contents subdataWithRange: + of_range(0, objectLength)]; + + if (previousObjectData != nil && + [objectData compare: previousObjectData] != + OF_ORDERED_DESCENDING) + @throw [OFInvalidFormatException exception]; + + count -= objectLength; + contents = [contents subdataWithRange: + of_range(objectLength, count)]; + + [ret addObject: object]; + + previousObjectData = objectData; + } + + [ret makeImmutable]; + + return ret; +} + +static size_t +parseObject(OFData *self, id *object, size_t depthLimit) +{ + const unsigned char *items = self.items; + size_t count = self.count; + unsigned char tag; + size_t contentsLength, bytesConsumed = 0; + Class valueClass; + OFData *contents; + + if (count < 2) + @throw [OFTruncatedDataException exception]; + + tag = *items++; + contentsLength = *items++; + bytesConsumed += 2; + + if (contentsLength > 127) { + uint_fast8_t lengthLength = contentsLength & 0x7F; + + if (lengthLength > sizeof(size_t)) + @throw [OFOutOfRangeException exception]; + + if (count - bytesConsumed < lengthLength) + @throw [OFTruncatedDataException exception]; + + if (lengthLength == 0 || + (lengthLength == 1 && items[0] < 0x80) || + (lengthLength >= 2 && items[0] == 0)) + @throw [OFInvalidFormatException exception]; + + contentsLength = 0; + + for (uint_fast8_t i = 0; i < lengthLength; i++) + contentsLength = (contentsLength << 8) | *items++; + + bytesConsumed += lengthLength; + + if (contentsLength <= 127) + @throw [OFInvalidFormatException exception]; + } + + if (count - bytesConsumed < contentsLength) + @throw [OFTruncatedDataException exception]; + + contents = [self subdataWithRange: + of_range(bytesConsumed, contentsLength)]; + bytesConsumed += contentsLength; + + switch (tag & ~ASN1_TAG_CONSTRUCTED_MASK) { + case OF_ASN1_TAG_NUMBER_BOOLEAN: + valueClass = [OFASN1Boolean class]; + break; + case OF_ASN1_TAG_NUMBER_INTEGER: + valueClass = [OFASN1Integer class]; + break; + case OF_ASN1_TAG_NUMBER_BIT_STRING: + valueClass = [OFASN1BitString class]; + break; + case OF_ASN1_TAG_NUMBER_OCTET_STRING: + valueClass = [OFASN1OctetString class]; + break; + case OF_ASN1_TAG_NUMBER_NULL: + if (tag & ASN1_TAG_CONSTRUCTED_MASK) + @throw [OFInvalidFormatException exception]; + + if (contents.count != 0) + @throw [OFInvalidFormatException exception]; + + *object = [OFNull null]; + return bytesConsumed; + case OF_ASN1_TAG_NUMBER_OBJECT_IDENTIFIER: + valueClass = [OFASN1ObjectIdentifier class]; + break; + case OF_ASN1_TAG_NUMBER_ENUMERATED: + valueClass = [OFASN1Enumerated class]; + break; + case OF_ASN1_TAG_NUMBER_UTF8_STRING: + valueClass = [OFASN1UTF8String class]; + break; + case OF_ASN1_TAG_NUMBER_SEQUENCE: + if (!(tag & ASN1_TAG_CONSTRUCTED_MASK)) + @throw [OFInvalidFormatException exception]; + + *object = parseSequence(contents, depthLimit - 1); + return bytesConsumed; + case OF_ASN1_TAG_NUMBER_SET: + if (!(tag & ASN1_TAG_CONSTRUCTED_MASK)) + @throw [OFInvalidFormatException exception]; + + *object = parseSet(contents, depthLimit - 1); + return bytesConsumed; + case OF_ASN1_TAG_NUMBER_NUMERIC_STRING: + valueClass = [OFASN1NumericString class]; + break; + case OF_ASN1_TAG_NUMBER_PRINTABLE_STRING: + valueClass = [OFASN1PrintableString class]; + break; + case OF_ASN1_TAG_NUMBER_IA5_STRING: + valueClass = [OFASN1IA5String class]; + break; + default: + valueClass = [OFASN1Value class]; + break; + } + + *object = [[[valueClass alloc] + initWithTagClass: tag >> 6 + tagNumber: tag & 0x1F + constructed: tag & ASN1_TAG_CONSTRUCTED_MASK + DEREncodedContents: contents] autorelease]; + return bytesConsumed; +} + +@implementation OFData (ASN1DERParsing) +- (id)objectByParsingASN1DER +{ + return [self objectByParsingASN1DERWithDepthLimit: 32]; +} + +- (id)objectByParsingASN1DERWithDepthLimit: (size_t)depthLimit +{ + void *pool = objc_autoreleasePoolPush(); + id object; + + if (self.itemSize != 1) + @throw [OFInvalidArgumentException exception]; + + if (parseObject(self, &object, depthLimit) != self.count) + @throw [OFInvalidFormatException exception]; + + [object retain]; + + objc_autoreleasePoolPop(pool); + + return [object autorelease]; +} +@end DELETED src/OFData+ASN1DERValue.h Index: src/OFData+ASN1DERValue.h ================================================================== --- src/OFData+ASN1DERValue.h +++ src/OFData+ASN1DERValue.h @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018, 2019, 2020 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFData.h" -#import "OFASN1Value.h" - -OF_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif -extern int _OFData_ASN1DERValue_reference; -#ifdef __cplusplus -} -#endif - -@interface OFData (ASN1DERValue) -/*! - * @brief The data interpreted as ASN.1 in DER representation and parsed as an - * object. - * - * This is either an OFArray (for a sequence), an OFSet (for a set) or an - * OFASN1Value. - */ -@property (readonly, nonatomic) id ASN1DERValue; - -/*! - * @brief Parses the ASN.1 DER representation and returns it as an object. - * - * This is either an OFArray (for a sequence), an OFSet (for a set) or an - * OFASN1Value. - * - * @param depthLimit The maximum depth the parser should accept (defaults to 32 - * if not specified, 0 means no limit (insecure!)) - * @return The ASN.1 DER representation as an object - */ -- (id)ASN1DERValueWithDepthLimit: (size_t)depthLimit; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFData+ASN1DERValue.m Index: src/OFData+ASN1DERValue.m ================================================================== --- src/OFData+ASN1DERValue.m +++ src/OFData+ASN1DERValue.m @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018, 2019, 2020 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFData+ASN1DERValue.h" -#import "OFASN1BitString.h" -#import "OFASN1Boolean.h" -#import "OFASN1Enumerated.h" -#import "OFASN1IA5String.h" -#import "OFASN1Integer.h" -#import "OFASN1NumericString.h" -#import "OFASN1ObjectIdentifier.h" -#import "OFASN1OctetString.h" -#import "OFASN1PrintableString.h" -#import "OFASN1UTF8String.h" -#import "OFASN1Value.h" -#import "OFArray.h" -#import "OFNull.h" -#import "OFSet.h" - -#import "OFInvalidArgumentException.h" -#import "OFInvalidFormatException.h" -#import "OFOutOfRangeException.h" -#import "OFTruncatedDataException.h" - -enum { - ASN1_TAG_CONSTRUCTED_MASK = 0x20 -}; - -int _OFData_ASN1DERValue_reference; - -static size_t parseObject(OFData *self, id *object, size_t depthLimit); - -static OFArray * -parseSequence(OFData *contents, size_t depthLimit) -{ - OFMutableArray *ret = [OFMutableArray array]; - size_t count = contents.count; - - if (depthLimit == 0) - @throw [OFOutOfRangeException exception]; - - while (count > 0) { - id object; - size_t objectLength; - - objectLength = parseObject(contents, &object, depthLimit); - - count -= objectLength; - contents = [contents subdataWithRange: - of_range(objectLength, count)]; - - [ret addObject: object]; - } - - [ret makeImmutable]; - - return ret; -} - -static OFSet * -parseSet(OFData *contents, size_t depthLimit) -{ - OFMutableSet *ret = [OFMutableSet set]; - size_t count = contents.count; - OFData *previousObjectData = nil; - - if (depthLimit == 0) - @throw [OFOutOfRangeException exception]; - - while (count > 0) { - id object; - size_t objectLength; - OFData *objectData; - - objectLength = parseObject(contents, &object, depthLimit); - objectData = [contents subdataWithRange: - of_range(0, objectLength)]; - - if (previousObjectData != nil && - [objectData compare: previousObjectData] != - OF_ORDERED_DESCENDING) - @throw [OFInvalidFormatException exception]; - - count -= objectLength; - contents = [contents subdataWithRange: - of_range(objectLength, count)]; - - [ret addObject: object]; - - previousObjectData = objectData; - } - - [ret makeImmutable]; - - return ret; -} - -static size_t -parseObject(OFData *self, id *object, size_t depthLimit) -{ - const unsigned char *items = self.items; - size_t count = self.count; - unsigned char tag; - size_t contentsLength, bytesConsumed = 0; - Class valueClass; - OFData *contents; - - if (count < 2) - @throw [OFTruncatedDataException exception]; - - tag = *items++; - contentsLength = *items++; - bytesConsumed += 2; - - if (contentsLength > 127) { - uint_fast8_t lengthLength = contentsLength & 0x7F; - - if (lengthLength > sizeof(size_t)) - @throw [OFOutOfRangeException exception]; - - if (count - bytesConsumed < lengthLength) - @throw [OFTruncatedDataException exception]; - - if (lengthLength == 0 || - (lengthLength == 1 && items[0] < 0x80) || - (lengthLength >= 2 && items[0] == 0)) - @throw [OFInvalidFormatException exception]; - - contentsLength = 0; - - for (uint_fast8_t i = 0; i < lengthLength; i++) - contentsLength = (contentsLength << 8) | *items++; - - bytesConsumed += lengthLength; - - if (contentsLength <= 127) - @throw [OFInvalidFormatException exception]; - } - - if (count - bytesConsumed < contentsLength) - @throw [OFTruncatedDataException exception]; - - contents = [self subdataWithRange: - of_range(bytesConsumed, contentsLength)]; - bytesConsumed += contentsLength; - - switch (tag & ~ASN1_TAG_CONSTRUCTED_MASK) { - case OF_ASN1_TAG_NUMBER_BOOLEAN: - valueClass = [OFASN1Boolean class]; - break; - case OF_ASN1_TAG_NUMBER_INTEGER: - valueClass = [OFASN1Integer class]; - break; - case OF_ASN1_TAG_NUMBER_BIT_STRING: - valueClass = [OFASN1BitString class]; - break; - case OF_ASN1_TAG_NUMBER_OCTET_STRING: - valueClass = [OFASN1OctetString class]; - break; - case OF_ASN1_TAG_NUMBER_NULL: - if (tag & ASN1_TAG_CONSTRUCTED_MASK) - @throw [OFInvalidFormatException exception]; - - if (contents.count != 0) - @throw [OFInvalidFormatException exception]; - - *object = [OFNull null]; - return bytesConsumed; - case OF_ASN1_TAG_NUMBER_OBJECT_IDENTIFIER: - valueClass = [OFASN1ObjectIdentifier class]; - break; - case OF_ASN1_TAG_NUMBER_ENUMERATED: - valueClass = [OFASN1Enumerated class]; - break; - case OF_ASN1_TAG_NUMBER_UTF8_STRING: - valueClass = [OFASN1UTF8String class]; - break; - case OF_ASN1_TAG_NUMBER_SEQUENCE: - if (!(tag & ASN1_TAG_CONSTRUCTED_MASK)) - @throw [OFInvalidFormatException exception]; - - *object = parseSequence(contents, depthLimit - 1); - return bytesConsumed; - case OF_ASN1_TAG_NUMBER_SET: - if (!(tag & ASN1_TAG_CONSTRUCTED_MASK)) - @throw [OFInvalidFormatException exception]; - - *object = parseSet(contents, depthLimit - 1); - return bytesConsumed; - case OF_ASN1_TAG_NUMBER_NUMERIC_STRING: - valueClass = [OFASN1NumericString class]; - break; - case OF_ASN1_TAG_NUMBER_PRINTABLE_STRING: - valueClass = [OFASN1PrintableString class]; - break; - case OF_ASN1_TAG_NUMBER_IA5_STRING: - valueClass = [OFASN1IA5String class]; - break; - default: - valueClass = [OFASN1Value class]; - break; - } - - *object = [[[valueClass alloc] - initWithTagClass: tag >> 6 - tagNumber: tag & 0x1F - constructed: tag & ASN1_TAG_CONSTRUCTED_MASK - DEREncodedContents: contents] autorelease]; - return bytesConsumed; -} - -@implementation OFData (ASN1DERValue) -- (id)ASN1DERValue -{ - return [self ASN1DERValueWithDepthLimit: 32]; -} - -- (id)ASN1DERValueWithDepthLimit: (size_t)depthLimit -{ - void *pool = objc_autoreleasePoolPush(); - id object; - - if (self.itemSize != 1) - @throw [OFInvalidArgumentException exception]; - - if (parseObject(self, &object, depthLimit) != self.count) - @throw [OFInvalidFormatException exception]; - - [object retain]; - - objc_autoreleasePoolPop(pool); - - return [object autorelease]; -} -@end Index: src/OFData.h ================================================================== --- src/OFData.h +++ src/OFData.h @@ -325,8 +325,8 @@ @end OF_ASSUME_NONNULL_END #import "OFMutableData.h" -#import "OFData+ASN1DERValue.h" +#import "OFData+ASN1DERParsing.h" #import "OFData+CryptoHashing.h" #import "OFData+MessagePackParsing.h" Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -46,11 +46,11 @@ /* References for static linking */ void _references_to_categories_of_OFData(void) { - _OFData_ASN1DERValue_reference = 1; + _OFData_ASN1DERParsing_reference = 1; _OFData_CryptoHashing_reference = 1; _OFData_MessagePackParsing_reference = 1; } @implementation OFData Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -9,12 +9,12 @@ DISTCLEAN = Info.plist PROG_NOINST = tests${PROG_SUFFIX} STATIC_LIB_NOINST = ${TESTS_STATIC_LIB} SRCS = ForwardingTests.m \ + OFASN1DERParsingTests.m \ OFASN1DERRepresentationTests.m \ - OFASN1DERValueTests.m \ OFArrayTests.m \ ${OF_BLOCK_TESTS_M} \ OFCharacterSetTests.m \ OFDataTests.m \ OFDateTests.m \ ADDED tests/OFASN1DERParsingTests.m Index: tests/OFASN1DERParsingTests.m ================================================================== --- tests/OFASN1DERParsingTests.m +++ tests/OFASN1DERParsingTests.m @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +static OFString *module = @"OFData+ASN1DERParsing"; + +@implementation TestsAppDelegate (OFASN1DERParsingTests) +- (void)ASN1DERParsingTests +{ + void *pool = objc_autoreleasePoolPush(); + OFASN1BitString *bitString; + OFArray *array; + OFSet *set; + OFEnumerator *enumerator; + + /* Boolean */ + TEST(@"Parsing of boolean", + ![[OFData dataWithItems: "\x01\x01\x00" + count: 3].objectByParsingASN1DER booleanValue] && + [[OFData dataWithItems: "\x01\x01\xFF" + count: 3].objectByParsingASN1DER booleanValue]) + + EXPECT_EXCEPTION(@"Detection of invalid boolean #1", + OFInvalidFormatException, + [[OFData dataWithItems: "\x01\x01\x01" + count: 3] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid boolean #2", + OFInvalidFormatException, + [[OFData dataWithItems: "\x01\x02\x00\x00" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid boolean #3", + OFInvalidFormatException, + [[OFData dataWithItems: "\x01\x00" + count: 2] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated boolean", + OFTruncatedDataException, + [[OFData dataWithItems: "\x01\x01" + count: 2] objectByParsingASN1DER]) + + /* Integer */ + TEST(@"Parsing of integer", + [[OFData dataWithItems: "\x02\x00" + count: 2].objectByParsingASN1DER longLongValue] == + 0 && + [[OFData dataWithItems: "\x02\x01\x01" + count: 3].objectByParsingASN1DER longLongValue] == + 1 && + [[OFData dataWithItems: "\x02\x02\x01\x04" + count: 4].objectByParsingASN1DER longLongValue] == + 260 && + [[OFData dataWithItems: "\x02\x01\xFF" + count: 3].objectByParsingASN1DER longLongValue] == + -1 && + [[OFData dataWithItems: "\x02\x03\xFF\x00\x00" + count: 5].objectByParsingASN1DER longLongValue] == + -65536 && + (unsigned long long)[[OFData dataWithItems: "\x02\x09\x00\xFF\xFF" + "\xFF\xFF\xFF\xFF\xFF" + "\xFF" + count: 11] + .objectByParsingASN1DER longLongValue] == ULLONG_MAX) + + EXPECT_EXCEPTION(@"Detection of invalid integer #1", + OFInvalidFormatException, + [[OFData dataWithItems: "\x02\x02\x00\x00" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid integer #2", + OFInvalidFormatException, + [[OFData dataWithItems: "\x02\x02\x00\x7F" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid integer #3", + OFInvalidFormatException, + [[OFData dataWithItems: "\x02\x02\xFF\x80" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range integer", + OFOutOfRangeException, + [[OFData dataWithItems: "\x02\x09\x01" + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated integer", + OFTruncatedDataException, + [[OFData dataWithItems: "\x02\x02\x00" + count: 3] objectByParsingASN1DER]) + + /* Bit string */ + TEST(@"Parsing of bit string", + (bitString = [OFData dataWithItems: "\x03\x01\x00" + count: 3].objectByParsingASN1DER) && + [bitString.bitStringValue isEqual: [OFData dataWithItems: "" + count: 0]] && + bitString.bitStringLength == 0 && + (bitString = [OFData dataWithItems: "\x03\x0D\x01Hello World\x80" + count: 15].objectByParsingASN1DER) && + [bitString.bitStringValue + isEqual: [OFData dataWithItems: "Hello World\x80" + count: 12]] && + bitString.bitStringLength == 95 && + (bitString = [OFData dataWithItems: "\x03\x81\x80\x00xxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxx" + count: 131].objectByParsingASN1DER) && + [bitString.bitStringValue + isEqual: [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxx" + count: 127]] && + bitString.bitStringLength == 127 * 8) + + EXPECT_EXCEPTION(@"Detection of invalid bit string #1", + OFInvalidFormatException, + [[OFData dataWithItems: "\x03\x00" + count: 2] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid bit string #2", + OFInvalidFormatException, + [[OFData dataWithItems: "\x03\x01\x01" + count: 3] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range bit string", + OFOutOfRangeException, + [[OFData dataWithItems: "\x03\x89" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated bit string", + OFTruncatedDataException, + [[OFData dataWithItems: "\x03\x01" + count: 2] objectByParsingASN1DER]) + + /* Octet string */ + TEST(@"Parsing of octet string", + [[[OFData dataWithItems: "\x04\x0CHello World!" + count: 14].objectByParsingASN1DER + octetStringValue] isEqual: [OFData dataWithItems: "Hello World!" + count: 12]] && + [[[OFData dataWithItems: "\x04\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxx" + count: 131].objectByParsingASN1DER + octetStringValue] isEqual: + [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + count: 128]]) + + EXPECT_EXCEPTION(@"Detection of out of range octet string", + OFOutOfRangeException, + [[OFData dataWithItems: "\x04\x89" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated octet string", + OFTruncatedDataException, + [[OFData dataWithItems: "\x04\x01" + count: 2] objectByParsingASN1DER]) + + /* Null */ + TEST(@"Parsing of null", + [[OFData dataWithItems: "\x05\x00" + count: 2].objectByParsingASN1DER + isEqual: [OFNull null]]) + + EXPECT_EXCEPTION(@"Detection of invalid null", + OFInvalidFormatException, + [[OFData dataWithItems: "\x05\x01\x00" + count: 3] objectByParsingASN1DER]) + + /* Object Identifier */ + TEST(@"Parsing of Object Identifier", + (array = [[OFData dataWithItems: "\x06\x01\x27" + count: 3].objectByParsingASN1DER + subidentifiers]) && array.count == 2 && + [[array objectAtIndex: 0] unsignedLongLongValue] == 0 && + [[array objectAtIndex: 1] unsignedLongLongValue] == 39 && + (array = [[OFData dataWithItems: "\x06\x01\x4F" + count: 3].objectByParsingASN1DER + subidentifiers]) && array.count == 2 && + [[array objectAtIndex: 0] unsignedLongLongValue] == 1 && + [[array objectAtIndex: 1] unsignedLongLongValue] == 39 && + (array = [[OFData dataWithItems: "\x06\x02\x88\x37" + count: 4].objectByParsingASN1DER + subidentifiers]) && array.count == 2 && + [[array objectAtIndex: 0] unsignedLongLongValue] == 2 && + [[array objectAtIndex: 1] unsignedLongLongValue] == 999 && + (array = [[OFData dataWithItems: "\x06\x09\x2A\x86\x48\x86\xF7\x0D" + "\x01\x01\x0B" + count: 11].objectByParsingASN1DER + subidentifiers]) && array.count == 7 && + [[array objectAtIndex: 0] unsignedLongLongValue] == 1 && + [[array objectAtIndex: 1] unsignedLongLongValue] == 2 && + [[array objectAtIndex: 2] unsignedLongLongValue] == 840 && + [[array objectAtIndex: 3] unsignedLongLongValue] == 113549 && + [[array objectAtIndex: 4] unsignedLongLongValue] == 1 && + [[array objectAtIndex: 5] unsignedLongLongValue] == 1 && + [[array objectAtIndex: 6] unsignedLongLongValue] == 11) + + EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #1", + OFInvalidFormatException, + [[OFData dataWithItems: "\x06\x01\x81" + count: 3] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #2", + OFInvalidFormatException, + [[OFData dataWithItems: "\x06\x02\x80\x01" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range Object Identifier", + OFOutOfRangeException, + [[OFData dataWithItems: "\x06\x0A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" + "\xFF\x7F" + count: 12] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated Object Identifier", + OFTruncatedDataException, + [[OFData dataWithItems: "\x06\x02\x00" + count: 3] objectByParsingASN1DER]) + + /* Enumerated */ + TEST(@"Parsing of enumerated", + [[OFData dataWithItems: "\x0A\x00" + count: 2].objectByParsingASN1DER longLongValue] == + 0 && + [[OFData dataWithItems: "\x0A\x01\x01" + count: 3].objectByParsingASN1DER longLongValue] == + 1 && + [[OFData dataWithItems: "\x0A\x02\x01\x04" + count: 4].objectByParsingASN1DER longLongValue] == + 260 && + [[OFData dataWithItems: "\x0A\x01\xFF" + count: 3].objectByParsingASN1DER longLongValue] == + -1 && + [[OFData dataWithItems: "\x0A\x03\xFF\x00\x00" + count: 5].objectByParsingASN1DER longLongValue] == + -65536 && + (unsigned long long)[[OFData dataWithItems: "\x0A\x09\x00\xFF\xFF" + "\xFF\xFF\xFF\xFF\xFF" + "\xFF" + count: 11] + .objectByParsingASN1DER longLongValue] == ULLONG_MAX) + + EXPECT_EXCEPTION(@"Detection of invalid enumerated #1", + OFInvalidFormatException, + [[OFData dataWithItems: "\x0A\x02\x00\x00" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid enumerated #2", + OFInvalidFormatException, + [[OFData dataWithItems: "\x0A\x02\x00\x7F" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid enumerated #3", + OFInvalidFormatException, + [[OFData dataWithItems: "\x0A\x02\xFF\x80" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range enumerated", + OFOutOfRangeException, + [[OFData dataWithItems: "\x0A\x09\x01" + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated enumerated", + OFTruncatedDataException, + [[OFData dataWithItems: "\x0A\x02\x00" + count: 3] objectByParsingASN1DER]) + + /* UTF-8 string */ + TEST(@"Parsing of UTF-8 string", + [[[OFData dataWithItems: "\x0C\x0EHällo Wörld!" + count: 16].objectByParsingASN1DER UTF8StringValue] + isEqual: @"Hällo Wörld!"] && + [[[OFData dataWithItems: "\x0C\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxx" + count: 131].objectByParsingASN1DER + UTF8StringValue] isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + @"xxxxxxxxxxx"]) + + EXPECT_EXCEPTION(@"Detection of out of range UTF-8 string", + OFOutOfRangeException, + [[OFData dataWithItems: "\x0C\x89" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated UTF-8 string", + OFTruncatedDataException, + [[OFData dataWithItems: "\x0C\x01" + count: 2] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated length", + OFTruncatedDataException, + [[OFData dataWithItems: "\x0C\x83\x01\x01" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #1", + OFInvalidFormatException, + [[OFData dataWithItems: "\x0C\x81\x7F" + count: 3] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #2", + OFInvalidFormatException, + [[OFData dataWithItems: "\x0C\x82\x00\x80xxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxx" + count: 132] objectByParsingASN1DER]) + + /* Sequence */ + TEST(@"Parsing of sequence", + (array = [OFData dataWithItems: "\x30\x00" + count: 2].objectByParsingASN1DER) && + [array isKindOfClass: [OFArray class]] && array.count == 0 && + (array = [OFData dataWithItems: "\x30\x09\x02\x01\x7B\x0C\x04Test" + count: 11].objectByParsingASN1DER) && + [array isKindOfClass: [OFArray class]] && array.count == 2 && + [[array objectAtIndex: 0] longLongValue] == 123 && + [[[array objectAtIndex: 1] stringValue] isEqual: @"Test"]) + + EXPECT_EXCEPTION(@"Detection of truncated sequence #1", + OFTruncatedDataException, + [[OFData dataWithItems: "\x30\x01" + count: 2] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated sequence #2", + OFTruncatedDataException, + [[OFData dataWithItems: "\x30\x04\x02\x01\x01\x00\x00" + count: 7] objectByParsingASN1DER]) + + /* Set */ + TEST(@"Parsing of set", + (set = [OFData dataWithItems: "\x31\x00" + count: 2].objectByParsingASN1DER) && + [set isKindOfClass: [OFSet class]] && set.count == 0 && + (set = [OFData dataWithItems: "\x31\x09\x02\x01\x7B\x0C\x04Test" + count: 11].objectByParsingASN1DER) && + [set isKindOfClass: [OFSet class]] && set.count == 2 && + (enumerator = [set objectEnumerator]) && + [[enumerator nextObject] longLongValue] == 123 && + [[[enumerator nextObject] stringValue] isEqual: @"Test"]) + + EXPECT_EXCEPTION(@"Detection of invalid set", + OFInvalidFormatException, + [[OFData dataWithItems: "\x31\x06\x02\x01\x02\x02\x01\x01" + count: 8] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated set #1", + OFTruncatedDataException, + [[OFData dataWithItems: "\x31\x01" + count: 2] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated set #2", + OFTruncatedDataException, + [[OFData dataWithItems: "\x31\x04\x02\x01\x01\x00\x00" + count: 7] objectByParsingASN1DER]) + + /* NumericString */ + TEST(@"Parsing of NumericString", + [[[OFData dataWithItems: "\x12\x0B" "12345 67890" + count: 13].objectByParsingASN1DER + numericStringValue] isEqual: @"12345 67890"] && + [[[OFData dataWithItems: "\x12\x81\x80" "00000000000000000000000000" + "00000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000" + "00000000000000000000" + count: 131].objectByParsingASN1DER + numericStringValue] isEqual: @"000000000000000000000000000000000000" + @"000000000000000000000000000000000000" + @"000000000000000000000000000000000000" + @"00000000000000000000"]) + + EXPECT_EXCEPTION(@"Detection of invalid NumericString", + OFInvalidEncodingException, + [[OFData dataWithItems: "\x12\x02." + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range NumericString", + OFOutOfRangeException, + [[OFData dataWithItems: "\x12\x89" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated NumericString", + OFTruncatedDataException, + [[OFData dataWithItems: "\x12\x01" + count: 2] objectByParsingASN1DER]) + + /* PrintableString */ + TEST(@"Parsing of PrintableString", + [[[OFData dataWithItems: "\x13\x0CHello World." + count: 14].objectByParsingASN1DER + printableStringValue] isEqual: @"Hello World."] && + [[[OFData dataWithItems: "\x13\x81\x80 '()+,-./:=?abcdefghijklmnopq" + "rstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()+," + "-./:=?abcdefghijklmnopqrstuvwxyzABCDEFGHI" + "JKLMNOPQRSTUVWXYZ" + count: 131].objectByParsingASN1DER + printableStringValue] isEqual: @" '()+,-./:=?abcdefghijklmnopqrstuv" + @"wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()" + @"+,-./:=?abcdefghijklmnopqrstuvwxyz" + @"ABCDEFGHIJKLMNOPQRSTUVWXYZ"]) + + EXPECT_EXCEPTION(@"Detection of invalid PrintableString", + OFInvalidEncodingException, + [[OFData dataWithItems: "\x13\x02;" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range PrintableString", + OFOutOfRangeException, + [[OFData dataWithItems: "\x13\x89" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated PrintableString", + OFTruncatedDataException, + [[OFData dataWithItems: "\x13\x01" + count: 2] objectByParsingASN1DER]) + + /* IA5String */ + TEST(@"Parsing of IA5String", + [[[OFData dataWithItems: "\x16\x0CHello World!" + count: 14].objectByParsingASN1DER IA5StringValue] + isEqual: @"Hello World!"] && + [[[OFData dataWithItems: "\x16\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxx" + count: 131].objectByParsingASN1DER IA5StringValue] + isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + @"xxxxxxxxxxxxxxxx"]) + + EXPECT_EXCEPTION(@"Detection of invalid IA5String", + OFInvalidEncodingException, + [[OFData dataWithItems: "\x16\x02ä" + count: 4] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of out of range IA5String", + OFOutOfRangeException, + [[OFData dataWithItems: "\x16\x89" + "\x01\x01\x01\x01\x01\x01\x01\x01\x01" + count: 11] objectByParsingASN1DER]) + + EXPECT_EXCEPTION(@"Detection of truncated IA5String", + OFTruncatedDataException, + [[OFData dataWithItems: "\x16\x01" + count: 2] objectByParsingASN1DER]) + + objc_autoreleasePoolPop(pool); +} +@end DELETED tests/OFASN1DERValueTests.m Index: tests/OFASN1DERValueTests.m ================================================================== --- tests/OFASN1DERValueTests.m +++ tests/OFASN1DERValueTests.m @@ -1,441 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018, 2019, 2020 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "TestsAppDelegate.h" - -static OFString *module = @"OFData+ASN1DERValue"; - -@implementation TestsAppDelegate (OFASN1DERValueTests) -- (void)ASN1DERValueTests -{ - void *pool = objc_autoreleasePoolPush(); - OFASN1BitString *bitString; - OFArray *array; - OFSet *set; - OFEnumerator *enumerator; - - /* Boolean */ - TEST(@"Parsing of boolean", - ![[[OFData dataWithItems: "\x01\x01\x00" - count: 3] ASN1DERValue] booleanValue] && - [[[OFData dataWithItems: "\x01\x01\xFF" - count: 3] ASN1DERValue] booleanValue]) - - EXPECT_EXCEPTION(@"Detection of invalid boolean #1", - OFInvalidFormatException, [[OFData dataWithItems: "\x01\x01\x01" - count: 3] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid boolean #2", - OFInvalidFormatException, [[OFData dataWithItems: "\x01\x02\x00\x00" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid boolean #3", - OFInvalidFormatException, [[OFData dataWithItems: "\x01\x00" - count: 2] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated boolean", - OFTruncatedDataException, [[OFData dataWithItems: "\x01\x01" - count: 2] ASN1DERValue]) - - /* Integer */ - TEST(@"Parsing of integer", - [[[OFData dataWithItems: "\x02\x00" - count: 2] ASN1DERValue] longLongValue] == 0 && - [[[OFData dataWithItems: "\x02\x01\x01" - count: 3] ASN1DERValue] longLongValue] == 1 && - [[[OFData dataWithItems: "\x02\x02\x01\x04" - count: 4] ASN1DERValue] longLongValue] == 260 && - [[[OFData dataWithItems: "\x02\x01\xFF" - count: 3] ASN1DERValue] longLongValue] == -1 && - [[[OFData dataWithItems: "\x02\x03\xFF\x00\x00" - count: 5] ASN1DERValue] longLongValue] == - -65536 && - (unsigned long long)[[[OFData dataWithItems: "\x02\x09\x00\xFF\xFF" - "\xFF\xFF\xFF\xFF\xFF" - "\xFF" - count: 11] ASN1DERValue] - longLongValue] == ULLONG_MAX) - - EXPECT_EXCEPTION(@"Detection of invalid integer #1", - OFInvalidFormatException, [[OFData dataWithItems: "\x02\x02\x00\x00" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid integer #2", - OFInvalidFormatException, [[OFData dataWithItems: "\x02\x02\x00\x7F" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid integer #3", - OFInvalidFormatException, [[OFData dataWithItems: "\x02\x02\xFF\x80" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range integer", - OFOutOfRangeException, - [[OFData dataWithItems: "\x02\x09\x01" - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated integer", - OFTruncatedDataException, [[OFData dataWithItems: "\x02\x02\x00" - count: 3] ASN1DERValue]) - - /* Bit string */ - TEST(@"Parsing of bit string", - (bitString = [[OFData dataWithItems: "\x03\x01\x00" - count: 3] ASN1DERValue]) && - [bitString.bitStringValue isEqual: [OFData dataWithItems: "" - count: 0]] && - bitString.bitStringLength == 0 && - (bitString = [[OFData dataWithItems: "\x03\x0D\x01Hello World\x80" - count: 15] ASN1DERValue]) && - [bitString.bitStringValue - isEqual: [OFData dataWithItems: "Hello World\x80" - count: 12]] && - bitString.bitStringLength == 95 && - (bitString = [[OFData dataWithItems: "\x03\x81\x80\x00xxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxx" - count: 131] ASN1DERValue]) && - [bitString.bitStringValue - isEqual: [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxx" - count: 127]] && - bitString.bitStringLength == 127 * 8) - - EXPECT_EXCEPTION(@"Detection of invalid bit string #1", - OFInvalidFormatException, [[OFData dataWithItems: "\x03\x00" - count: 2] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid bit string #2", - OFInvalidFormatException, [[OFData dataWithItems: "\x03\x01\x01" - count: 3] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range bit string", - OFOutOfRangeException, - [[OFData dataWithItems: "\x03\x89" - "\x01\x01\x01\x01\x01\x01\x01\x01\x01" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated bit string", - OFTruncatedDataException, [[OFData dataWithItems: "\x03\x01" - count: 2] ASN1DERValue]) - - /* Octet string */ - TEST(@"Parsing of octet string", - [[[[OFData dataWithItems: "\x04\x0CHello World!" - count: 14] ASN1DERValue] octetStringValue] - isEqual: [OFData dataWithItems: "Hello World!" - count: 12]] && - [[[[OFData dataWithItems: "\x04\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxx" - count: 131] ASN1DERValue] octetStringValue] - isEqual: [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxx" - count: 128]]) - - EXPECT_EXCEPTION(@"Detection of out of range octet string", - OFOutOfRangeException, - [[OFData dataWithItems: "\x04\x89" - "\x01\x01\x01\x01\x01\x01\x01\x01\x01" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated octet string", - OFTruncatedDataException, [[OFData dataWithItems: "\x04\x01" - count: 2] ASN1DERValue]) - - /* Null */ - TEST(@"Parsing of null", - [[[OFData dataWithItems: "\x05\x00" - count: 2] ASN1DERValue] isEqual: [OFNull null]]) - - EXPECT_EXCEPTION(@"Detection of invalid null", - OFInvalidFormatException, [[OFData dataWithItems: "\x05\x01\x00" - count: 3] ASN1DERValue]) - - /* Object Identifier */ - TEST(@"Parsing of Object Identifier", - (array = [[[OFData dataWithItems: "\x06\x01\x27" - count: 3] ASN1DERValue] - subidentifiers]) && array.count == 2 && - [[array objectAtIndex: 0] unsignedLongLongValue] == 0 && - [[array objectAtIndex: 1] unsignedLongLongValue] == 39 && - (array = [[[OFData dataWithItems: "\x06\x01\x4F" - count: 3] ASN1DERValue] - subidentifiers]) && array.count == 2 && - [[array objectAtIndex: 0] unsignedLongLongValue] == 1 && - [[array objectAtIndex: 1] unsignedLongLongValue] == 39 && - (array = [[[OFData dataWithItems: "\x06\x02\x88\x37" - count: 4] ASN1DERValue] - subidentifiers]) && array.count == 2 && - [[array objectAtIndex: 0] unsignedLongLongValue] == 2 && - [[array objectAtIndex: 1] unsignedLongLongValue] == 999 && - (array = [[[OFData dataWithItems: "\x06\x09\x2A\x86\x48\x86\xF7\x0D" - "\x01\x01\x0B" - count: 11] ASN1DERValue] - subidentifiers]) && array.count == 7 && - [[array objectAtIndex: 0] unsignedLongLongValue] == 1 && - [[array objectAtIndex: 1] unsignedLongLongValue] == 2 && - [[array objectAtIndex: 2] unsignedLongLongValue] == 840 && - [[array objectAtIndex: 3] unsignedLongLongValue] == 113549 && - [[array objectAtIndex: 4] unsignedLongLongValue] == 1 && - [[array objectAtIndex: 5] unsignedLongLongValue] == 1 && - [[array objectAtIndex: 6] unsignedLongLongValue] == 11) - - EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #1", - OFInvalidFormatException, [[OFData dataWithItems: "\x06\x01\x81" - count: 3] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #2", - OFInvalidFormatException, [[OFData dataWithItems: "\x06\x02\x80\x01" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range Object Identifier", - OFOutOfRangeException, - [[OFData dataWithItems: "\x06\x0A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - "\xFF\x7F" - count: 12] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated Object Identifier", - OFTruncatedDataException, [[OFData dataWithItems: "\x06\x02\x00" - count: 3] ASN1DERValue]) - - /* Enumerated */ - TEST(@"Parsing of enumerated", - [[[OFData dataWithItems: "\x0A\x00" - count: 2] ASN1DERValue] longLongValue] == 0 && - [[[OFData dataWithItems: "\x0A\x01\x01" - count: 3] ASN1DERValue] longLongValue] == 1 && - [[[OFData dataWithItems: "\x0A\x02\x01\x04" - count: 4] ASN1DERValue] longLongValue] == 260 && - [[[OFData dataWithItems: "\x0A\x01\xFF" - count: 3] ASN1DERValue] longLongValue] == -1 && - [[[OFData dataWithItems: "\x0A\x03\xFF\x00\x00" - count: 5] ASN1DERValue] longLongValue] == - -65536 && - (unsigned long long)[[[OFData dataWithItems: "\x0A\x09\x00\xFF\xFF" - "\xFF\xFF\xFF\xFF\xFF" - "\xFF" - count: 11] ASN1DERValue] - longLongValue] == ULLONG_MAX) - - EXPECT_EXCEPTION(@"Detection of invalid enumerated #1", - OFInvalidFormatException, [[OFData dataWithItems: "\x0A\x02\x00\x00" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid enumerated #2", - OFInvalidFormatException, [[OFData dataWithItems: "\x0A\x02\x00\x7F" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid enumerated #3", - OFInvalidFormatException, [[OFData dataWithItems: "\x0A\x02\xFF\x80" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range enumerated", - OFOutOfRangeException, - [[OFData dataWithItems: "\x0A\x09\x01" - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated enumerated", - OFTruncatedDataException, [[OFData dataWithItems: "\x0A\x02\x00" - count: 3] ASN1DERValue]) - - /* UTF-8 string */ - TEST(@"Parsing of UTF-8 string", - [[[[OFData dataWithItems: "\x0C\x0EHällo Wörld!" - count: 16] ASN1DERValue] UTF8StringValue] - isEqual: @"Hällo Wörld!"] && - [[[[OFData dataWithItems: "\x0C\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxx" - count: 131] ASN1DERValue] UTF8StringValue] - isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - @"xxxxxxxxxxxxxxxx"]) - - EXPECT_EXCEPTION(@"Detection of out of range UTF-8 string", - OFOutOfRangeException, - [[OFData dataWithItems: "\x0C\x89" - "\x01\x01\x01\x01\x01\x01\x01\x01\x01" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated UTF-8 string", - OFTruncatedDataException, [[OFData dataWithItems: "\x0C\x01" - count: 2] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated length", - OFTruncatedDataException, [[OFData dataWithItems: "\x0C\x83\x01\x01" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #1", - OFInvalidFormatException, [[OFData dataWithItems: "\x0C\x81\x7F" - count: 3] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #2", - OFInvalidFormatException, - [[OFData dataWithItems: "\x0C\x82\x00\x80xxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxx" - count: 132] ASN1DERValue]) - - /* Sequence */ - TEST(@"Parsing of sequence", - (array = [[OFData dataWithItems: "\x30\x00" - count: 2] ASN1DERValue]) && - [array isKindOfClass: [OFArray class]] && array.count == 0 && - (array = [[OFData dataWithItems: "\x30\x09\x02\x01\x7B\x0C\x04Test" - count: 11] ASN1DERValue]) && - [array isKindOfClass: [OFArray class]] && array.count == 2 && - [[array objectAtIndex: 0] longLongValue] == 123 && - [[[array objectAtIndex: 1] stringValue] isEqual: @"Test"]) - - EXPECT_EXCEPTION(@"Detection of truncated sequence #1", - OFTruncatedDataException, [[OFData dataWithItems: "\x30\x01" - count: 2] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated sequence #2", - OFTruncatedDataException, - [[OFData dataWithItems: "\x30\x04\x02\x01\x01\x00\x00" - count: 7] ASN1DERValue]) - - /* Set */ - TEST(@"Parsing of set", - (set = [[OFData dataWithItems: "\x31\x00" - count: 2] ASN1DERValue]) && - [set isKindOfClass: [OFSet class]] && set.count == 0 && - (set = [[OFData dataWithItems: "\x31\x09\x02\x01\x7B\x0C\x04Test" - count: 11] ASN1DERValue]) && - [set isKindOfClass: [OFSet class]] && set.count == 2 && - (enumerator = [set objectEnumerator]) && - [[enumerator nextObject] longLongValue] == 123 && - [[[enumerator nextObject] stringValue] isEqual: @"Test"]) - - EXPECT_EXCEPTION(@"Detection of invalid set", - OFInvalidFormatException, - [[OFData dataWithItems: "\x31\x06\x02\x01\x02\x02\x01\x01" - count: 8] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated set #1", - OFTruncatedDataException, [[OFData dataWithItems: "\x31\x01" - count: 2] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated set #2", - OFTruncatedDataException, - [[OFData dataWithItems: "\x31\x04\x02\x01\x01\x00\x00" - count: 7] ASN1DERValue]) - - /* NumericString */ - TEST(@"Parsing of NumericString", - [[[[OFData dataWithItems: "\x12\x0B" "12345 67890" - count: 13] ASN1DERValue] numericStringValue] - isEqual: @"12345 67890"] && - [[[[OFData dataWithItems: "\x12\x81\x80" "0000000000000000000000000" - "0000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000" - "00000000000000000000000" - count: 131] ASN1DERValue] numericStringValue] - isEqual: @"00000000000000000000000000000000000000000000000000000000" - @"00000000000000000000000000000000000000000000000000000000" - @"0000000000000000"]) - - EXPECT_EXCEPTION(@"Detection of invalid NumericString", - OFInvalidEncodingException, - [[OFData dataWithItems: "\x12\x02." - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range NumericString", - OFOutOfRangeException, - [[OFData dataWithItems: "\x12\x89" - "\x01\x01\x01\x01\x01\x01\x01\x01\x01" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated NumericString", - OFTruncatedDataException, [[OFData dataWithItems: "\x12\x01" - count: 2] ASN1DERValue]) - - /* PrintableString */ - TEST(@"Parsing of PrintableString", - [[[[OFData dataWithItems: "\x13\x0CHello World." - count: 14] ASN1DERValue] printableStringValue] - isEqual: @"Hello World."] && - [[[[OFData dataWithItems: "\x13\x81\x80 '()+,-./:=?abcdefghijklmnop" - "qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()" - "+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEF" - "GHIJKLMNOPQRSTUVWXYZ" - count: 131] ASN1DERValue] printableStringValue] - isEqual: @" '()+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR" - @"STUVWXYZ '()+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEFGHIJ" - @"KLMNOPQRSTUVWXYZ"]) - - EXPECT_EXCEPTION(@"Detection of invalid PrintableString", - OFInvalidEncodingException, - [[OFData dataWithItems: "\x13\x02;" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range PrintableString", - OFOutOfRangeException, - [[OFData dataWithItems: "\x13\x89" - "\x01\x01\x01\x01\x01\x01\x01\x01\x01" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated PrintableString", - OFTruncatedDataException, [[OFData dataWithItems: "\x13\x01" - count: 2] ASN1DERValue]) - - /* IA5String */ - TEST(@"Parsing of IA5String", - [[[[OFData dataWithItems: "\x16\x0CHello World!" - count: 14] ASN1DERValue] IA5StringValue] - isEqual: @"Hello World!"] && - [[[[OFData dataWithItems: "\x16\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - "xxxxxxxxxxxxxxxxxxxx" - count: 131] ASN1DERValue] IA5StringValue] - isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - @"xxxxxxxxxxxxxxxx"]) - - EXPECT_EXCEPTION(@"Detection of invalid IA5String", - OFInvalidEncodingException, - [[OFData dataWithItems: "\x16\x02ä" - count: 4] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of out of range IA5String", - OFOutOfRangeException, - [[OFData dataWithItems: "\x16\x89" - "\x01\x01\x01\x01\x01\x01\x01\x01\x01" - count: 11] ASN1DERValue]) - - EXPECT_EXCEPTION(@"Detection of truncated IA5String", - OFTruncatedDataException, [[OFData dataWithItems: "\x16\x01" - count: 2] ASN1DERValue]) - - objc_autoreleasePoolPop(pool); -} -@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -68,12 +68,12 @@ inModule: (OFString *)module; - (void)outputFailure: (OFString *)test inModule: (OFString *)module; @end -@interface TestsAppDelegate (OFASN1DERValueTests) -- (void)ASN1DERValueTests; +@interface TestsAppDelegate (OFASN1DERParsingTests) +- (void)ASN1DERParsingTests; @end @interface TestsAppDelegate (OFASN1DERRepresentationTests) - (void)ASN1DERRepresentationTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -378,11 +378,11 @@ #ifdef OF_HAVE_FILES [self serializationTests]; #endif [self JSONTests]; [self propertyListTests]; - [self ASN1DERValueTests]; + [self ASN1DERParsingTests]; [self ASN1DERRepresentationTests]; #if defined(OF_HAVE_PLUGINS) [self pluginTests]; #endif #ifdef OF_WINDOWS