Skip to content

Instantly share code, notes, and snippets.

@t0mm13b
Created May 7, 2013 14:40
Show Gist options
  • Save t0mm13b/5533085 to your computer and use it in GitHub Desktop.
Save t0mm13b/5533085 to your computer and use it in GitHub Desktop.
The implementation for the specified header https://gist.github.com/t0mm13b/5533040
#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
@frankshaka
Copy link

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