Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -10,11 +10,10 @@ LIB_MAJOR = ${OBJFW_LIB_MAJOR} LIB_MINOR = ${OBJFW_LIB_MINOR} LIB_PATCH = ${OBJFW_LIB_PATCH} SRCS = OFASN1BitString.m \ - OFASN1Boolean.m \ OFASN1Enumerated.m \ OFASN1IA5String.m \ OFASN1Integer.m \ OFASN1NumericString.m \ OFASN1ObjectIdentifier.m \ DELETED src/OFASN1Boolean.h Index: src/OFASN1Boolean.h ================================================================== --- src/OFASN1Boolean.h +++ src/OFASN1Boolean.h @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2008-2024 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 "OFObject.h" -#import "OFASN1DERRepresentation.h" -#import "OFASN1Value.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @brief An ASN.1 Boolean. - */ -OF_SUBCLASSING_RESTRICTED -@interface OFASN1Boolean: OFObject -{ - bool _boolValue; -} - -/** - * @brief The value of the Boolean. - */ -@property (readonly, nonatomic) bool boolValue; - -/** - * @brief Creates an ASN.1 Boolean with the specified Boolean value. - * - * @param bool_ The value of the Boolean - * @return A new, autoreleased OFASN1Boolean - */ -+ (instancetype)booleanWithBool: (bool)bool_; - -- (instancetype)init OF_UNAVAILABLE; - -/** - * @brief Initializes an already allocated ASN.1 Boolean with the specified - * Boolean value. - * - * @param bool_ The value of the Boolean - * @return An initialized OFASN1Boolean - */ -- (instancetype)initWithBool: (bool)bool_ OF_DESIGNATED_INITIALIZER; - -/** - * @brief Initializes an already allocated ASN.1 Boolean with the specified - * arguments. - * - * @param tagClass The tag class of the value's type - * @param tagNumber The tag number of the value's type - * @param constructed Whether the value if of a constructed type - * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized OFASN1Boolean - */ -- (instancetype)initWithTagClass: (OFASN1TagClass)tagClass - tagNumber: (OFASN1TagNumber)tagNumber - constructed: (bool)constructed - DEREncodedContents: (OFData *)DEREncodedContents; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFASN1Boolean.m Index: src/OFASN1Boolean.m ================================================================== --- src/OFASN1Boolean.m +++ src/OFASN1Boolean.m @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2008-2024 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 "OFASN1Boolean.h" -#import "OFData.h" -#import "OFString.h" - -#import "OFInvalidArgumentException.h" -#import "OFInvalidFormatException.h" - -@implementation OFASN1Boolean -@synthesize boolValue = _boolValue; - -+ (instancetype)booleanWithBool: (bool)bool_ -{ - return [[[self alloc] initWithBool: bool_] autorelease]; -} - -- (instancetype)initWithBool: (bool)bool_ -{ - self = [super init]; - - _boolValue = bool_; - - return self; -} - -- (instancetype)initWithTagClass: (OFASN1TagClass)tagClass - tagNumber: (OFASN1TagNumber)tagNumber - constructed: (bool)constructed - DEREncodedContents: (OFData *)DEREncodedContents -{ - unsigned char value; - - @try { - if (tagClass != OFASN1TagClassUniversal || - tagNumber != OFASN1TagNumberBoolean || constructed) - @throw [OFInvalidArgumentException exception]; - - if (DEREncodedContents.itemSize != 1 || - DEREncodedContents.count != 1) - @throw [OFInvalidFormatException exception]; - - value = *(unsigned char *)[DEREncodedContents itemAtIndex: 0]; - - if (value != 0 && value != 0xFF) - @throw [OFInvalidFormatException exception]; - } @catch (id e) { - [self release]; - @throw e; - } - - return [self initWithBool: !!value]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (OFData *)ASN1DERRepresentation -{ - char buffer[] = { - OFASN1TagNumberBoolean, - 1, - (_boolValue ? 0xFF : 0x00) - }; - - return [OFData dataWithItems: buffer count: sizeof(buffer)]; -} - -- (bool)isEqual: (id)object -{ - OFASN1Boolean *boolean; - - if (object == self) - return true; - - if (![object isKindOfClass: [OFASN1Boolean class]]) - return false; - - boolean = object; - - if (boolean->_boolValue != _boolValue) - return false; - - return true; -} - -- (unsigned long)hash -{ - return _boolValue; -} - -- (OFString *)description -{ - return (_boolValue - ? @"" - : @""); -} -@end Index: src/OFData+ASN1DERParsing.m ================================================================== --- src/OFData+ASN1DERParsing.m +++ src/OFData+ASN1DERParsing.m @@ -15,11 +15,10 @@ #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" @@ -27,10 +26,11 @@ #import "OFASN1PrintableString.h" #import "OFASN1UTF8String.h" #import "OFASN1Value.h" #import "OFArray.h" #import "OFNull.h" +#import "OFNumber.h" #import "OFSet.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" @@ -157,13 +157,26 @@ contents = [self subdataWithRange: OFMakeRange(bytesConsumed, contentsLength)]; bytesConsumed += contentsLength; switch (tag & ~tagConstructedMask) { - case OFASN1TagNumberBoolean: - valueClass = [OFASN1Boolean class]; - break; + case OFASN1TagNumberBoolean:; + unsigned char boolValue; + + if (tag & tagConstructedMask) + @throw [OFInvalidFormatException exception]; + + if (contents.count != 1) + @throw [OFInvalidFormatException exception]; + + boolValue = *(unsigned char *)[contents itemAtIndex: 0]; + + if (boolValue != 0 && boolValue != 0xFF) + @throw [OFInvalidFormatException exception]; + + *object = [OFNumber numberWithBool: boolValue]; + return bytesConsumed; case OFASN1TagNumberInteger: valueClass = [OFASN1Integer class]; break; case OFASN1TagNumberBitString: valueClass = [OFASN1BitString class]; Index: src/OFNumber.h ================================================================== --- src/OFNumber.h +++ src/OFNumber.h @@ -24,10 +24,11 @@ #ifdef OF_HAVE_SYS_TYPES_H # include #endif +#import "OFASN1DERRepresentation.h" #import "OFJSONRepresentation.h" #import "OFMessagePackRepresentation.h" #import "OFValue.h" OF_ASSUME_NONNULL_BEGIN @@ -37,12 +38,12 @@ /** * @class OFNumber OFNumber.h ObjFW/OFNumber.h * * @brief Provides a way to store a number in an object. */ -@interface OFNumber: OFValue +@interface OFNumber: OFValue /** * @brief The OFNumber as a `bool`. */ @property (readonly, nonatomic) bool boolValue; Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -23,10 +23,11 @@ #import "OFString.h" #import "OFTaggedPointerNumber.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" +#import "OFNotImplementedException.h" #import "OFOutOfRangeException.h" @interface OFNumber () - (OFString *) of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options @@ -708,10 +709,25 @@ return [OFString stringWithFormat: @"%llu", self.unsignedLongLongValue]; @throw [OFInvalidFormatException exception]; } + +- (OFData *)ASN1DERRepresentation +{ + if (self.objCType[0] == 'B' && self.objCType[1] == '\0') { + char buffer[] = { + OFASN1TagNumberBoolean, + 1, + (self.boolValue ? 0xFF : 0x00) + }; + + return [OFData dataWithItems: buffer count: sizeof(buffer)]; + } else + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; +} - (OFString *)JSONRepresentation { return [self of_JSONRepresentationWithOptions: 0 depth: 0]; } Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -143,11 +143,10 @@ #ifdef OF_WINDOWS # import "OFWindowsRegistryKey.h" #endif #import "OFASN1BitString.h" -#import "OFASN1Boolean.h" #import "OFASN1Enumerated.h" #import "OFASN1IA5String.h" #import "OFASN1Integer.h" #import "OFASN1NumericString.h" #import "OFASN1ObjectIdentifier.h" Index: tests/OFASN1DERRepresentationTests.m ================================================================== --- tests/OFASN1DERRepresentationTests.m +++ tests/OFASN1DERRepresentationTests.m @@ -38,15 +38,15 @@ (data = [OFData dataWithItems: "" count: 0]) && [[[OFASN1BitString bitStringWithBitString: data length: 0] ASN1DERRepresentation] isEqual: [OFData dataWithItems: "\x03\x01\x00" count: 3]]) - module = @"OFASN1Boolean"; - TEST(@"-[ASN1DERRepresentation]", - [[[OFASN1Boolean booleanWithBool: false] ASN1DERRepresentation] + module = @"OFNumber"; + TEST(@"-[ASN1DERRepresentation] for bool", + [[[OFNumber numberWithBool: false] ASN1DERRepresentation] isEqual: [OFData dataWithItems: "\x01\x01\x00" count: 3]] && - [[[OFASN1Boolean booleanWithBool: true] ASN1DERRepresentation] + [[[OFNumber numberWithBool: true] ASN1DERRepresentation] isEqual: [OFData dataWithItems: "\x01\x01\xFF" count: 3]]) module = @"OFNull"; TEST(@"-[OFASN1DERRepresentation]", [[[OFNull null] ASN1DERRepresentation] isEqual: