forked from mykeepass/KeePassLib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HashedInputData.m
132 lines (104 loc) · 3.16 KB
/
HashedInputData.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//
// HashedInputData.m
// KeePass2
//
// Created by Qiang Yu on 1/31/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <CommonCrypto/CommonDigest.h>
#import "HashedInputData.h"
#import "Kdb.h"
#import "Utils.h"
@interface HashedInputData (PrivateMethods)
-(BOOL)readBlock;
@end
@implementation HashedInputData
@synthesize _dataSource;
#pragma mark -
#pragma mark alloc/dealloc
-(id)initWithDataSource:(id<InputDataSource>)input{
if(self=[super init]){
self._dataSource = input;
_eof = NO;
}
return self;
}
-(void)dealloc{
[_block release];
[_dataSource release];
[super dealloc];
}
#pragma mark -
#pragma mark Private Methods
//
// read a block
// return YES if more to read; otherwise NO
//
-(BOOL)readBlock {
if(_eof) return NO;
if([Utils readInt32LE:_dataSource]!=_blockIndex){
@throw [NSException exceptionWithName:@"InvalidData" reason:@"InvalidBlockIndex" userInfo:nil];
}
_blockIndex++;
// read the hash
uint8_t hash[32];
if([_dataSource readBytes:hash length:32]!=32){
@throw [NSException exceptionWithName:@"InvalidData" reason:@"InvalidBlockHashSize" userInfo:nil];
}
// read the block
uint32_t blockSize = [Utils readInt32LE:_dataSource];
if(blockSize < 0){
@throw [NSException exceptionWithName:@"InvalidData" reason:@"InvalidBlockSize" userInfo:nil];
}
if(blockSize){
if(_block) [_block release];
_block = [[ByteBuffer alloc ]initWithSize:blockSize];
if([_dataSource readBytes:_block._bytes length:blockSize]!=blockSize){
@throw [NSException exceptionWithName:@"InvalidData" reason:@"InvalidBlock" userInfo:nil];
}
// verify the hashcode
uint8_t result[32];
CC_SHA256(_block._bytes, blockSize, result);
if(memcmp(result, hash, 32))
@throw [NSException exceptionWithName:@"InvalidData" reason:@"InvalidBlockHash" userInfo:nil];
return YES;
}else{ //end of block
_eof = YES;
[_block release];
_block = nil;
for(int i=0; i<32; i++){
if(hash[i])
@throw [NSException exceptionWithName:@"InvalidData" reason:@"InvalidBlockHash" userInfo:nil];
}
return NO;
}
}
#pragma mark -
#pragma mark InputDataSource Protocol
-(NSUInteger)readBytes:(void *)buffer length:(NSUInteger)length{
if(_eof) return 0;
NSUInteger remaining = length; //number of remaining bytes to read
NSUInteger bufferOffset = 0;
while (remaining>0) {
if(_block == nil || _blockOffset == _block._size){
_blockOffset = 0;
if(![self readBlock]){
return length - remaining;
}
}
NSUInteger bytesToCopy = MIN(remaining, _block._size - _blockOffset);
memcpy(buffer+bufferOffset, _block._bytes+_blockOffset, bytesToCopy);
_blockOffset+=bytesToCopy; bufferOffset+=bytesToCopy;remaining -= bytesToCopy;
}
return length;
}
-(NSUInteger)lengthOfRemainingReadbleBytes{
@throw [NSException exceptionWithName:@"UnsupportedMethod" reason:@"UnsupportedMethod" userInfo:nil];
}
-(NSUInteger)setReadOffset:(NSUInteger) offset{
@throw [NSException exceptionWithName:@"UnsupportedMethod" reason:@"UnsupportedMethod" userInfo:nil];
}
-(NSUInteger)moveReadOffset:(NSInteger) offset{
@throw [NSException exceptionWithName:@"UnsupportedMethod" reason:@"UnsupportedMethod" userInfo:nil];
}
@end