Index: src/OFASN1Value.h ================================================================== --- src/OFASN1Value.h +++ src/OFASN1Value.h @@ -53,10 +53,12 @@ OF_ASN1_TAG_NUMBER_NULL = 0x05, /*! UTF-8 string */ OF_ASN1_TAG_NUMBER_UTF8_STRING = 0x0C, /*! Sequence */ OF_ASN1_TAG_NUMBER_SEQUENCE = 0x10, + /*! Set */ + OF_ASN1_TAG_NUMBER_SET = 0x11, /*! NumericString */ OF_ASN1_TAG_NUMBER_NUMERIC_STRING = 0x12, /*! PrintableString */ OF_ASN1_TAG_NUMBER_PRINTABLE_STRING = 0x13, /*! IA5String */ Index: src/OFData+ASN1DERValue.m ================================================================== --- src/OFData+ASN1DERValue.m +++ src/OFData+ASN1DERValue.m @@ -27,10 +27,11 @@ #import "OFASN1OctetString.h" #import "OFASN1PrintableString.h" #import "OFASN1UTF8String.h" #import "OFASN1Value.h" #import "OFArray.h" +#import "OFSet.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" @@ -62,10 +63,48 @@ 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; } @@ -142,10 +181,16 @@ 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]; Index: tests/OFASN1DERValueTests.m ================================================================== --- tests/OFASN1DERValueTests.m +++ tests/OFASN1DERValueTests.m @@ -26,10 +26,11 @@ #import "OFASN1NumericString.h" #import "OFASN1OctetString.h" #import "OFASN1PrintableString.h" #import "OFASN1UTF8String.h" #import "OFArray.h" +#import "OFSet.h" #import "OFString.h" #import "OFAutoreleasePool.h" #import "TestsAppDelegate.h" @@ -44,10 +45,12 @@ - (void)ASN1DERValueTests { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFASN1BitString *bitString; OFArray *array; + OFSet *set; + OFEnumerator *enumerator; /* Boolean */ TEST(@"Parsing of boolean", ![[[OFData dataWithItems: "\x01\x01\x00" count: 3] ASN1DERValue] booleanValue] && @@ -240,19 +243,45 @@ count: 11] ASN1DERValue]) && [array isKindOfClass: [OFArray class]] && [array count] == 2 && [[array objectAtIndex: 0] integerValue] == 123 && [[[array objectAtIndex: 1] stringValue] isEqual: @"Test"]) - EXPECT_EXCEPTION(@"Parsing of truncated sequence #1", + EXPECT_EXCEPTION(@"Detection of truncated sequence #1", OFTruncatedDataException, [[OFData dataWithItems: "\x30\x01" count: 2] ASN1DERValue]) - EXPECT_EXCEPTION(@"Parsing of truncated sequence #2", + 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] integerValue] == 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"] &&