/*
* Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
*
* 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] boolValue] &&
[[[OFData dataWithItems: "\x01\x01\xFF"
count: 3] objectByParsingASN1DER] boolValue])
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\x00xxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
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\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxx"
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\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxx"
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" "0000000000000000000000000"
"0000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000"
"00000000000000000000000"
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 '()+,-./:=?abcdefghijklmnop"
"qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()"
"+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEF"
"GHIJKLMNOPQRSTUVWXYZ"
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\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxx"
count: 131] objectByParsingASN1DER]
IA5StringValue] isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@"xxxxxxxx"])
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