/*
* Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
*
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3.0 only,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3.0 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3.0 along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
#import "OFData.h"
OF_ASSUME_NONNULL_BEGIN
/**
* @class OFSecureData OFSecureData.h ObjFW/ObjFW.h
*
* @brief A class for storing arbitrary data in secure (non-swappable) memory,
* securely wiping it when it gets deallocated.
*
* @warning Non-swappable memory might be unavailable, in which case this falls
* back to swappable memory, but still wipes the data when it gets
* deallocated. Check the @ref allowsSwappableMemory property to see
* whether a particular OFSecureData might be allocated in swappable
* memory.
*/
OF_SUBCLASSING_RESTRICTED
@interface OFSecureData: OFData
{
unsigned char *_Nullable _items;
size_t _count, _itemSize;
bool _freeWhenDone, _allowsSwappableMemory;
void *_page;
}
/**
* @brief Whether the data may be stored in swappable memory.
*/
@property (readonly, nonatomic) bool allowsSwappableMemory;
/**
* @brief All items of the OFSecureData as a C array.
*
* Modifying the returned array directly is allowed and will change the contents
* of the data.
*/
@property (readonly, nonatomic) void *mutableItems OF_RETURNS_INNER_POINTER;
/**
* @brief Preallocates the specified number of bytes for unswappable memory.
*
* This is useful to allocate unswappable memory before enabling a sandbox that
* does not allow it anymore.
*
* @note This may only be called once per thread!
* @note Preallocated unswappable memory is only available for data that is
* smaller than a single page!
*
* @param size The number of bytes of unswappable memory to preallocate
*/
+ (void)preallocateUnswappableMemoryWithSize: (size_t)size;
/**
* @brief Creates a new, autoreleased OFSecureData with `count` items of item
* size 1, all set to zero.
*
* @param count The number of zero items the OFSecureData should contain
* @param allowsSwappableMemory Whether the data may be stored in swappable
* memory
* @return A new, autoreleased OFSecureData
*/
+ (instancetype)dataWithCount: (size_t)count
allowsSwappableMemory: (bool)allowsSwappableMemory;
/**
* @brief Creates a new, autoreleased OFSecureData with `count` items of the
* specified item size, all set to zero.
*
* @param count The number of zero items the OFSecureData should contain
* @param itemSize The size of a single item in the OFSecureData in bytes
* @param allowsSwappableMemory Whether the data may be stored in swappable
* memory
* @return A new, autoreleased OFSecureData
*/
+ (instancetype)dataWithCount: (size_t)count
itemSize: (size_t)itemSize
allowsSwappableMemory: (bool)allowsSwappableMemory;
+ (instancetype)dataWithItems: (const void *)items
count: (size_t)count OF_UNAVAILABLE;
+ (instancetype)dataWithItems: (const void *)items
count: (size_t)count
itemSize: (size_t)itemSize OF_UNAVAILABLE;
+ (instancetype)dataWithItemsNoCopy: (void *)items
count: (size_t)count
freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
+ (instancetype)dataWithItemsNoCopy: (void *)items
count: (size_t)count
itemSize: (size_t)itemSize
freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE;
+ (instancetype)dataWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
+ (instancetype)dataWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;
/**
* @brief Initializes an already allocated OFSecureData with `count` items of
* item size 1, all set to zero.
*
* @param count The number of zero items the OFSecureData should contain
* @param allowsSwappableMemory Whether the data may be stored in swappable
* memory
* @return An initialized OFSecureData
*/
- (instancetype)initWithCount: (size_t)count
allowsSwappableMemory: (bool)allowsSwappableMemory;
/**
* @brief Initializes an already allocated OFSecureData with `count` items of
* the specified item size, all set to zero.
*
* @param itemSize The size of a single item in the OFSecureData in bytes
* @param count The number of zero items the OFSecureData should contain
* @param allowsSwappableMemory Whether the data may be stored in swappable
* memory
* @return An initialized OFSecureData
*/
- (instancetype)initWithCount: (size_t)count
itemSize: (size_t)itemSize
allowsSwappableMemory: (bool)allowsSwappableMemory
OF_DESIGNATED_INITIALIZER;
- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithItemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
count: (size_t)count OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
count: (size_t)count
itemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
count: (size_t)count
freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
count: (size_t)count
itemSize: (size_t)itemSize
freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE;
- (instancetype)initWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
- (instancetype)initWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;
/**
* @brief Returns a specific item of the OFSecureData.
*
* Modifying the returned item directly is allowed and will change the contents
* of the data array.
*
* @param index The number of the item to return
* @return The specified item of the OFSecureData
*/
- (void *)mutableItemAtIndex: (size_t)index OF_RETURNS_INNER_POINTER;
/**
* @brief Checks the OFSecureData for equality to another object.
*
* If the specified object is a subclass of @ref OFData, the comparison is
* performed in constant time.
*
* @param object The object which should be tested for equality
* @return A boolean whether the OFSecureData is equal to the specified object
*/
- (bool)isEqual: (nullable id)object;
/**
* @brief Zeroes the data.
*/
- (void)zero;
- (OFString *)stringRepresentation OF_UNAVAILABLE;
- (OFString *)stringByBase64Encoding OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (void)writeToIRI: (OFIRI *)IRI OF_UNAVAILABLE;
- (OFData *)messagePackRepresentation OF_UNAVAILABLE;
@end
OF_ASSUME_NONNULL_END