Created
May 7, 2013 14:40
-
-
Save t0mm13b/5533085 to your computer and use it in GitHub Desktop.
The implementation for the specified header https://gist.github.com/t0mm13b/5533040
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <CommonCrypto/CommonDigest.h> | |
#import "PKCS12ParametersGenerator.h" | |
#define PKCS12_KEY_MATERIAL 1 | |
#define PKCS12_IV_MATERIAL 2 | |
#define PKCS12_MAC_MATERIAL 3 | |
#define NUL_TERMINATOR '\0' | |
@implementation PKCS12ParametersGenerator | |
@synthesize keySize; | |
@synthesize ivSize; | |
@synthesize derivedKey; | |
@synthesize derivedIV; | |
@synthesize password; | |
@synthesize salt; | |
@synthesize ptrPasswordBytes; | |
@synthesize ptrPasswdPCKS12Bytes; | |
@synthesize ptrSaltBytes; | |
@synthesize iterations; | |
@synthesize szPasswordLen; | |
@synthesize szSaltLen; | |
@synthesize szPasswdPKCS12Len; | |
-(id) init :(NSString *)argPassword | |
saltedHash:(NSData *)argSalt | |
iterCount:(NSInteger)argIterationCount | |
keySize:(NSInteger) argKeySize | |
initVectSize:(NSInteger) argIVSize{ | |
self = [super init]; | |
if (self){ | |
self.keySize = argKeySize / 8; | |
self.ivSize = argIVSize / 8; | |
self.password = argPassword; | |
self.salt = argSalt; | |
self.iterations = argIterationCount; | |
self.ptrPasswordBytes = (uint8_t *)[self.password cStringUsingEncoding:NSUTF8StringEncoding]; | |
self.ptrSaltBytes = (uint8_t *)[self.salt bytes]; | |
self.ptrPasswdPCKS12Bytes = [self pkcs12Password:self.ptrPasswordBytes]; | |
self.szPasswordLen = [self.password length]; | |
self.szSaltLen = [self.salt length]; | |
if (self.szPasswordLen > 0) self.szPasswdPKCS12Len = (self.szPasswordLen * 2); | |
else self.szPasswdPKCS12Len = 0; | |
//self.szPasswdPKCS12Len = strlen(self.ptrPasswdPCKS12Bytes); | |
} | |
return self; | |
} | |
-(void) dealloc{ | |
[super dealloc]; | |
[self.derivedIV release]; | |
[self.derivedKey release]; | |
self.derivedKey = nil; | |
self.derivedIV = nil; | |
self.ptrPasswordBytes = nil; | |
self.ptrSaltBytes = nil; | |
self.szPasswordLen = 0; | |
self.szSaltLen = 0; | |
} | |
-(void) generateDerivedParameters{ | |
uint8_t *lDerivedKey = [self generateDerivedKey: PKCS12_KEY_MATERIAL byteLen:self.keySize]; | |
self.derivedKey = [NSData dataWithBytesNoCopy:lDerivedKey length:self.keySize]; | |
// | |
uint8_t *lDerivedIV = [self generateDerivedKey: PKCS12_IV_MATERIAL byteLen:self.ivSize]; | |
self.derivedIV = [NSData dataWithBytesNoCopy:lDerivedIV length:self.ivSize]; | |
} | |
-(unsigned char *)generateDerivedKey :(NSInteger) iMaterialType | |
byteLen:(NSInteger)argSizeLen{ | |
int u = CC_SHA256_DIGEST_LENGTH; | |
int v = CC_SHA256_BLOCK_BYTES; | |
// | |
size_t szDLen = sizeof(unsigned char) * v; | |
unsigned char *D = malloc(szDLen + 1); | |
// | |
size_t szdKeyLen = sizeof(unsigned char) * argSizeLen; | |
unsigned char *dKey = calloc(szdKeyLen + 1, sizeof(unsigned char)); | |
// | |
for (int i = 0; i != szDLen; i++){ | |
D[i] = iMaterialType; | |
} | |
D[szDLen] = NUL_TERMINATOR; | |
// | |
unsigned char *S; | |
size_t szSLen = 0; | |
if (self.ptrSaltBytes != NULL && self.szSaltLen != 0){ | |
szSLen = sizeof(unsigned char) * (v * (((self.szSaltLen + v) - 1) / v)); // NUL terminator? | |
S = calloc(szSLen + 1, sizeof(unsigned char)); | |
// | |
for (int i = 0; i != szSLen; i++){ | |
S[i] = self.ptrSaltBytes[i % self.szSaltLen]; | |
} | |
S[self.szSaltLen] = NUL_TERMINATOR; | |
}else{ | |
szSLen = sizeof(unsigned char) * 1; | |
S = calloc(szSLen + 1, sizeof(unsigned char)); | |
S[szSLen] = NUL_TERMINATOR; | |
} | |
// | |
unsigned char *P; | |
size_t szPLen = 0; | |
if (self.ptrPasswdPCKS12Bytes != NULL && self.szPasswdPKCS12Len != 0){ | |
szPLen = sizeof(unsigned char) * (v * (((self.szPasswdPKCS12Len + v) - 1) / v)); // NUL terminator? | |
P = calloc(szPLen + 1, sizeof(unsigned char)); | |
for (int i = 0; i != self.szPasswdPKCS12Len; i++){ | |
P[i] = self.ptrPasswdPCKS12Bytes[i % self.szPasswdPKCS12Len]; | |
} | |
P[self.szPasswdPKCS12Len] = NUL_TERMINATOR; | |
}else{ | |
szPLen = sizeof(unsigned char) * 1; | |
P = calloc(szPLen + 1, sizeof(unsigned char)); | |
P[szPLen] = NUL_TERMINATOR; | |
} | |
// | |
size_t szILen = sizeof(unsigned char) * (szSLen + szPLen); | |
unsigned char *I = calloc(szILen + 1, sizeof(unsigned char)); | |
// | |
memcpy(&I[0], S, szSaltLen); | |
memcpy(&I[szSaltLen], P, szPLen); | |
I[szILen] = NUL_TERMINATOR; | |
// | |
size_t szBLen = sizeof(unsigned char) * v; | |
unsigned char *B = calloc(szBLen + 1, sizeof(unsigned char)); | |
// | |
size_t c = (argSizeLen + u - 1) / u; | |
CC_SHA256_CTX context; | |
CC_SHA256_Init(&context); | |
for (int i = 1; i <= c; i++){ | |
size_t szALen = sizeof(unsigned char) * u; | |
unsigned char *A = calloc(szALen + 1, sizeof(unsigned char)); | |
// | |
CC_SHA256_Update(&context, D, szDLen); | |
CC_SHA256_Update(&context, I, szILen); | |
CC_SHA256_Final(A, &context); | |
// | |
for (int j = 1; j != self.iterations; j++){ | |
CC_SHA256_Update(&context, A, szALen); | |
CC_SHA256_Final(A, &context); | |
} | |
// | |
A[szALen] = NUL_TERMINATOR; | |
for (int j = 0; j != szBLen; j++){ | |
B[j] = A[j % szALen]; | |
} | |
// | |
for (int j = 0; j != (szILen / v); j++){ | |
[self adjust :I | |
offset:(j * v) | |
buffer:B]; | |
} | |
// | |
if (i == c){ | |
memcpy(&dKey[(i - 1) * u], A, szdKeyLen - ((i - 1) * u)); | |
}else{ | |
memcpy(&dKey[(i - 1) * u], A, szALen); | |
} | |
if (A) free(A); | |
A = NULL; | |
} | |
if (B) free(B); | |
if (P) free(P); | |
if (S) free(S); | |
if (D) free(D); | |
B = P = S = D = NULL; | |
dKey[szdKeyLen] = NUL_TERMINATOR; | |
return dKey; | |
} | |
-(void) adjust :(unsigned char *)a offset:(size_t)aOff buffer:(unsigned char *)b{ | |
size_t szBLen = strlen(b); | |
unsigned int x = (b[szBLen-1] & 0xff) + (a[aOff + szBLen - 1] & 0xff) + 1; | |
//unsigned int x = (b[szBLen] & 0xff) + (a[aOff + szBLen] & 0xff) + 1; | |
a[aOff + szBLen - 1] = (unsigned char)x; | |
x >>= 8; | |
for (int i = szBLen - 2; i >= 0; i--){ | |
x += (b[i] & 0xff) + (a[aOff + i] & 0xff); | |
a[aOff + i] = (unsigned char)x; | |
x >>= 8; | |
} | |
} | |
-(uint8_t *) pkcs12Password : (uint8_t *)argPtrPassword{ | |
size_t lenPasswdChk = strlen(argPtrPassword); | |
uint8_t *passwordPKCS12 = NULL; | |
if (lenPasswdChk > 0){ | |
size_t lenPassword = (lenPasswdChk * 2) + 1; | |
passwordPKCS12 = calloc(lenPassword, sizeof(uint8_t)); | |
for (int i = 0; i != lenPassword; i++){ | |
passwordPKCS12[i * 2] = (uint8_t)argPtrPassword[i] >> 8; | |
passwordPKCS12[i * 2 + 1] = (uint8_t)argPtrPassword[i]; | |
} | |
passwordPKCS12[lenPassword] = NUL_TERMINATOR; | |
}else{ | |
passwordPKCS12 = calloc(1, sizeof(uint8_t)); | |
} | |
return passwordPKCS12; | |
} | |
@end |
Another issue is that the digest context is never reset. CC_SHA356_Init() should be called every time a new iteration starts (before CC_SHA256_Update).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some array lengths are wrong. I created a gist for the patch.