- Update Pod

This commit is contained in:
giuseppenuc committed 2016-03-15 22:17:08 +01:00
1 parent ef4deb51f6
commit 6a5119dbe3
108 files changed
+13081 -7351

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
//
// NAAES.h
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM (NSUInteger, NAAESAlgorithm) {
NAAESAlgorithm256CTR = 1,
};
@interface NAAES : NSObject
@property (readonly) NAAESAlgorithm algorithm;
- (instancetype)initWithAlgorithm:(NAAESAlgorithm)algorithm;
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
@end
+72
View File
@@ -0,0 +1,72 @@
//
// NAAES.m
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NAAES.h"
//#include "crypto_stream_aes256estream.h"
#include <CommonCrypto/CommonCryptor.h>
#import "NACounter.h"
#import "NANSMutableData+Utils.h"
#define AES_256_CTR_NONCE_BYTES (16)
#define AES_256_CTR_KEY_BYTES (32)
@implementation NAAES
- (instancetype)initWithAlgorithm:(NAAESAlgorithm)algorithm {
if ((self = [super init])) {
_algorithm = algorithm;
}
return self;
}
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
NSAssert(_algorithm == NAAESAlgorithm256CTR, @"Unsupported algorithm");
if (!nonce || [nonce length] < AES_256_CTR_NONCE_BYTES) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:600 userInfo:@{NSLocalizedDescriptionKey: @"Invalid AES nonce"}];
return nil;
}
if (!key || [key length] != AES_256_CTR_KEY_BYTES) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:601 userInfo:@{NSLocalizedDescriptionKey: @"Invalid AES key"}];
return nil;
}
// This libsodium version doesn't return what I expected
//int retval = crypto_stream_aes256estream_xor([outData mutableBytes], [data bytes], [data length], [nonce bytes], [key bytes]);
NSMutableData *outData = [data mutableCopy];
CCCryptorStatus cryptStatus;
CCCryptorRef cryptor;
cryptStatus = CCCryptorCreateWithMode(kCCEncrypt, kCCModeCTR, kCCAlgorithmAES128, ccNoPadding, [nonce bytes], [key bytes], [key length], NULL, 0, 0, kCCModeOptionCTR_BE, &cryptor);
if (cryptStatus != kCCSuccess) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:604 userInfo:@{NSLocalizedDescriptionKey: @"Failed AES (1)"}];
return nil;
}
size_t bytesEncrypted;
cryptStatus = CCCryptorUpdate(cryptor, [data bytes],[ data length], [outData mutableBytes], [outData length], &bytesEncrypted);
if (cryptStatus != kCCSuccess) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:605 userInfo:@{NSLocalizedDescriptionKey: @"Failed AES (2)"}];
return nil;
}
return outData;
}
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
NSAssert(_algorithm == NAAESAlgorithm256CTR, @"Unsupported algorithm");
return [self encrypt:data nonce:nonce key:key error:error];
}
@end
+20
View File
@@ -0,0 +1,20 @@
//
// NACounter.h
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
// Counter for CTR mode
@interface NACounter : NSObject
- (instancetype)initWithData:(NSData *)data;
- (void)increment;
- (NSData *)data;
@end
+44
View File
@@ -0,0 +1,44 @@
//
// NACounter.m
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NACounter.h"
@interface NACounter ()
@property NSMutableData *counterData;
@end
#define DEFAULT_LENGTH (16)
@implementation NACounter
- (instancetype)init {
NSAssert(NO, @"Use initWithData:");
return nil;
}
- (instancetype)initWithData:(NSData *)data {
if ((self = [super init])) {
_counterData = [data mutableCopy];
}
return self;
}
- (void)increment {
for (NSInteger i = [_counterData length] - 1; i >= 0; i--) {
uint8_t *bytes = [_counterData mutableBytes];
bytes[i]++;
if (bytes[i])
break;
}
}
- (NSData *)data {
return _counterData;
}
@end
+33
View File
@@ -0,0 +1,33 @@
//
// NACrypto.h
// NACrypto
//
// Created by Gabriel on 6/16/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for NACrypto.
FOUNDATION_EXPORT double NACryptoVersionNumber;
//! Project version string for NACrypto.
FOUNDATION_EXPORT const unsigned char NACryptoVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <NACrypto/PublicHeader.h>
#import <NACrypto/NASecRandom.h>
#import <NACrypto/NAHMAC.h>
#import <NACrypto/NAKeychain.h>
#import <NACrypto/NATwoFish.h>
#import <NACrypto/NAAES.h>
#import <NACrypto/NACounter.h>
#import <NACrypto/NADigest.h>
#import <NACrypto/NASHA3.h>
#import <NACrypto/NANSData+Utils.h>
#import <NACrypto/NANSString+Utils.h>
#import <NACrypto/NANSMutableData+Utils.h>
+34
View File
@@ -0,0 +1,34 @@
//
// NADigest.h
// NACrypto
//
// Created by Gabriel on 7/3/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM (NSUInteger, NADigestAlgorithm) {
//NADigestAlgorithmSHA1 = 1, // SHA1 might not be secure enough
NADigestAlgorithmSHA2_224 = 2,
NADigestAlgorithmSHA2_256,
NADigestAlgorithmSHA2_384,
NADigestAlgorithmSHA2_512,
// SHA3
NADigestAlgorithmSHA3_256,
NADigestAlgorithmSHA3_384,
NADigestAlgorithmSHA3_512,
};
@interface NADigest : NSObject
@property NADigestAlgorithm algorithm;
- (instancetype)initWithAlgorithm:(NADigestAlgorithm)algorithm;
- (NSData *)digestForData:(NSData *)data;
+ (NSData *)digestForData:(NSData *)data algorithm:(NADigestAlgorithm)algorithm;
@end
+77
View File
@@ -0,0 +1,77 @@
//
// NADigest.m
// NACrypto
//
// Created by Gabriel on 7/3/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NADigest.h"
#import "NASHA3.h"
#import <CommonCrypto/CommonDigest.h>
@implementation NADigest
- (instancetype)initWithAlgorithm:(NADigestAlgorithm)algorithm {
if ((self = [super init])) {
_algorithm = algorithm;
}
return self;
}
- (NSData *)digestForData:(NSData *)data {
return [NADigest digestForData:data algorithm:_algorithm];
}
+ (NSData *)digestForData:(NSData *)data algorithm:(NADigestAlgorithm)algorithm {
switch (algorithm) {
case NADigestAlgorithmSHA2_224:
case NADigestAlgorithmSHA2_256:
case NADigestAlgorithmSHA2_384:
case NADigestAlgorithmSHA2_512:
return [self _SHAForData:data algorithm:algorithm];
case NADigestAlgorithmSHA3_256:
return [NASHA3 SHA3ForData:data digestBitLength:256];
case NADigestAlgorithmSHA3_384:
return [NASHA3 SHA3ForData:data digestBitLength:384];
case NADigestAlgorithmSHA3_512:
return [NASHA3 SHA3ForData:data digestBitLength:512];
}
}
+ (NSData *)_SHAForData:(NSData *)data algorithm:(NADigestAlgorithm)algorithm {
switch (algorithm) {
case NADigestAlgorithmSHA2_224: {
uint8_t digest[CC_SHA224_DIGEST_LENGTH];
CC_SHA224(data.bytes, (CC_LONG)data.length, digest);
return [[NSData alloc] initWithBytes:digest length:sizeof(digest)];
}
case NADigestAlgorithmSHA2_256: {
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
return [[NSData alloc] initWithBytes:digest length:sizeof(digest)];
}
case NADigestAlgorithmSHA2_384: {
uint8_t digest[CC_SHA384_DIGEST_LENGTH];
CC_SHA384(data.bytes, (CC_LONG)data.length, digest);
return [[NSData alloc] initWithBytes:digest length:sizeof(digest)];
}
case NADigestAlgorithmSHA2_512: {
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, (CC_LONG)data.length, digest);
return [[NSData alloc] initWithBytes:digest length:sizeof(digest)];
}
default: {
NSAssert(NO, @"Unsupported algorithm");
return nil;
}
}
}
@end
+34
View File
@@ -0,0 +1,34 @@
//
// NAHMAC.h
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM (NSUInteger, NAHMACAlgorithm) {
NAHMACAlgorithmSHA1,
NAHMACAlgorithmSHA2_224,
NAHMACAlgorithmSHA2_256,
NAHMACAlgorithmSHA2_384,
NAHMACAlgorithmSHA2_512,
// SHA3
NAHMACAlgorithmSHA3_256,
NAHMACAlgorithmSHA3_384,
NAHMACAlgorithmSHA3_512,
};
@interface NAHMAC : NSObject
@property NAHMACAlgorithm algorithm;
- (instancetype)initWithAlgorithm:(NAHMACAlgorithm)algorithm;
- (NSData *)HMACForKey:(NSData *)key data:(NSData *)data;
+ (NSData *)HMACForKey:(NSData *)key data:(NSData *)data algorithm:(NAHMACAlgorithm)algorithm;
@end
+121
View File
@@ -0,0 +1,121 @@
//
// NAHMAC.m
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NAHMAC.h"
#include <CommonCrypto/CommonHMAC.h>
#import "NANSData+Utils.h"
#import "NANSString+Utils.h"
#import "NASHA3.h"
@implementation NAHMAC
- (instancetype)initWithAlgorithm:(NAHMACAlgorithm)algorithm {
if ((self = [super init])) {
_algorithm = algorithm;
}
return self;
}
- (NSData *)HMACForKey:(NSData *)key data:(NSData *)data {
return [NAHMAC HMACForKey:key data:data algorithm:_algorithm];
}
+ (NSData *)HMACForKey:(NSData *)key data:(NSData *)data algorithm:(NAHMACAlgorithm)algorithm {
NSParameterAssert(key);
switch (algorithm) {
case NAHMACAlgorithmSHA1:
case NAHMACAlgorithmSHA2_224:
case NAHMACAlgorithmSHA2_256:
case NAHMACAlgorithmSHA2_384:
case NAHMACAlgorithmSHA2_512:
return [self _HMACSHAForKey:key data:data algorithm:algorithm];
case NAHMACAlgorithmSHA3_256:
case NAHMACAlgorithmSHA3_384:
case NAHMACAlgorithmSHA3_512:
return [self _HMACSHA3ForKey:key data:data algorithm:algorithm];
}
}
+ (NSData *)_HMACSHAForKey:(NSData *)key data:(NSData *)data algorithm:(NAHMACAlgorithm)algorithm {
CCHmacAlgorithm ccAlgorithm;
NSUInteger dataLength;
switch (algorithm) {
case NAHMACAlgorithmSHA1: ccAlgorithm = kCCHmacAlgSHA1; dataLength = CC_SHA1_DIGEST_LENGTH; break;
case NAHMACAlgorithmSHA2_224: ccAlgorithm = kCCHmacAlgSHA224; dataLength = CC_SHA224_DIGEST_LENGTH; break;
case NAHMACAlgorithmSHA2_256: ccAlgorithm = kCCHmacAlgSHA256; dataLength = CC_SHA256_DIGEST_LENGTH; break;
case NAHMACAlgorithmSHA2_384: ccAlgorithm = kCCHmacAlgSHA384; dataLength = CC_SHA384_DIGEST_LENGTH; break;
case NAHMACAlgorithmSHA2_512: ccAlgorithm = kCCHmacAlgSHA512; dataLength = CC_SHA512_DIGEST_LENGTH; break;
default:
NSAssert(NO, @"Unsupported algorithm");
return nil;
}
CCHmacContext ctx;
CCHmacInit(&ctx, ccAlgorithm, [key bytes], [key length]);
CCHmacUpdate(&ctx, [data bytes], [data length]);
NSMutableData *macOut = [NSMutableData dataWithLength:dataLength];
CCHmacFinal(&ctx, [macOut mutableBytes]);
return macOut;
}
+ (NSData *)_HMACSHA3ForKey:(NSData *)key data:(NSData *)data algorithm:(NAHMACAlgorithm)algorithm {
NSUInteger blockLength = 72;
NSUInteger keyLength = [key length];
NSUInteger digestBitLength;
switch (algorithm) {
case NAHMACAlgorithmSHA3_256: digestBitLength = 256; break;
case NAHMACAlgorithmSHA3_384: digestBitLength = 384; break;
case NAHMACAlgorithmSHA3_512: digestBitLength = 512; break;
default:
NSAssert(NO, @"Unsupported algorithm");
return nil;
}
//
// Used this as a reference:
// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/API/CommonHMAC.c
//
uint8_t *keyP;
if (keyLength > blockLength) {
key = [NASHA3 SHA3ForData:key digestBitLength:digestBitLength];
keyLength = [key length];
}
NSMutableData *keyIn = [NSMutableData dataWithLength:blockLength];
uint8_t *k_ipad = [keyIn mutableBytes];
NSMutableData *keyOut = [NSMutableData dataWithLength:blockLength];
uint8_t *k_opad = [keyOut mutableBytes];
keyP = (uint8_t *)[key bytes];
/* Copy the key into k_ipad and k_opad while doing the XOR. */
for (uint32_t byte = 0; byte < keyLength; byte++) {
k_ipad[byte] = keyP[byte] ^ 0x36;
k_opad[byte] = keyP[byte] ^ 0x5c;
}
/* Fill the remainder of k_ipad and k_opad with 0 XORed with the appropriate value. */
if (keyLength < blockLength) {
memset(k_ipad + keyLength, 0x36, blockLength - keyLength);
memset(k_opad + keyLength, 0x5c, blockLength - keyLength);
}
NSData *macOut = [NASHA3 SHA3ForDatas:@[keyIn, data] digestBitLength:digestBitLength];
/* Perform outer digest */
return [NASHA3 SHA3ForDatas:@[keyOut, macOut] digestBitLength:digestBitLength];
}
@end
+17
View File
@@ -0,0 +1,17 @@
//
// NAKeychain.h
// NACL
//
// Created by Gabriel Handford on 1/21/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NAKeychain : NSObject
+ (BOOL)addSymmetricKey:(NSData *)symmetricKey applicationLabel:(NSString *)applicationLabel tag:(NSData *)tag label:(NSString *)label;
+ (NSData *)symmetricKeyWithApplicationLabel:(NSString *)applicationLabel;
@end
+104
View File
@@ -0,0 +1,104 @@
//
// NAKeychain.m
// NACL
//
// Created by Gabriel Handford on 1/21/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NAKeychain.h"
@implementation NAKeychain
+ (BOOL)addKey:(NSData *)key attributes:(NSDictionary *)attributes {
if (!key || attributes[(__bridge id)(kSecAttrKeyClass)] == nil || attributes[(__bridge id)(kSecAttrApplicationLabel)] == nil) {
return NO;
}
NSMutableDictionary *allAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
allAttributes[(__bridge __strong id)(kSecClass)] = (__bridge id)(kSecClassKey);
allAttributes[(__bridge __strong id)(kSecValueData)] = key;
if (allAttributes[(__bridge id)(kSecAttrIsPermanent)] == nil) {
allAttributes[(__bridge __strong id)(kSecAttrIsPermanent)] = @(YES);
}
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)(allAttributes), NULL);
if (status != errSecSuccess) {
return NO;
}
return YES;
}
+ (BOOL)addSymmetricKey:(NSData *)symmetricKey applicationLabel:(NSString *)applicationLabel tag:(NSData *)tag label:(NSString *)label {
if (!symmetricKey || !applicationLabel) {
return NO;
}
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
attributes[(__bridge __strong id)kSecAttrKeyClass] = (__bridge id)kSecAttrKeyClassSymmetric;
attributes[(__bridge __strong id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly;
attributes[(__bridge __strong id)kSecAttrApplicationLabel] = applicationLabel;
if (tag) {
attributes[(__bridge __strong id)kSecAttrApplicationTag] = tag;
}
if (label) {
attributes[(__bridge __strong id)kSecAttrLabel] = label;
}
return [self addKey:symmetricKey attributes:attributes];
}
+ (NSData *)keyWithApplicationLabel:(NSString *)applicationLabel attributes:(NSDictionary *)attributes {
if (!applicationLabel || !attributes[(__bridge id)(kSecAttrKeyClass)]) {
return nil;
}
NSMutableDictionary *allAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
allAttributes[(__bridge __strong id)(kSecClass)] = (__bridge id)(kSecClassKey);
allAttributes[(__bridge __strong id)kSecAttrApplicationLabel] = applicationLabel;
if (allAttributes[(__bridge id)(kSecAttrIsPermanent)] == nil) {
allAttributes[(__bridge __strong id)(kSecAttrIsPermanent)] = @(YES);
}
allAttributes[(__bridge __strong id)(kSecReturnData)] = @(YES);
CFTypeRef keyData = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)allAttributes, &keyData);
if (status != errSecSuccess) {
return nil;
}
return (__bridge_transfer NSData *)keyData;
}
+ (NSData *)symmetricKeyWithApplicationLabel:(NSString *)applicationLabel {
NSDictionary *attributes = @{(__bridge __strong id)kSecAttrKeyClass: (__bridge id)kSecAttrKeyClassSymmetric};
return [self keyWithApplicationLabel:applicationLabel attributes:attributes];
}
+ (NSDictionary *)keyAttributesWithApplicationLabel:(NSString *)applicationLabel queryAttributes:(NSDictionary *)queryAttributes {
if (!applicationLabel || !queryAttributes || !queryAttributes[(__bridge id)(kSecAttrKeyClass)]) {
return nil;
}
NSMutableDictionary *allAttributes = [NSMutableDictionary dictionaryWithDictionary:queryAttributes];
allAttributes[(__bridge __strong id)(kSecClass)] = (__bridge id)(kSecClassKey);
allAttributes[(__bridge __strong id)(kSecAttrApplicationLabel)] = applicationLabel;
allAttributes[(__bridge __strong id)(kSecReturnData)] = @YES;
allAttributes[(__bridge __strong id)(kSecReturnAttributes)] = @YES;
CFTypeRef resultData = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)allAttributes, &resultData);
if (status != errSecSuccess) {
return nil;
}
return (__bridge_transfer NSDictionary *)resultData;
}
+ (NSDictionary *)symmetricKeyAttributesWithApplicationLabel:(NSString *)applicationLabel {
NSDictionary *queryAttributes = @{(__bridge __strong id)(kSecAttrKeyClass): (__bridge id)(kSecAttrKeyClassSymmetric)};
return [self keyAttributesWithApplicationLabel:applicationLabel queryAttributes:queryAttributes];
}
@end
+23
View File
@@ -0,0 +1,23 @@
//
// NANSData+Utils.h
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSData (NAUtils)
- (NSString *)na_hexString;
+ (NSData *)na_dataWithDatas:(NSArray *)datas;
- (BOOL)na_isEqualConstantTime:(NSData *)data;
- (void)na_sliceNoCopyAtIndex:(NSUInteger)index data:(NSData **)data1 data:(NSData **)data2;
+ (NSData *)na_dataNoCopy:(NSData *)data offset:(NSUInteger)offset length:(NSUInteger)length;
@end
+70
View File
@@ -0,0 +1,70 @@
//
// NANSData+Utils.m
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NANSData+Utils.h"
@implementation NSData (NAUtils)
- (NSString *)na_hexString {
if ([self length] == 0) return nil;
NSMutableString *hexString = [NSMutableString stringWithCapacity:[self length] * 2];
for (NSUInteger i = 0; i < [self length]; ++i) {
[hexString appendFormat:@"%02X", *((uint8_t *)[self bytes] + i)];
}
return [hexString lowercaseString];
}
+ (NSData *)na_dataWithDatas:(NSArray *)datas {
NSInteger length = 0;
for (NSData *data in datas) {
length += data.length;
}
NSMutableData *combined = [NSMutableData dataWithCapacity:length];
for (NSData *data in datas) {
[combined appendData:data];
}
return combined;
}
- (BOOL)na_isEqualConstantTime:(NSData *)data {
if ([self length] != [data length]) return NO;
const uint8_t *dataPtr = (uint8_t *)self.bytes;
const uint8_t *data2Ptr = (uint8_t *)data.bytes;
uint8_t result = 0;
for (int i = 0; i < self.length; i++) {
result = result ^ (dataPtr[i] ^ data2Ptr[i]);
}
return (result == 0);
}
- (void)na_sliceNoCopyAtIndex:(NSUInteger)index data:(NSData **)data1 data:(NSData **)data2 {
if (index > [self length]) {
[NSException raise:NSRangeException format:@"Index is out of bounds"];
return;
}
if (index > 0) {
*data1 = [NSData dataWithBytesNoCopy:(uint8_t *)[self bytes] length:index freeWhenDone:NO];
} else {
*data1 = [NSData data];
}
if ([self length] > index) {
*data2 = [NSData dataWithBytesNoCopy:((uint8_t *)[self bytes] + index) length:([self length] - index) freeWhenDone:NO];
} else {
*data2 = [NSData data];
}
}
+ (NSData *)na_dataNoCopy:(NSData *)data offset:(NSUInteger)offset length:(NSUInteger)length {
return [NSData dataWithBytesNoCopy:((uint8_t *)[data bytes] + offset) length:length freeWhenDone:NO];
}
@end
+15
View File
@@ -0,0 +1,15 @@
//
// NANSMutableData+Utils.h
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMutableData (NAUtils)
- (void)na_XORWithData:(NSData *)data index:(NSInteger)index;
@end
+24
View File
@@ -0,0 +1,24 @@
//
// NANSMutableData+Utils.m
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NANSMutableData+Utils.h"
@implementation NSMutableData (NAUtils)
- (void)na_XORWithData:(NSData *)data index:(NSInteger)index {
uint8_t *dataPtr = (uint8_t *)self.mutableBytes;
const uint8_t *data2Ptr = (uint8_t *)data.bytes;
NSAssert(index < self.length, @"Invalid index");
for (int i = 0; i < data.length && (i + index) < self.length; i++) {
dataPtr[i + index] = dataPtr[i + index] ^ data2Ptr[i];
}
}
@end
+15
View File
@@ -0,0 +1,15 @@
//
// NANSString+Utils.h
// NACrypto
//
// Created by Gabriel on 6/19/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (NAUtils)
- (NSData *)na_dataFromHexString;
@end
+33
View File
@@ -0,0 +1,33 @@
//
// NANSString+Utils.m
// NACrypto
//
// Created by Gabriel on 6/19/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NANSString+Utils.h"
@implementation NSString (NAUtils)
- (NSData *)na_dataFromHexString {
if ((self.length % 2) != 0) {
return nil;
}
const char *chars = [self UTF8String];
NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
char byteChars[3] = {0, 0, 0};
unsigned long wholeByte;
for (int i = 0; i < self.length; i += 2) {
byteChars[0] = chars[i];
byteChars[1] = chars[i + 1];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}
@end
+17
View File
@@ -0,0 +1,17 @@
//
// NASHA3.h
// NACrypto
//
// Created by Gabriel on 6/23/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NASHA3 : NSObject
+ (NSData *)SHA3ForData:(NSData *)data digestBitLength:(NSUInteger)digestBitLength;
+ (NSData *)SHA3ForDatas:(NSArray *)datas digestBitLength:(NSUInteger)digestBitLength;
@end
+37
View File
@@ -0,0 +1,37 @@
//
// NASHA3.m
// NACrypto
//
// Created by Gabriel on 6/23/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NASHA3.h"
#import "KeccakNISTInterface.h"
@implementation NASHA3
+ (NSData *)SHA3ForData:(NSData *)data digestBitLength:(NSUInteger)digestBitLength {
return [self SHA3ForDatas:@[data] digestBitLength:digestBitLength];
}
+ (NSData *)SHA3ForDatas:(NSArray *)datas digestBitLength:(NSUInteger)digestBitLength {
NSUInteger digestLength = digestBitLength/8;
NSMutableData *outData = [NSMutableData dataWithLength:digestLength];
hashState state;
int result;
result = Init(&state, (int)digestBitLength); // Bit length
NSAssert(result == 0, @"Failed to init");
for (NSData *data in datas) {
result = Update(&state, (const BitSequence *)[data bytes], [data length] * 8); // Bit length
NSAssert(result == 0, @"Failed to update");
}
result = Final(&state, [outData mutableBytes]);
NSAssert(result == 0, @"Failed to finalize");
return outData;
}
@end
+27
View File
@@ -0,0 +1,27 @@
//
// NASecRandom.h
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NASecRandom : NSObject
/*!
Generate random data.
The source code of SecRandomCopyBytes() is located at
http://opensource.apple.com/source/Security/Security-55179.11/sec/Security/SecFramework.c
@param len Number of random bytes to generate
@result NSData of length bytes, or nil if an error occurred
*/
+ (NSData *)randomData:(size_t)numBytes error:(NSError **)error;
/*!
Generate random base64 string.
*/
+ (NSString *)randomBase64String:(size_t)length error:(NSError **)error;
@end
+35
View File
@@ -0,0 +1,35 @@
//
// NASecRandom.m
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NASecRandom.h"
#import "NANSData+Utils.h"
#include <Security/SecRandom.h>
@implementation NASecRandom
+ (NSData *)randomData:(size_t)numBytes error:(NSError **)error {
NSMutableData *data = [NSMutableData dataWithLength:numBytes];
int ret = SecRandomCopyBytes(kSecRandomDefault, numBytes, [data mutableBytes]);
if (ret == -1) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:50 userInfo:@{NSLocalizedDescriptionKey: @"Unable to generate random data"}];
return nil;
}
return data;
}
+ (NSString *)randomBase64String:(size_t)length error:(NSError **)error {
size_t numBytes = (size_t)ceil((length * 8.0) / 6.0);
NSData *data = [self randomData:numBytes error:error];
if (!data) return nil;
NSString *base64String = [data base64EncodedStringWithOptions:0];
if ([base64String length] > length) base64String = [base64String substringToIndex:length];
return base64String;
}
@end
+17
View File
@@ -0,0 +1,17 @@
//
// NATwoFish.h
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NATwoFish : NSObject
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
@end
+58
View File
@@ -0,0 +1,58 @@
//
// NATwoFish.m
// NACrypto
//
// Created by Gabriel on 6/20/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NATwoFish.h"
#import "NACounter.h"
#import "NANSMutableData+Utils.h"
#import "NANSData+Utils.h"
#include "twofish.h"
@implementation NATwoFish
static dispatch_once_t twoFishInit;
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
if (!nonce || [nonce length] < 16) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:700 userInfo:@{NSLocalizedDescriptionKey: @"Invalid TwoFish nonce"}];
return nil;
}
if (!key || [key length] != 32) {
if (error) *error = [NSError errorWithDomain:@"NACrypto" code:701 userInfo:@{NSLocalizedDescriptionKey: @"Invalid TwoFish key"}];
return nil;
}
dispatch_once(&twoFishInit, ^{ Twofish_initialise(); });
Twofish_key xkey;
Twofish_prepare_key((uint8_t *)[key bytes], (int)[key length], &xkey);
NACounter *counter = [[NACounter alloc] initWithData:nonce];
NSInteger blockLength = [nonce length];
NSMutableData *outData = [data mutableCopy];
NSMutableData *blockOutData = [NSMutableData dataWithLength:blockLength];
for (NSInteger index = 0; index < [data length]; index += blockLength) {
Twofish_encrypt(&xkey, (uint8_t *)[counter.data bytes], [blockOutData mutableBytes]);
[outData na_XORWithData:blockOutData index:index];
[counter increment];
}
return outData;
}
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
return [self encrypt:data nonce:nonce key:key error:error];
}
@end
File diff suppressed because it is too large. Load diff
+180
View File
@@ -0,0 +1,180 @@
/*
* Fast, portable, and easy-to-use Twofish implementation,
* Version 0.3.
* Copyright (c) 2002 by Niels Ferguson.
*
* See the twofish.c file for the details of the how and why of this code.
*
* The author hereby grants a perpetual license to everybody to
* use this code for any purpose as long as the copyright message is included
* in the source code of this or any derived work.
*/
#include <stdint.h>
/*
* PLATFORM FIXES
* ==============
*
* The following definitions have to be fixed for each particular platform
* you work on. If you have a multi-platform program, you no doubt have
* portable definitions that you can substitute here without changing
* the rest of the code.
*
* The defaults provided here should work on most PC compilers.
*/
/*
* A Twofish_Byte must be an unsigned 8-bit integer.
* It must also be the elementary data size of your C platform,
* i.e. sizeof( Twofish_Byte ) == 1.
*/
typedef uint8_t Twofish_Byte;
/*
* A Twofish_UInt32 must be an unsigned integer of at least 32 bits.
*
* This type is used only internally in the implementation, so ideally it
* would not appear in the header file, but it is used inside the
* Twofish_key structure which means it has to be included here.
*/
typedef uint32_t Twofish_UInt32;
/*
* END OF PLATFORM FIXES
* =====================
*
* You should not have to touch the rest of this file, but the code
* in twofish.c has a few things you need to fix too.
*/
/*
* Structure that contains a prepared Twofish key.
* A cipher key is used in two stages. In the first stage it is converted
* form the original form to an internal representation.
* This internal form is then used to encrypt and decrypt data.
* This structure contains the internal form. It is rather large: 4256 bytes
* on a platform with 32-bit unsigned values.
*
* Treat this as an opague structure, and don't try to manipulate the
* elements in it. I wish I could hide the inside of the structure,
* but C doesn't allow that.
*/
typedef
struct
{
Twofish_UInt32 s[4][256]; /* pre-computed S-boxes */
Twofish_UInt32 K[40]; /* Round key words */
}
Twofish_key;
/*
* Initialise and test the Twofish implementation.
*
* This function MUST be called before any other function in the
* Twofish implementation is called.
* It only needs to be called once.
*
* Apart from initialising the implementation it performs a self test.
* If the Twofish_fatal function is not called, the code passed the test.
* (See the twofish.c file for details on the Twofish_fatal function.)
*/
extern void Twofish_initialise();
/*
* Convert a cipher key to the internal form used for
* encryption and decryption.
*
* The cipher key is an array of bytes; the Twofish_Byte type is
* defined above to a type suitable on your platform.
*
* Any key must be converted to an internal form in the Twofisk_key structure
* before it can be used.
* The encryption and decryption functions only work with the internal form.
* The conversion to internal form need only be done once for each key value.
*
* Be sure to wipe all key storage, including the Twofish_key structure,
* once you are done with the key data.
* A simple memset( TwofishKey, 0, sizeof( TwofishKey ) ) will do just fine.
*
* Unlike most implementations, this one allows any key size from 0 bytes
* to 32 bytes. According to the Twofish specifications,
* irregular key sizes are handled by padding the key with zeroes at the end
* until the key size is 16, 24, or 32 bytes, whichever
* comes first. Note that each key of irregular size is equivalent to exactly
* one key of 16, 24, or 32 bytes.
*
* WARNING: Short keys have low entropy, and result in low security.
* Anything less than 8 bytes is utterly insecure. For good security
* use at least 16 bytes. I prefer to use 32-byte keys to prevent
* any collision attacks on the key.
*
* The key length argument key_len must be in the proper range.
* If key_len is not in the range 0,...,32 this routine attempts to generate
* a fatal error (depending on the code environment),
* and at best (or worst) returns without having done anything.
*
* Arguments:
* key Array of key bytes
* key_len Number of key bytes, must be in the range 0,1,...,32.
* xkey Pointer to an Twofish_key structure that will be filled
* with the internal form of the cipher key.
*/
extern void Twofish_prepare_key(
Twofish_Byte key[],
int key_len,
Twofish_key * xkey
);
/*
* Encrypt a single block of data.
*
* This function encrypts a single block of 16 bytes of data.
* If you want to encrypt a larger or variable-length message,
* you will have to use a cipher mode, such as CBC or CTR.
* These are outside the scope of this implementation.
*
* The xkey structure is not modified by this routine, and can be
* used for further encryption and decryption operations.
*
* Arguments:
* xkey pointer to Twofish_key, internal form of the key
* produces by Twofish_prepare_key()
* p Plaintext to be encrypted
* c Place to store the ciphertext
*/
extern void Twofish_encrypt(
Twofish_key * xkey,
Twofish_Byte p[16],
Twofish_Byte c[16]
);
/*
* Decrypt a single block of data.
*
* This function decrypts a single block of 16 bytes of data.
* If you want to decrypt a larger or variable-length message,
* you will have to use a cipher mode, such as CBC or CTR.
* These are outside the scope of this implementation.
*
* The xkey structure is not modified by this routine, and can be
* used for further encryption and decryption operations.
*
* Arguments:
* xkey pointer to Twofish_key, internal form of the key
* produces by Twofish_prepare_key()
* c Ciphertext to be decrypted
* p Place to store the plaintext
*/
extern void Twofish_decrypt(
Twofish_key * xkey,
Twofish_Byte c[16],
Twofish_Byte p[16]
);
@@ -0,0 +1,562 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by Ronny Van Keer,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include "KeccakF-1600-interface.h"
#ifndef _Keccak1600_32_rvk_h_
#define _Keccak1600_32_rvk_h_
static const UINT32 KeccakF1600RoundConstants_int2[2*24] =
{
0x00000001UL, 0x00000000UL,
0x00000000UL, 0x00000089UL,
0x00000000UL, 0x8000008bUL,
0x00000000UL, 0x80008080UL,
0x00000001UL, 0x0000008bUL,
0x00000001UL, 0x00008000UL,
0x00000001UL, 0x80008088UL,
0x00000001UL, 0x80000082UL,
0x00000000UL, 0x0000000bUL,
0x00000000UL, 0x0000000aUL,
0x00000001UL, 0x00008082UL,
0x00000000UL, 0x00008003UL,
0x00000001UL, 0x0000808bUL,
0x00000001UL, 0x8000000bUL,
0x00000001UL, 0x8000008aUL,
0x00000001UL, 0x80000081UL,
0x00000000UL, 0x80000081UL,
0x00000000UL, 0x80000008UL,
0x00000000UL, 0x00000083UL,
0x00000000UL, 0x80008003UL,
0x00000001UL, 0x80008088UL,
0x00000000UL, 0x80000088UL,
0x00000001UL, 0x00008000UL,
0x00000000UL, 0x80008082UL
};
#undef rounds
#define rounds \
{ \
UINT32 Da0, De0, Di0, Do0, Du0; \
UINT32 Da1, De1, Di1, Do1, Du1; \
UINT32 Ba, Be, Bi, Bo, Bu; \
UINT32 Aba0, Abe0, Abi0, Abo0, Abu0; \
UINT32 Aba1, Abe1, Abi1, Abo1, Abu1; \
UINT32 Aga0, Age0, Agi0, Ago0, Agu0; \
UINT32 Aga1, Age1, Agi1, Ago1, Agu1; \
UINT32 Aka0, Ake0, Aki0, Ako0, Aku0; \
UINT32 Aka1, Ake1, Aki1, Ako1, Aku1; \
UINT32 Ama0, Ame0, Ami0, Amo0, Amu0; \
UINT32 Ama1, Ame1, Ami1, Amo1, Amu1; \
UINT32 Asa0, Ase0, Asi0, Aso0, Asu0; \
UINT32 Asa1, Ase1, Asi1, Aso1, Asu1; \
UINT32 Cw, Cx, Cy, Cz; \
UINT32 Eba0, Ebe0, Ebi0, Ebo0, Ebu0; \
UINT32 Eba1, Ebe1, Ebi1, Ebo1, Ebu1; \
UINT32 Ega0, Ege0, Egi0, Ego0, Egu0; \
UINT32 Ega1, Ege1, Egi1, Ego1, Egu1; \
UINT32 Eka0, Eke0, Eki0, Eko0, Eku0; \
UINT32 Eka1, Eke1, Eki1, Eko1, Eku1; \
UINT32 Ema0, Eme0, Emi0, Emo0, Emu0; \
UINT32 Ema1, Eme1, Emi1, Emo1, Emu1; \
UINT32 Esa0, Ese0, Esi0, Eso0, Esu0; \
UINT32 Esa1, Ese1, Esi1, Eso1, Esu1; \
const UINT32 * pRoundConstants = KeccakF1600RoundConstants_int2; \
UINT32 i; \
\
copyFromState(A, state) \
\
for( i = 12; i != 0; --i ) { \
Cx = Abu0^Agu0^Aku0^Amu0^Asu0; \
Du1 = Abe1^Age1^Ake1^Ame1^Ase1; \
Da0 = Cx^ROL32(Du1, 1); \
Cz = Abu1^Agu1^Aku1^Amu1^Asu1; \
Du0 = Abe0^Age0^Ake0^Ame0^Ase0; \
Da1 = Cz^Du0; \
\
Cw = Abi0^Agi0^Aki0^Ami0^Asi0; \
Do0 = Cw^ROL32(Cz, 1); \
Cy = Abi1^Agi1^Aki1^Ami1^Asi1; \
Do1 = Cy^Cx; \
\
Cx = Aba0^Aga0^Aka0^Ama0^Asa0; \
De0 = Cx^ROL32(Cy, 1); \
Cz = Aba1^Aga1^Aka1^Ama1^Asa1; \
De1 = Cz^Cw; \
\
Cy = Abo1^Ago1^Ako1^Amo1^Aso1; \
Di0 = Du0^ROL32(Cy, 1); \
Cw = Abo0^Ago0^Ako0^Amo0^Aso0; \
Di1 = Du1^Cw; \
\
Du0 = Cw^ROL32(Cz, 1); \
Du1 = Cy^Cx; \
\
Aba0 ^= Da0; \
Ba = Aba0; \
Age0 ^= De0; \
Be = ROL32(Age0, 22); \
Aki1 ^= Di1; \
Bi = ROL32(Aki1, 22); \
Amo1 ^= Do1; \
Bo = ROL32(Amo1, 11); \
Asu0 ^= Du0; \
Bu = ROL32(Asu0, 7); \
Eba0 = Ba ^((~Be)& Bi ) ^ *(pRoundConstants++); \
Ebe0 = Be ^((~Bi)& Bo ); \
Ebi0 = Bi ^((~Bo)& Bu ); \
Ebo0 = Bo ^((~Bu)& Ba ); \
Ebu0 = Bu ^((~Ba)& Be ); \
\
Abo0 ^= Do0; \
Ba = ROL32(Abo0, 14); \
Agu0 ^= Du0; \
Be = ROL32(Agu0, 10); \
Aka1 ^= Da1; \
Bi = ROL32(Aka1, 2); \
Ame1 ^= De1; \
Bo = ROL32(Ame1, 23); \
Asi1 ^= Di1; \
Bu = ROL32(Asi1, 31); \
Ega0 = Ba ^((~Be)& Bi ); \
Ege0 = Be ^((~Bi)& Bo ); \
Egi0 = Bi ^((~Bo)& Bu ); \
Ego0 = Bo ^((~Bu)& Ba ); \
Egu0 = Bu ^((~Ba)& Be ); \
\
Abe1 ^= De1; \
Ba = ROL32(Abe1, 1); \
Agi0 ^= Di0; \
Be = ROL32(Agi0, 3); \
Ako1 ^= Do1; \
Bi = ROL32(Ako1, 13); \
Amu0 ^= Du0; \
Bo = ROL32(Amu0, 4); \
Asa0 ^= Da0; \
Bu = ROL32(Asa0, 9); \
Eka0 = Ba ^((~Be)& Bi ); \
Eke0 = Be ^((~Bi)& Bo ); \
Eki0 = Bi ^((~Bo)& Bu ); \
Eko0 = Bo ^((~Bu)& Ba ); \
Eku0 = Bu ^((~Ba)& Be ); \
\
Abu1 ^= Du1; \
Ba = ROL32(Abu1, 14); \
Aga0 ^= Da0; \
Be = ROL32(Aga0, 18); \
Ake0 ^= De0; \
Bi = ROL32(Ake0, 5); \
Ami1 ^= Di1; \
Bo = ROL32(Ami1, 8); \
Aso0 ^= Do0; \
Bu = ROL32(Aso0, 28); \
Ema0 = Ba ^((~Be)& Bi ); \
Eme0 = Be ^((~Bi)& Bo ); \
Emi0 = Bi ^((~Bo)& Bu ); \
Emo0 = Bo ^((~Bu)& Ba ); \
Emu0 = Bu ^((~Ba)& Be ); \
\
Abi0 ^= Di0; \
Ba = ROL32(Abi0, 31); \
Ago1 ^= Do1; \
Be = ROL32(Ago1, 28); \
Aku1 ^= Du1; \
Bi = ROL32(Aku1, 20); \
Ama1 ^= Da1; \
Bo = ROL32(Ama1, 21); \
Ase0 ^= De0; \
Bu = ROL32(Ase0, 1); \
Esa0 = Ba ^((~Be)& Bi ); \
Ese0 = Be ^((~Bi)& Bo ); \
Esi0 = Bi ^((~Bo)& Bu ); \
Eso0 = Bo ^((~Bu)& Ba ); \
Esu0 = Bu ^((~Ba)& Be ); \
\
Aba1 ^= Da1; \
Ba = Aba1; \
Age1 ^= De1; \
Be = ROL32(Age1, 22); \
Aki0 ^= Di0; \
Bi = ROL32(Aki0, 21); \
Amo0 ^= Do0; \
Bo = ROL32(Amo0, 10); \
Asu1 ^= Du1; \
Bu = ROL32(Asu1, 7); \
Eba1 = Ba ^((~Be)& Bi ); \
Eba1 ^= *(pRoundConstants++); \
Ebe1 = Be ^((~Bi)& Bo ); \
Ebi1 = Bi ^((~Bo)& Bu ); \
Ebo1 = Bo ^((~Bu)& Ba ); \
Ebu1 = Bu ^((~Ba)& Be ); \
\
Abo1 ^= Do1; \
Ba = ROL32(Abo1, 14); \
Agu1 ^= Du1; \
Be = ROL32(Agu1, 10); \
Aka0 ^= Da0; \
Bi = ROL32(Aka0, 1); \
Ame0 ^= De0; \
Bo = ROL32(Ame0, 22); \
Asi0 ^= Di0; \
Bu = ROL32(Asi0, 30); \
Ega1 = Ba ^((~Be)& Bi ); \
Ege1 = Be ^((~Bi)& Bo ); \
Egi1 = Bi ^((~Bo)& Bu ); \
Ego1 = Bo ^((~Bu)& Ba ); \
Egu1 = Bu ^((~Ba)& Be ); \
\
Abe0 ^= De0; \
Ba = Abe0; \
Agi1 ^= Di1; \
Be = ROL32(Agi1, 3); \
Ako0 ^= Do0; \
Bi = ROL32(Ako0, 12); \
Amu1 ^= Du1; \
Bo = ROL32(Amu1, 4); \
Asa1 ^= Da1; \
Bu = ROL32(Asa1, 9); \
Eka1 = Ba ^((~Be)& Bi ); \
Eke1 = Be ^((~Bi)& Bo ); \
Eki1 = Bi ^((~Bo)& Bu ); \
Eko1 = Bo ^((~Bu)& Ba ); \
Eku1 = Bu ^((~Ba)& Be ); \
\
Abu0 ^= Du0; \
Ba = ROL32(Abu0, 13); \
Aga1 ^= Da1; \
Be = ROL32(Aga1, 18); \
Ake1 ^= De1; \
Bi = ROL32(Ake1, 5); \
Ami0 ^= Di0; \
Bo = ROL32(Ami0, 7); \
Aso1 ^= Do1; \
Bu = ROL32(Aso1, 28); \
Ema1 = Ba ^((~Be)& Bi ); \
Eme1 = Be ^((~Bi)& Bo ); \
Emi1 = Bi ^((~Bo)& Bu ); \
Emo1 = Bo ^((~Bu)& Ba ); \
Emu1 = Bu ^((~Ba)& Be ); \
\
Abi1 ^= Di1; \
Ba = ROL32(Abi1, 31); \
Ago0 ^= Do0; \
Be = ROL32(Ago0, 27); \
Aku0 ^= Du0; \
Bi = ROL32(Aku0, 19); \
Ama0 ^= Da0; \
Bo = ROL32(Ama0, 20); \
Ase1 ^= De1; \
Bu = ROL32(Ase1, 1); \
Esa1 = Ba ^((~Be)& Bi ); \
Ese1 = Be ^((~Bi)& Bo ); \
Esi1 = Bi ^((~Bo)& Bu ); \
Eso1 = Bo ^((~Bu)& Ba ); \
Esu1 = Bu ^((~Ba)& Be ); \
\
Cx = Ebu0^Egu0^Eku0^Emu0^Esu0; \
Du1 = Ebe1^Ege1^Eke1^Eme1^Ese1; \
Da0 = Cx^ROL32(Du1, 1); \
Cz = Ebu1^Egu1^Eku1^Emu1^Esu1; \
Du0 = Ebe0^Ege0^Eke0^Eme0^Ese0; \
Da1 = Cz^Du0; \
\
Cw = Ebi0^Egi0^Eki0^Emi0^Esi0; \
Do0 = Cw^ROL32(Cz, 1); \
Cy = Ebi1^Egi1^Eki1^Emi1^Esi1; \
Do1 = Cy^Cx; \
\
Cx = Eba0^Ega0^Eka0^Ema0^Esa0; \
De0 = Cx^ROL32(Cy, 1); \
Cz = Eba1^Ega1^Eka1^Ema1^Esa1; \
De1 = Cz^Cw; \
\
Cy = Ebo1^Ego1^Eko1^Emo1^Eso1; \
Di0 = Du0^ROL32(Cy, 1); \
Cw = Ebo0^Ego0^Eko0^Emo0^Eso0; \
Di1 = Du1^Cw; \
\
Du0 = Cw^ROL32(Cz, 1); \
Du1 = Cy^Cx; \
\
Eba0 ^= Da0; \
Ba = Eba0; \
Ege0 ^= De0; \
Be = ROL32(Ege0, 22); \
Eki1 ^= Di1; \
Bi = ROL32(Eki1, 22); \
Emo1 ^= Do1; \
Bo = ROL32(Emo1, 11); \
Esu0 ^= Du0; \
Bu = ROL32(Esu0, 7); \
Aba0 = Ba ^((~Be)& Bi ); \
Aba0 ^= *(pRoundConstants++); \
Abe0 = Be ^((~Bi)& Bo ); \
Abi0 = Bi ^((~Bo)& Bu ); \
Abo0 = Bo ^((~Bu)& Ba ); \
Abu0 = Bu ^((~Ba)& Be ); \
\
Ebo0 ^= Do0; \
Ba = ROL32(Ebo0, 14); \
Egu0 ^= Du0; \
Be = ROL32(Egu0, 10); \
Eka1 ^= Da1; \
Bi = ROL32(Eka1, 2); \
Eme1 ^= De1; \
Bo = ROL32(Eme1, 23); \
Esi1 ^= Di1; \
Bu = ROL32(Esi1, 31); \
Aga0 = Ba ^((~Be)& Bi ); \
Age0 = Be ^((~Bi)& Bo ); \
Agi0 = Bi ^((~Bo)& Bu ); \
Ago0 = Bo ^((~Bu)& Ba ); \
Agu0 = Bu ^((~Ba)& Be ); \
\
Ebe1 ^= De1; \
Ba = ROL32(Ebe1, 1); \
Egi0 ^= Di0; \
Be = ROL32(Egi0, 3); \
Eko1 ^= Do1; \
Bi = ROL32(Eko1, 13); \
Emu0 ^= Du0; \
Bo = ROL32(Emu0, 4); \
Esa0 ^= Da0; \
Bu = ROL32(Esa0, 9); \
Aka0 = Ba ^((~Be)& Bi ); \
Ake0 = Be ^((~Bi)& Bo ); \
Aki0 = Bi ^((~Bo)& Bu ); \
Ako0 = Bo ^((~Bu)& Ba ); \
Aku0 = Bu ^((~Ba)& Be ); \
\
Ebu1 ^= Du1; \
Ba = ROL32(Ebu1, 14); \
Ega0 ^= Da0; \
Be = ROL32(Ega0, 18); \
Eke0 ^= De0; \
Bi = ROL32(Eke0, 5); \
Emi1 ^= Di1; \
Bo = ROL32(Emi1, 8); \
Eso0 ^= Do0; \
Bu = ROL32(Eso0, 28); \
Ama0 = Ba ^((~Be)& Bi ); \
Ame0 = Be ^((~Bi)& Bo ); \
Ami0 = Bi ^((~Bo)& Bu ); \
Amo0 = Bo ^((~Bu)& Ba ); \
Amu0 = Bu ^((~Ba)& Be ); \
\
Ebi0 ^= Di0; \
Ba = ROL32(Ebi0, 31); \
Ego1 ^= Do1; \
Be = ROL32(Ego1, 28); \
Eku1 ^= Du1; \
Bi = ROL32(Eku1, 20); \
Ema1 ^= Da1; \
Bo = ROL32(Ema1, 21); \
Ese0 ^= De0; \
Bu = ROL32(Ese0, 1); \
Asa0 = Ba ^((~Be)& Bi ); \
Ase0 = Be ^((~Bi)& Bo ); \
Asi0 = Bi ^((~Bo)& Bu ); \
Aso0 = Bo ^((~Bu)& Ba ); \
Asu0 = Bu ^((~Ba)& Be ); \
\
Eba1 ^= Da1; \
Ba = Eba1; \
Ege1 ^= De1; \
Be = ROL32(Ege1, 22); \
Eki0 ^= Di0; \
Bi = ROL32(Eki0, 21); \
Emo0 ^= Do0; \
Bo = ROL32(Emo0, 10); \
Esu1 ^= Du1; \
Bu = ROL32(Esu1, 7); \
Aba1 = Ba ^((~Be)& Bi ); \
Aba1 ^= *(pRoundConstants++); \
Abe1 = Be ^((~Bi)& Bo ); \
Abi1 = Bi ^((~Bo)& Bu ); \
Abo1 = Bo ^((~Bu)& Ba ); \
Abu1 = Bu ^((~Ba)& Be ); \
\
Ebo1 ^= Do1; \
Ba = ROL32(Ebo1, 14); \
Egu1 ^= Du1; \
Be = ROL32(Egu1, 10); \
Eka0 ^= Da0; \
Bi = ROL32(Eka0, 1); \
Eme0 ^= De0; \
Bo = ROL32(Eme0, 22); \
Esi0 ^= Di0; \
Bu = ROL32(Esi0, 30); \
Aga1 = Ba ^((~Be)& Bi ); \
Age1 = Be ^((~Bi)& Bo ); \
Agi1 = Bi ^((~Bo)& Bu ); \
Ago1 = Bo ^((~Bu)& Ba ); \
Agu1 = Bu ^((~Ba)& Be ); \
\
Ebe0 ^= De0; \
Ba = Ebe0; \
Egi1 ^= Di1; \
Be = ROL32(Egi1, 3); \
Eko0 ^= Do0; \
Bi = ROL32(Eko0, 12); \
Emu1 ^= Du1; \
Bo = ROL32(Emu1, 4); \
Esa1 ^= Da1; \
Bu = ROL32(Esa1, 9); \
Aka1 = Ba ^((~Be)& Bi ); \
Ake1 = Be ^((~Bi)& Bo ); \
Aki1 = Bi ^((~Bo)& Bu ); \
Ako1 = Bo ^((~Bu)& Ba ); \
Aku1 = Bu ^((~Ba)& Be ); \
\
Ebu0 ^= Du0; \
Ba = ROL32(Ebu0, 13); \
Ega1 ^= Da1; \
Be = ROL32(Ega1, 18); \
Eke1 ^= De1; \
Bi = ROL32(Eke1, 5); \
Emi0 ^= Di0; \
Bo = ROL32(Emi0, 7); \
Eso1 ^= Do1; \
Bu = ROL32(Eso1, 28); \
Ama1 = Ba ^((~Be)& Bi ); \
Ame1 = Be ^((~Bi)& Bo ); \
Ami1 = Bi ^((~Bo)& Bu ); \
Amo1 = Bo ^((~Bu)& Ba ); \
Amu1 = Bu ^((~Ba)& Be ); \
\
Ebi1 ^= Di1; \
Ba = ROL32(Ebi1, 31); \
Ego0 ^= Do0; \
Be = ROL32(Ego0, 27); \
Eku0 ^= Du0; \
Bi = ROL32(Eku0, 19); \
Ema0 ^= Da0; \
Bo = ROL32(Ema0, 20); \
Ese1 ^= De1; \
Bu = ROL32(Ese1, 1); \
Asa1 = Ba ^((~Be)& Bi ); \
Ase1 = Be ^((~Bi)& Bo ); \
Asi1 = Bi ^((~Bo)& Bu ); \
Aso1 = Bo ^((~Bu)& Ba ); \
Asu1 = Bu ^((~Ba)& Be ); \
} \
copyToState(state, A) \
}
#define copyFromState(X, state) \
X##ba0 = state[ 0]; \
X##ba1 = state[ 1]; \
X##be0 = state[ 2]; \
X##be1 = state[ 3]; \
X##bi0 = state[ 4]; \
X##bi1 = state[ 5]; \
X##bo0 = state[ 6]; \
X##bo1 = state[ 7]; \
X##bu0 = state[ 8]; \
X##bu1 = state[ 9]; \
X##ga0 = state[10]; \
X##ga1 = state[11]; \
X##ge0 = state[12]; \
X##ge1 = state[13]; \
X##gi0 = state[14]; \
X##gi1 = state[15]; \
X##go0 = state[16]; \
X##go1 = state[17]; \
X##gu0 = state[18]; \
X##gu1 = state[19]; \
X##ka0 = state[20]; \
X##ka1 = state[21]; \
X##ke0 = state[22]; \
X##ke1 = state[23]; \
X##ki0 = state[24]; \
X##ki1 = state[25]; \
X##ko0 = state[26]; \
X##ko1 = state[27]; \
X##ku0 = state[28]; \
X##ku1 = state[29]; \
X##ma0 = state[30]; \
X##ma1 = state[31]; \
X##me0 = state[32]; \
X##me1 = state[33]; \
X##mi0 = state[34]; \
X##mi1 = state[35]; \
X##mo0 = state[36]; \
X##mo1 = state[37]; \
X##mu0 = state[38]; \
X##mu1 = state[39]; \
X##sa0 = state[40]; \
X##sa1 = state[41]; \
X##se0 = state[42]; \
X##se1 = state[43]; \
X##si0 = state[44]; \
X##si1 = state[45]; \
X##so0 = state[46]; \
X##so1 = state[47]; \
X##su0 = state[48]; \
X##su1 = state[49]; \
#define copyToState(state, X) \
state[ 0] = X##ba0; \
state[ 1] = X##ba1; \
state[ 2] = X##be0; \
state[ 3] = X##be1; \
state[ 4] = X##bi0; \
state[ 5] = X##bi1; \
state[ 6] = X##bo0; \
state[ 7] = X##bo1; \
state[ 8] = X##bu0; \
state[ 9] = X##bu1; \
state[10] = X##ga0; \
state[11] = X##ga1; \
state[12] = X##ge0; \
state[13] = X##ge1; \
state[14] = X##gi0; \
state[15] = X##gi1; \
state[16] = X##go0; \
state[17] = X##go1; \
state[18] = X##gu0; \
state[19] = X##gu1; \
state[20] = X##ka0; \
state[21] = X##ka1; \
state[22] = X##ke0; \
state[23] = X##ke1; \
state[24] = X##ki0; \
state[25] = X##ki1; \
state[26] = X##ko0; \
state[27] = X##ko1; \
state[28] = X##ku0; \
state[29] = X##ku1; \
state[30] = X##ma0; \
state[31] = X##ma1; \
state[32] = X##me0; \
state[33] = X##me1; \
state[34] = X##mi0; \
state[35] = X##mi1; \
state[36] = X##mo0; \
state[37] = X##mo1; \
state[38] = X##mu0; \
state[39] = X##mu1; \
state[40] = X##sa0; \
state[41] = X##sa1; \
state[42] = X##se0; \
state[43] = X##se1; \
state[44] = X##si0; \
state[45] = X##si1; \
state[46] = X##so0; \
state[47] = X##so1; \
state[48] = X##su0; \
state[49] = X##su1; \
#endif
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+26
View File
@@ -0,0 +1,26 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifdef UseSchedule
#if (UseSchedule == 1)
#include "KeccakF-1600-32-s1.h"
#elif (UseSchedule == 2)
#include "KeccakF-1600-32-s2.h"
#elif (UseSchedule == 3)
#include "KeccakF-1600-32-rvk.h"
#else
#error "This schedule is not supported."
#endif
#else
#include "KeccakF-1600-32-s1.h"
#endif
@@ -0,0 +1,6 @@
#define ProvideFast576
#define ProvideFast832
#define ProvideFast1024
#define ProvideFast1088
#define ProvideFast1152
#define ProvideFast1344
@@ -0,0 +1,51 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakPermutationInterface_h_
#define _KeccakPermutationInterface_h_
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef uint64_t UINT64;
#include "KeccakF-1600-int-set.h"
void KeccakInitialize( void );
void KeccakInitializeState(unsigned char *state);
void KeccakPermutation(unsigned char *state);
#ifdef ProvideFast576
void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast832
void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1024
void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1088
void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1152
void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data);
#endif
#ifdef ProvideFast1344
void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data);
#endif
void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount);
#ifdef ProvideFast1024
void KeccakExtract1024bits(const unsigned char *state, unsigned char *data);
#endif
void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount);
#endif
@@ -0,0 +1,6 @@
#define Unrolling 2
#define UseSchedule 3
/*
#define UseBebigokimisa
#define UseInterleaveTables
*/
+519
View File
@@ -0,0 +1,519 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include "brg_endian.h"
#include "KeccakF-1600-opt32-settings.h"
#include "KeccakF-1600-interface.h"
#ifdef UseInterleaveTables
static int interleaveTablesBuilt = 0;
static UINT16 interleaveTable[65536];
static UINT16 deinterleaveTable[65536];
static void buildInterleaveTables()
{
UINT32 i, j;
UINT16 x;
if (!interleaveTablesBuilt) {
for(i=0; i<65536; i++) {
x = 0;
for(j=0; j<16; j++) {
if (i & (1 << j))
x |= (1 << (j/2 + 8*(j%2)));
}
interleaveTable[i] = x;
deinterleaveTable[x] = (UINT16)i;
}
interleaveTablesBuilt = 1;
}
}
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#define xor2bytesIntoInterleavedWords(even, odd, source, j) \
i##j = interleaveTable[((const UINT16*)source)[j]]; \
((UINT8*)even)[j] ^= i##j & 0xFF; \
((UINT8*)odd)[j] ^= i##j >> 8;
#define setInterleavedWordsInto2bytes(dest, even, odd, j) \
d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \
((UINT16*)dest)[j] = d##j;
#else /* (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) */
#define xor2bytesIntoInterleavedWords(even, odd, source, j) \
i##j = interleaveTable[source[2*j] ^ ((UINT16)source[2*j+1] << 8)]; \
*even ^= (i##j & 0xFF) << (j*8); \
*odd ^= ((i##j >> 8) & 0xFF) << (j*8);
#define setInterleavedWordsInto2bytes(dest, even, odd, j) \
d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \
dest[2*j] = d##j & 0xFF; \
dest[2*j+1] = d##j >> 8;
#endif /* Endianness */
static void xor8bytesIntoInterleavedWords(UINT32 *even, UINT32 *odd, const UINT8* source)
{
UINT16 i0, i1, i2, i3;
xor2bytesIntoInterleavedWords(even, odd, source, 0)
xor2bytesIntoInterleavedWords(even, odd, source, 1)
xor2bytesIntoInterleavedWords(even, odd, source, 2)
xor2bytesIntoInterleavedWords(even, odd, source, 3)
}
#define xorLanesIntoState(laneCount, state, input) \
{ \
int i; \
for(i=0; i<(laneCount); i++) \
xor8bytesIntoInterleavedWords(state+i*2, state+i*2+1, input+i*8); \
}
static void setInterleavedWordsInto8bytes(UINT8* dest, UINT32 even, UINT32 odd)
{
UINT16 d0, d1, d2, d3;
setInterleavedWordsInto2bytes(dest, even, odd, 0)
setInterleavedWordsInto2bytes(dest, even, odd, 1)
setInterleavedWordsInto2bytes(dest, even, odd, 2)
setInterleavedWordsInto2bytes(dest, even, odd, 3)
}
#define extractLanes(laneCount, state, data) \
{ \
int i; \
for(i=0; i<(laneCount); i++) \
setInterleavedWordsInto8bytes(data+i*8, ((UINT32*)state)[i*2], ((UINT32*)state)[i*2+1]); \
}
#else /* No interleaving tables */
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
/* Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
#define xorInterleavedLE(rateInLanes, state, input) \
{ \
const UINT32 * pI = (const UINT32 *)input; \
UINT32 * pS = state; \
UINT32 t, x0, x1; \
int i; \
for (i = (rateInLanes)-1; i >= 0; --i) \
{ \
x0 = *(pI++); \
t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); \
t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); \
t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); \
t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); \
x1 = *(pI++); \
t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); \
t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); \
t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); \
t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); \
*(pS++) ^= (UINT16)x0 | (x1 << 16); \
*(pS++) ^= (x0 >> 16) | (x1 & 0xFFFF0000); \
} \
}
#define xorLanesIntoState(laneCount, state, input) \
xorInterleavedLE(laneCount, state, input)
#else /* (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) */
/* Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
UINT64 toInterleaving(UINT64 x)
{
UINT64 t;
t = (x ^ (x >> 1)) & 0x2222222222222222ULL; x = x ^ t ^ (t << 1);
t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CULL; x = x ^ t ^ (t << 2);
t = (x ^ (x >> 4)) & 0x00F000F000F000F0ULL; x = x ^ t ^ (t << 4);
t = (x ^ (x >> 8)) & 0x0000FF000000FF00ULL; x = x ^ t ^ (t << 8);
t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL; x = x ^ t ^ (t << 16);
return x;
}
static void xor8bytesIntoInterleavedWords(UINT32* evenAndOdd, const UINT8* source)
{
/* This can be optimized */
UINT64 sourceWord =
(UINT64)source[0]
^ (((UINT64)source[1]) << 8)
^ (((UINT64)source[2]) << 16)
^ (((UINT64)source[3]) << 24)
^ (((UINT64)source[4]) << 32)
^ (((UINT64)source[5]) << 40)
^ (((UINT64)source[6]) << 48)
^ (((UINT64)source[7]) << 56);
UINT64 evenAndOddWord = toInterleaving(sourceWord);
evenAndOdd[0] ^= (UINT32)evenAndOddWord;
evenAndOdd[1] ^= (UINT32)(evenAndOddWord >> 32);
}
#define xorLanesIntoState(laneCount, state, input) \
{ \
int i; \
for(i=0; i<(laneCount); i++) \
xor8bytesIntoInterleavedWords(state+i*2, input+i*8); \
}
#endif /* Endianness */
/* Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
UINT64 fromInterleaving(UINT64 x)
{
UINT64 t;
t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL; x = x ^ t ^ (t << 16);
t = (x ^ (x >> 8)) & 0x0000FF000000FF00ULL; x = x ^ t ^ (t << 8);
t = (x ^ (x >> 4)) & 0x00F000F000F000F0ULL; x = x ^ t ^ (t << 4);
t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CULL; x = x ^ t ^ (t << 2);
t = (x ^ (x >> 1)) & 0x2222222222222222ULL; x = x ^ t ^ (t << 1);
return x;
}
static void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
((UINT64*)dest)[0] = fromInterleaving(*(UINT64*)evenAndOdd);
#else /* (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) */
/* This can be optimized */
UINT64 evenAndOddWord = (UINT64)evenAndOdd[0] ^ ((UINT64)evenAndOdd[1] << 32);
UINT64 destWord = fromInterleaving(evenAndOddWord);
dest[0] = destWord & 0xFF;
dest[1] = (destWord >> 8) & 0xFF;
dest[2] = (destWord >> 16) & 0xFF;
dest[3] = (destWord >> 24) & 0xFF;
dest[4] = (destWord >> 32) & 0xFF;
dest[5] = (destWord >> 40) & 0xFF;
dest[6] = (destWord >> 48) & 0xFF;
dest[7] = (destWord >> 56) & 0xFF;
#endif /* Endianness */
}
#define extractLanes(laneCount, state, data) \
{ \
int i; \
for(i=0; i<(laneCount); i++) \
setInterleavedWordsInto8bytes(data+i*8, (UINT32*)state+i*2); \
}
#endif /* With or without interleaving tables */
#if defined(_MSC_VER)
#define ROL32(a, offset) _rotl(a, offset)
#elif (defined (__arm__) && defined(__ARMCC_VERSION))
#define ROL32(a, offset) __ror(a, 32-(offset))
#else
#define ROL32(a, offset) ((((UINT32)a) << (offset)) ^ (((UINT32)a) >> (32-(offset))))
#endif
#include "KeccakF-1600-unrolling.h"
#include "KeccakF-1600-32.h"
#if (UseSchedule == 3)
#ifdef UseBebigokimisa
#error "No lane complementing with schedule 3."
#endif
#if (Unrolling != 2)
#error "Only unrolling 2 is supported by schedule 3."
#endif
static void KeccakPermutationOnWords(UINT32 *state)
{
rounds
}
static void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount)
{
xorLanesIntoState(laneCount, state, input)
rounds
}
#ifdef ProvideFast576
static void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input)
{
xorLanesIntoState(9, state, input)
rounds
}
#endif
#ifdef ProvideFast832
static void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input)
{
xorLanesIntoState(13, state, input)
rounds
}
#endif
#ifdef ProvideFast1024
static void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input)
{
xorLanesIntoState(16, state, input)
rounds
}
#endif
#ifdef ProvideFast1088
static void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input)
{
xorLanesIntoState(17, state, input)
rounds
}
#endif
#ifdef ProvideFast1152
static void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input)
{
xorLanesIntoState(18, state, input)
rounds
}
#endif
#ifdef ProvideFast1344
static void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input)
{
xorLanesIntoState(21, state, input)
rounds
}
#endif
#else /* (Schedule != 3) */
static void KeccakPermutationOnWords(UINT32 *state)
{
declareABCDE
#if (Unrolling != 24)
unsigned int i;
#endif
copyFromState(A, state)
rounds
}
static void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount)
{
declareABCDE
unsigned int i;
xorLanesIntoState(laneCount, state, input)
copyFromState(A, state)
rounds
}
#ifdef ProvideFast576
static void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input)
{
declareABCDE
unsigned int i;
xorLanesIntoState(9, state, input)
copyFromState(A, state)
rounds
}
#endif
#ifdef ProvideFast832
static void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input)
{
declareABCDE
unsigned int i;
xorLanesIntoState(13, state, input)
copyFromState(A, state)
rounds
}
#endif
#ifdef ProvideFast1024
static void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input)
{
declareABCDE
unsigned int i;
xorLanesIntoState(16, state, input)
copyFromState(A, state)
rounds
}
#endif
#ifdef ProvideFast1088
static void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input)
{
declareABCDE
unsigned int i;
xorLanesIntoState(17, state, input)
copyFromState(A, state)
rounds
}
#endif
#ifdef ProvideFast1152
static void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input)
{
declareABCDE
unsigned int i;
xorLanesIntoState(18, state, input)
copyFromState(A, state)
rounds
}
#endif
#ifdef ProvideFast1344
static void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input)
{
declareABCDE
unsigned int i;
xorLanesIntoState(21, state, input)
copyFromState(A, state)
rounds
}
#endif
#endif
void KeccakInitialize()
{
#ifdef UseInterleaveTables
buildInterleaveTables();
#endif
}
void KeccakInitializeState(unsigned char *state)
{
memset(state, 0, 200);
#ifdef UseBebigokimisa
((UINT32*)state)[ 2] = ~(UINT32)0;
((UINT32*)state)[ 3] = ~(UINT32)0;
((UINT32*)state)[ 4] = ~(UINT32)0;
((UINT32*)state)[ 5] = ~(UINT32)0;
((UINT32*)state)[16] = ~(UINT32)0;
((UINT32*)state)[17] = ~(UINT32)0;
((UINT32*)state)[24] = ~(UINT32)0;
((UINT32*)state)[25] = ~(UINT32)0;
((UINT32*)state)[34] = ~(UINT32)0;
((UINT32*)state)[35] = ~(UINT32)0;
((UINT32*)state)[40] = ~(UINT32)0;
((UINT32*)state)[41] = ~(UINT32)0;
#endif
}
void KeccakPermutation(unsigned char *state)
{
/* We assume the state is always stored as interleaved 32-bit words */
KeccakPermutationOnWords((UINT32*)state);
}
#ifdef ProvideFast576
void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data)
{
KeccakPermutationOnWordsAfterXoring576bits((UINT32*)state, data);
}
#endif
#ifdef ProvideFast832
void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data)
{
KeccakPermutationOnWordsAfterXoring832bits((UINT32*)state, data);
}
#endif
#ifdef ProvideFast1024
void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data)
{
KeccakPermutationOnWordsAfterXoring1024bits((UINT32*)state, data);
}
#endif
#ifdef ProvideFast1088
void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data)
{
KeccakPermutationOnWordsAfterXoring1088bits((UINT32*)state, data);
}
#endif
#ifdef ProvideFast1152
void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data)
{
KeccakPermutationOnWordsAfterXoring1152bits((UINT32*)state, data);
}
#endif
#ifdef ProvideFast1344
void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data)
{
KeccakPermutationOnWordsAfterXoring1344bits((UINT32*)state, data);
}
#endif
void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount)
{
KeccakPermutationOnWordsAfterXoring((UINT32*)state, data, laneCount);
}
#ifdef ProvideFast1024
void KeccakExtract1024bits(const unsigned char *state, unsigned char *data)
{
extractLanes(16, state, data)
#ifdef UseBebigokimisa
((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2];
((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3];
((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4];
((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5];
((UINT32*)data)[16] = ~((UINT32*)data)[16];
((UINT32*)data)[17] = ~((UINT32*)data)[17];
((UINT32*)data)[24] = ~((UINT32*)data)[24];
((UINT32*)data)[25] = ~((UINT32*)data)[25];
#endif
}
#endif
void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount)
{
extractLanes(laneCount, state, data)
#ifdef UseBebigokimisa
if (laneCount > 1) {
((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2];
((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3];
if (laneCount > 2) {
((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4];
((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5];
if (laneCount > 8) {
((UINT32*)data)[16] = ~((UINT32*)data)[16];
((UINT32*)data)[17] = ~((UINT32*)data)[17];
if (laneCount > 12) {
((UINT32*)data)[24] = ~((UINT32*)data)[24];
((UINT32*)data)[25] = ~((UINT32*)data)[25];
if (laneCount > 17) {
((UINT32*)data)[34] = ~((UINT32*)data)[34];
((UINT32*)data)[35] = ~((UINT32*)data)[35];
if (laneCount > 20) {
((UINT32*)data)[40] = ~((UINT32*)data)[40];
((UINT32*)data)[41] = ~((UINT32*)data)[41];
}
}
}
}
}
}
#endif
}
@@ -0,0 +1,128 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _Keccak1600_unrolling_h_
#define _Keccak1600_unrolling_h_
#if (Unrolling == 24)
#define rounds \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
thetaRhoPiChiIotaPrepareTheta(10, A, E) \
thetaRhoPiChiIotaPrepareTheta(11, E, A) \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
copyToState(state, A)
#elif (Unrolling == 12)
#define rounds \
prepareTheta \
for(i=0; i<24; i+=12) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
} \
copyToState(state, A)
#elif (Unrolling == 8)
#define rounds \
prepareTheta \
for(i=0; i<24; i+=8) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+6, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+7, E, A) \
} \
copyToState(state, A)
#elif (Unrolling == 6)
#define rounds \
prepareTheta \
for(i=0; i<24; i+=6) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
} \
copyToState(state, A)
#elif (Unrolling == 4)
#define rounds \
prepareTheta \
for(i=0; i<24; i+=4) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
} \
copyToState(state, A)
#elif (Unrolling == 3)
#define rounds \
prepareTheta \
for(i=0; i<24; i+=3) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
copyStateVariables(A, E) \
} \
copyToState(state, A)
#elif (Unrolling == 2)
#define rounds \
prepareTheta \
for(i=0; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
copyToState(state, A)
#elif (Unrolling == 1)
#define rounds \
prepareTheta \
for(i=0; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
copyToState(state, A)
#else
#error "Unrolling is not correctly specified!"
#endif
#endif
@@ -0,0 +1,83 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include "KeccakNISTInterface.h"
#include "KeccakF-1600-interface.h"
HashReturn Init(hashState *state, int hashbitlen)
{
switch(hashbitlen) {
case 0: /* Default parameters, arbitrary length output */
InitSponge((spongeState*)state, 1024, 576);
break;
case 224:
InitSponge((spongeState*)state, 1152, 448);
break;
case 256:
InitSponge((spongeState*)state, 1088, 512);
break;
case 384:
InitSponge((spongeState*)state, 832, 768);
break;
case 512:
InitSponge((spongeState*)state, 576, 1024);
break;
default:
return BAD_HASHLEN;
}
state->fixedOutputLength = hashbitlen;
return SUCCESS;
}
HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen)
{
if ((databitlen % 8) == 0)
return Absorb((spongeState*)state, data, databitlen);
else {
HashReturn ret = Absorb((spongeState*)state, data, databitlen - (databitlen % 8));
if (ret == SUCCESS) {
unsigned char lastByte;
/* Align the last partial byte to the least significant bits */
lastByte = data[databitlen/8] >> (8 - (databitlen % 8));
return Absorb((spongeState*)state, &lastByte, databitlen % 8);
}
else
return ret;
}
}
HashReturn Final(hashState *state, BitSequence *hashval)
{
return Squeeze(state, hashval, state->fixedOutputLength);
}
/*
static HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval)
{
hashState state;
HashReturn result;
if ((hashbitlen != 224) && (hashbitlen != 256) && (hashbitlen != 384) && (hashbitlen != 512))
return BAD_HASHLEN; * Only the four fixed output lengths available through this API *
result = Init(&state, hashbitlen);
if (result != SUCCESS)
return result;
result = Update(&state, data, databitlen);
if (result != SUCCESS)
return result;
result = Final(&state, hashval);
return result;
}
*/
@@ -0,0 +1,72 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakNISTInterface_h_
#define _KeccakNISTInterface_h_
#include "KeccakSponge.h"
typedef unsigned char BitSequence;
typedef unsigned long long DataLength;
typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
typedef spongeState hashState;
/**
* Function to initialize the state of the Keccak[r, c] sponge function.
* The rate r and capacity c values are determined from @a hashbitlen.
* @param state Pointer to the state of the sponge function to be initialized.
* @param hashbitlen The desired number of output bits,
* or 0 for Keccak[] with default parameters
* and arbitrarily-long output.
* @pre The value of hashbitlen must be one of 0, 224, 256, 384 and 512.
* @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect.
*/
HashReturn Init(hashState *state, int hashbitlen);
/**
* Function to give input data for the sponge function to absorb.
* @param state Pointer to the state of the sponge function initialized by Init().
* @param data Pointer to the input data.
* When @a databitLen is not a multiple of 8, the last bits of data must be
* in the most significant bits of the last byte.
* @param databitLen The number of input bits provided in the input data.
* @pre In the previous call to Absorb(), databitLen was a multiple of 8.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen);
/**
* Function to squeeze output data from the sponge function.
* If @a hashbitlen was not 0 in the call to Init(), the number of output bits is equal to @a hashbitlen.
* If @a hashbitlen was 0 in the call to Init(), the output bits must be extracted using the Squeeze() function.
* @param state Pointer to the state of the sponge function initialized by Init().
* @param hashval Pointer to the buffer where to store the output data.
* @return SUCCESS if successful, FAIL otherwise.
*/
HashReturn Final(hashState *state, BitSequence *hashval);
/**
* Function to compute a hash using the Keccak[r, c] sponge function.
* The rate r and capacity c values are determined from @a hashbitlen.
* @param hashbitlen The desired number of output bits.
* @param data Pointer to the input data.
* When @a databitLen is not a multiple of 8, the last bits of data must be
* in the most significant bits of the last byte.
* @param databitLen The number of input bits provided in the input data.
* @param hashval Pointer to the buffer where to store the output data.
* @pre The value of hashbitlen must be one of 224, 256, 384 and 512.
* @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect.
*/
/*
static HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval);
*/
#endif
+266
View File
@@ -0,0 +1,266 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include "KeccakSponge.h"
#include "KeccakF-1600-interface.h"
#ifdef KeccakReference
#include "displayIntermediateValues.h"
#endif
int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity)
{
if (rate+capacity != 1600)
return 1;
if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))
return 1;
KeccakInitialize();
state->rate = rate;
state->capacity = capacity;
state->fixedOutputLength = 0;
KeccakInitializeState(state->state);
memset(state->dataQueue, 0, KeccakMaximumRateInBytes);
state->bitsInQueue = 0;
state->squeezing = 0;
state->bitsAvailableForSqueezing = 0;
return 0;
}
static void AbsorbQueue(spongeState *state)
{
/* state->bitsInQueue is assumed to be equal to state->rate */
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", state->dataQueue, state->rate/8);
#endif
#ifdef ProvideFast576
if (state->rate == 576)
KeccakAbsorb576bits(state->state, state->dataQueue);
else
#endif
#ifdef ProvideFast832
if (state->rate == 832)
KeccakAbsorb832bits(state->state, state->dataQueue);
else
#endif
#ifdef ProvideFast1024
if (state->rate == 1024)
KeccakAbsorb1024bits(state->state, state->dataQueue);
else
#endif
#ifdef ProvideFast1088
if (state->rate == 1088)
KeccakAbsorb1088bits(state->state, state->dataQueue);
else
#endif
#ifdef ProvideFast1152
if (state->rate == 1152)
KeccakAbsorb1152bits(state->state, state->dataQueue);
else
#endif
#ifdef ProvideFast1344
if (state->rate == 1344)
KeccakAbsorb1344bits(state->state, state->dataQueue);
else
#endif
KeccakAbsorb(state->state, state->dataQueue, state->rate/64);
state->bitsInQueue = 0;
}
int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen)
{
unsigned long long i, j, wholeBlocks;
unsigned int partialBlock, partialByte;
const unsigned char *curData;
if ((state->bitsInQueue % 8) != 0)
return 1; /* Only the last call may contain a partial byte */
if (state->squeezing)
return 1; /* Too late for additional input */
i = 0;
while(i < databitlen) {
if ((state->bitsInQueue == 0) && (databitlen >= state->rate) && (i <= (databitlen-state->rate))) {
wholeBlocks = (databitlen-i)/state->rate;
curData = data+i/8;
#ifdef ProvideFast576
if (state->rate == 576) {
for(j=0; j<wholeBlocks; j++, curData+=576/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb576bits(state->state, curData);
}
}
else
#endif
#ifdef ProvideFast832
if (state->rate == 832) {
for(j=0; j<wholeBlocks; j++, curData+=832/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb832bits(state->state, curData);
}
}
else
#endif
#ifdef ProvideFast1024
if (state->rate == 1024) {
for(j=0; j<wholeBlocks; j++, curData+=1024/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb1024bits(state->state, curData);
}
}
else
#endif
#ifdef ProvideFast1088
if (state->rate == 1088) {
for(j=0; j<wholeBlocks; j++, curData+=1088/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb1088bits(state->state, curData);
}
}
else
#endif
#ifdef ProvideFast1152
if (state->rate == 1152) {
for(j=0; j<wholeBlocks; j++, curData+=1152/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb1152bits(state->state, curData);
}
}
else
#endif
#ifdef ProvideFast1344
if (state->rate == 1344) {
for(j=0; j<wholeBlocks; j++, curData+=1344/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb1344bits(state->state, curData);
}
}
else
#endif
{
for(j=0; j<wholeBlocks; j++, curData+=state->rate/8) {
#ifdef KeccakReference
displayBytes(1, "Block to be absorbed", curData, state->rate/8);
#endif
KeccakAbsorb(state->state, curData, state->rate/64);
}
}
i += wholeBlocks*state->rate;
}
else {
partialBlock = (unsigned int)(databitlen - i);
if (partialBlock+state->bitsInQueue > state->rate)
partialBlock = state->rate-state->bitsInQueue;
partialByte = partialBlock % 8;
partialBlock -= partialByte;
memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8);
state->bitsInQueue += partialBlock;
i += partialBlock;
if (state->bitsInQueue == state->rate)
AbsorbQueue(state);
if (partialByte > 0) {
unsigned char mask = (1 << partialByte)-1;
state->dataQueue[state->bitsInQueue/8] = data[i/8] & mask;
state->bitsInQueue += partialByte;
i += partialByte;
}
}
}
return 0;
}
static void PadAndSwitchToSqueezingPhase(spongeState *state)
{
/* Note: the bits are numbered from 0=LSB to 7=MSB */
if (state->bitsInQueue + 1 == state->rate) {
state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8);
AbsorbQueue(state);
memset(state->dataQueue, 0, state->rate/8);
}
else {
memset(state->dataQueue + (state->bitsInQueue+7)/8, 0, state->rate/8 - (state->bitsInQueue+7)/8);
state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8);
}
state->dataQueue[(state->rate-1)/8] |= 1 << ((state->rate-1) % 8);
AbsorbQueue(state);
#ifdef KeccakReference
displayText(1, "--- Switching to squeezing phase ---");
#endif
#ifdef ProvideFast1024
if (state->rate == 1024) {
KeccakExtract1024bits(state->state, state->dataQueue);
state->bitsAvailableForSqueezing = 1024;
}
else
#endif
{
KeccakExtract(state->state, state->dataQueue, state->rate/64);
state->bitsAvailableForSqueezing = state->rate;
}
#ifdef KeccakReference
displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8);
#endif
state->squeezing = 1;
}
int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength)
{
unsigned long long i;
unsigned int partialBlock;
if (!state->squeezing)
PadAndSwitchToSqueezingPhase(state);
if ((outputLength % 8) != 0)
return 1; /* Only multiple of 8 bits are allowed, truncation can be done at user level */
i = 0;
while(i < outputLength) {
if (state->bitsAvailableForSqueezing == 0) {
KeccakPermutation(state->state);
#ifdef ProvideFast1024
if (state->rate == 1024) {
KeccakExtract1024bits(state->state, state->dataQueue);
state->bitsAvailableForSqueezing = 1024;
}
else
#endif
{
KeccakExtract(state->state, state->dataQueue, state->rate/64);
state->bitsAvailableForSqueezing = state->rate;
}
#ifdef KeccakReference
displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8);
#endif
}
partialBlock = state->bitsAvailableForSqueezing;
if ((unsigned long long)partialBlock > outputLength - i)
partialBlock = (unsigned int)(outputLength - i);
memcpy(output+i/8, state->dataQueue+(state->rate-state->bitsAvailableForSqueezing)/8, partialBlock/8);
state->bitsAvailableForSqueezing -= partialBlock;
i += partialBlock;
}
return 0;
}
+77
View File
@@ -0,0 +1,77 @@
/*
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
Michaël Peeters and Gilles Van Assche. For more information, feedback or
questions, please refer to our website: http://keccak.noekeon.org/
Implementation by the designers,
hereby denoted as "the implementer".
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakSponge_h_
#define _KeccakSponge_h_
#define KeccakPermutationSize 1600
#define KeccakPermutationSizeInBytes (KeccakPermutationSize/8)
#define KeccakMaximumRate 1536
#define KeccakMaximumRateInBytes (KeccakMaximumRate/8)
#if defined(__GNUC__)
#undef ALIGN
#define ALIGN __attribute__ ((aligned(32)))
#elif defined(_MSC_VER)
#define ALIGN __declspec(align(32))
#else
#define ALIGN
#endif
ALIGN typedef struct spongeStateStruct {
ALIGN unsigned char state[KeccakPermutationSizeInBytes];
ALIGN unsigned char dataQueue[KeccakMaximumRateInBytes];
unsigned int rate;
unsigned int capacity;
unsigned int bitsInQueue;
unsigned int fixedOutputLength;
int squeezing;
unsigned int bitsAvailableForSqueezing;
} spongeState;
/**
* Function to initialize the state of the Keccak[r, c] sponge function.
* The sponge function is set to the absorbing phase.
* @param state Pointer to the state of the sponge function to be initialized.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @pre One must have r+c=1600 and the rate a multiple of 64 bits in this implementation.
* @return Zero if successful, 1 otherwise.
*/
int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity);
/**
* Function to give input data for the sponge function to absorb.
* @param state Pointer to the state of the sponge function initialized by InitSponge().
* @param data Pointer to the input data.
* When @a databitLen is not a multiple of 8, the last bits of data must be
* in the least significant bits of the last byte.
* @param databitLen The number of input bits provided in the input data.
* @pre In the previous call to Absorb(), databitLen was a multiple of 8.
* @pre The sponge function must be in the absorbing phase,
* i.e., Squeeze() must not have been called before.
* @return Zero if successful, 1 otherwise.
*/
int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen);
/**
* Function to squeeze output data from the sponge function.
* If the sponge function was in the absorbing phase, this function
* switches it to the squeezing phase.
* @param state Pointer to the state of the sponge function initialized by InitSponge().
* @param output Pointer to the buffer where to store the output data.
* @param outputLength The number of output bits desired.
* It must be a multiple of 8.
* @return Zero if successful, 1 otherwise.
*/
int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength);
#endif
+152
View File
@@ -0,0 +1,152 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
Changes for ARM 9/9/2010
*/
/* modified by justin@basho.com to include Solaris endianness test */
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#if 0
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
# include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) || \
defined (__DragonFly__)
# include <sys/types.h>
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
# include <machine/endian.h>
#elif defined (__SVR4) && defined (__sun)
# ifdef __sparc__
# define BYTE_ORDER IS_BIG_ENDIAN
# else
# define BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# if !defined( __MINGW32__ ) && !defined( _AIX )
# include <endian.h>
# if !defined( __BEOS__ )
# include <byteswap.h>
# endif
# endif
#endif
#endif
/* Now attempt to set the define for platform byte order using any */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__arm__)
# ifdef __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
#endif
#endif
#endif