C4Err HASH_Import(void *inData, size_t bufSize, HASH_ContextRef * ctx) { C4Err err = kC4Err_NoErr; HASH_Context* hashCTX = NULL; ValidateParam(ctx); *ctx = NULL; if(sizeof(HASH_Context) != bufSize) RETERR( kC4Err_BadParams); hashCTX = XMALLOC(sizeof (HASH_Context)); CKNULL(hashCTX); COPY( inData, hashCTX, sizeof(HASH_Context)); validateHASHContext(hashCTX); *ctx = hashCTX; done: if(IsC4Err(err)) { if(IsntNull(hashCTX)) { XFREE(hashCTX); } } return err; }
C4Err ECC_Init(ECC_ContextRef * ctx) { C4Err err = kC4Err_NoErr; ECC_Context* eccCTX = kInvalidECC_ContextRef; ValidateParam(ctx); eccCTX = XMALLOC(sizeof (ECC_Context)); CKNULL(eccCTX); eccCTX->magic = kECC_ContextMagic; CKERR; *ctx = eccCTX; done: return err; }
C4Err CBC_Init(Cipher_Algorithm algorithm, const void *key, const void *iv, CBC_ContextRef * ctxOut) { int err = kC4Err_NoErr; CBC_Context* cbcCTX = NULL; int keylen = 0; int cipher = -1; int status = CRYPT_OK; ValidateParam(ctxOut); switch(algorithm) { case kCipher_Algorithm_AES128: keylen = 128 >> 3; cipher = find_cipher("aes"); break; case kCipher_Algorithm_AES192: keylen = 192 >> 3; cipher = find_cipher("aes"); break; case kCipher_Algorithm_AES256: keylen = 256 >> 3; cipher = find_cipher("aes"); break; case kCipher_Algorithm_2FISH256: keylen = 256 >> 3; cipher = find_cipher("twofish"); break; default: RETERR(kC4Err_BadCipherNumber); } cbcCTX = XMALLOC(sizeof (CBC_Context)); CKNULL(cbcCTX); cbcCTX->magic = kCBC_ContextMagic; cbcCTX->algor = algorithm; status = cbc_start(cipher, iv, key, keylen, 0, &cbcCTX->state); CKSTAT; *ctxOut = cbcCTX; done: if(status != CRYPT_OK) { if(cbcCTX) { memset(cbcCTX, sizeof (CBC_Context), 0); XFREE(cbcCTX); } err = sCrypt2C4Err(status); } return err; }
static struct passwd * vnextpwent(char const * nam, uid_t uid, int doclose) { struct passwd * pw = NULL; static char pwtmp[1024]; strlcpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof(pwtmp)); if (pwd_fp != NULL || (pwd_fp = fopen(pwtmp, "r")) != NULL) { int done = 0; static struct passwd pwd; while (!done && fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL) { int i, quickout = 0; char * q; char * p = strchr(pwtmp, '\n'); if (p == NULL) { while (fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL && strchr(pwtmp, '\n')==NULL) ; /* Skip long lines */ continue; } /* skip comments & empty lines */ if (*pwtmp =='\n' || *pwtmp == '#') continue; i = 0; q = p = pwtmp; bzero(&pwd, sizeof pwd); while (!quickout && (p = strsep(&q, ":\n")) != NULL) { switch (i++) { case 0: /* username */ pwd.pw_name = p; if (nam) { if (strcmp(nam, p) == 0) done = 1; else quickout = 1; } break; case 1: /* password */ pwd.pw_passwd = p; break; case 2: /* uid */ pwd.pw_uid = atoi(p); if (uid != (uid_t)-1) { if (uid == pwd.pw_uid) done = 1; else quickout = 1; } break; case 3: /* gid */ pwd.pw_gid = atoi(p); break; case 4: /* class */ if (nam == NULL && uid == (uid_t)-1) done = 1; pwd.pw_class = p; break; case 5: /* change */ pwd.pw_change = (time_t)atol(p); break; case 6: /* expire */ pwd.pw_expire = (time_t)atol(p); break; case 7: /* gecos */ pwd.pw_gecos = p; break; case 8: /* directory */ pwd.pw_dir = p; break; case 9: /* shell */ pwd.pw_shell = p; break; } } } if (doclose) vendpwent(); if (done && pwd.pw_name) { pw = &pwd; #define CKNULL(s) s = s ? s : "" CKNULL(pwd.pw_passwd); CKNULL(pwd.pw_class); CKNULL(pwd.pw_gecos); CKNULL(pwd.pw_dir); CKNULL(pwd.pw_shell); } } return pw; }
static struct group * vnextgrent(char const * nam, gid_t gid, int doclose) { struct group * gr = NULL; static char * grtmp = NULL; static int grlen = 0; static char ** mems = NULL; static int memlen = 0; extendline(&grtmp, &grlen, MAXPATHLEN); strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN); if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) { int done = 0; static struct group grp; while (!done && fgets(grtmp, grlen, grp_fp) != NULL) { int i, quickout = 0; int mno = 0; char * q, * p; char * sep = ":\n"; if ((p = strchr(grtmp, '\n')) == NULL) { int l; extendline(&grtmp, &grlen, grlen + PWBUFSZ); l = strlen(grtmp); if (fgets(grtmp + l, grlen - l, grp_fp) == NULL) break; /* No newline terminator on last line */ } /* Skip comments and empty lines */ if (*grtmp == '\n' || *grtmp == '#') continue; i = 0; q = p = grtmp; bzero(&grp, sizeof grp); extendarray(&mems, &memlen, 200); while (!quickout && (p = strsep(&q, sep)) != NULL) { switch (i++) { case 0: /* groupname */ grp.gr_name = p; if (nam) { if (strcmp(nam, p) == 0) done = 1; else quickout = 1; } break; case 1: /* password */ grp.gr_passwd = p; break; case 2: /* gid */ grp.gr_gid = atoi(p); if (gid != (gid_t)-1) { if (gid == (gid_t)grp.gr_gid) done = 1; else quickout = 1; } else if (nam == NULL) done = 1; break; case 3: q = p; sep = ",\n"; break; default: if (*p) { extendarray(&mems, &memlen, mno + 2); mems[mno++] = p; } break; } } grp.gr_mem = mems; mems[mno] = NULL; } if (doclose) vendgrent(); if (done && grp.gr_name) { gr = &grp; CKNULL(grp.gr_passwd); } } return gr; }
static SCLError sSCKeysStorageTest(SCKeySuite keySuite) { SCLError err = kSCLError_NoErr; SCKeyContextRef storageKey = kInvalidSCKeyContextRef; SCKeyContextRef pKey = kInvalidSCKeyContextRef; const char* passphrase = "Tant las fotei com auziretz"; uint8_t* keyData = NULL; size_t keyDataLen = 0; Cipher_Algorithm algorithm = kCipher_Algorithm_Invalid; size_t symKeyLen = 0; int msg_count = ( sizeof(Msgs) / sizeof(char*)) -1; typedef struct { uint8_t *data; size_t len; }storage_entry; storage_entry *msg_store = NULL; uint8_t deviceUUID[32]; uint8_t IV[32]; OPTESTLogInfo("\tTesting SCKeys Storage API (%s)\n", sckey_suite_table(keySuite)); msg_store = XMALLOC(sizeof(storage_entry) * msg_count); CKNULL(msg_store); ZERO(msg_store,sizeof(storage_entry) * msg_count); // we use the UUID only as a nonce, it should be unique but doesnt have to be secure err = RNG_GetBytes(deviceUUID,sizeof(deviceUUID)); // generate a 128 bit storagre key and a 128 bit IV err = RNG_GetBytes(IV,sizeof(IV)); err = SCKeyCipherForKeySuite(keySuite, &algorithm, &symKeyLen); CKERR; OPTESTLogVerbose("\t\tCreate %s encyption key\n",cipher_algor_table(algorithm)); err = SCKeyNew(keySuite, deviceUUID, sizeof(deviceUUID), &storageKey); CKERR; err = SCKeySetProperty (storageKey, kSCKeyProp_IV, SCKeyPropertyType_Binary, IV , symKeyLen); CKERR; OPTESTLogVerbose("\t\tEncrypt %d test messages\n", msg_count); // Encrypt a bunch of messages for(int i = 0; Msgs[i] != NULL; i++) { unsigned long msgLen; msgLen = strlen(Msgs[i]); OPTESTLogDebug("\t\t %3d - %3d bytes |%.*s|\n", i+1, (int)msgLen,(int)msgLen, Msgs[i] ); err = SCKeyStorageEncrypt(storageKey, (uint8_t*) Msgs[i], msgLen, &msg_store[i].data, &msg_store[i].len); CKERR; dumpHex(IF_LOG_DEBUG, msg_store[i].data, (int)msg_store[i].len, 0); OPTESTLogDebug("\n"); } OPTESTLogVerbose("\t\tSecure the storage key to a passphrase\n"); // secure the storage key to a passphrase err = SCKeyEncryptToPassPhrase(storageKey, (uint8_t*)passphrase, strlen(passphrase), &pKey); CKERR; // get rid of orignial storage key SCKeyFree(storageKey); storageKey = NULL; err = SCKeySerialize(pKey, &keyData, &keyDataLen); CKERR; SCKeyFree(pKey); pKey = NULL; ZERO(IV,sizeof(IV)); // save the passphrase key somewhere OPTESTLogDebug("\t\tPBKDF2 Passphrase Key Packet: (%ld bytes)\n%s\n",keyDataLen, (char*)keyData); // restore the passphrase key err = SCKeyDeserialize(keyData, keyDataLen, &pKey);CKERR; // unlock passphrase key and make a SKey err = SCKeyDecryptFromPassPhrase(pKey, (uint8_t*)passphrase, strlen(passphrase), &storageKey ); CKERR; SCKeyFree(pKey); pKey = NULL; OPTESTLogVerbose("\t\tDecrypt and compare %d messages\n", msg_count); for(int i = 0; Msgs[i] != NULL; i++) { unsigned long msgLen; uint8_t* PT = NULL; size_t PTLen = 0; msgLen = strlen(Msgs[i]); err = SCKeyStorageDecrypt(storageKey, msg_store[i].data, msg_store[i].len, &PT, &PTLen); CKERR; if(msgLen != PTLen) { OPTESTLogInfo("ERROR MSG Decrypt: Expecting %d bytes, got %d\n", (int)msgLen, (int)PTLen ); RETERR(kSCLError_SelfTestFailed); } err = compareResults( Msgs[i], PT, msgLen , kResultFormat_Byte, "MSG Decrypt"); CKERR; if(PT) XFREE(PT); PT = NULL; } SCKeyFree(storageKey); storageKey = NULL; OPTESTLogVerbose("\n"); done: for(int i = 0; i < msg_count; i++) { if(msg_store[i].data ) { XFREE(msg_store[i].data); } } XFREE(msg_store); if(SCKeyContextRefIsValid(pKey)) SCKeyFree(pKey); if(SCKeyContextRefIsValid(storageKey)) SCKeyFree(storageKey); return err; }
C4Err HASH_Init(HASH_Algorithm algorithm, HASH_ContextRef * ctx) { int err = kC4Err_NoErr; HASH_Context* hashCTX = NULL; const struct ltc_hash_descriptor* desc = NULL; ValidateParam(ctx); *ctx = NULL; hashCTX = XMALLOC(sizeof (HASH_Context)); CKNULL(hashCTX); hashCTX->magic = kHASH_ContextMagic; hashCTX->algor = algorithm; #if _USES_COMMON_CRYPTO_ switch(algorithm) { case kHASH_Algorithm_MD5: hashCTX->ccAlgor = kCCHmacAlgMD5; hashCTX->process = (void*) sCCHashUpdateMD5; hashCTX->done = (void*) sCCHashFinalMD5; hashCTX->hashsize = 16; CC_MD5_Init(&hashCTX->state.ccMD5_state); break; case kHASH_Algorithm_SHA1: hashCTX->ccAlgor = kCCHmacAlgSHA1; hashCTX->hashsize = 20; hashCTX->process = (void*) sCCHashUpdateSHA1; hashCTX->done = (void*) sCCHashFinalSHA1;; CC_SHA1_Init(&hashCTX->state.ccSHA1_state); break; case kHASH_Algorithm_SHA224: hashCTX->ccAlgor = kCCHmacAlgSHA224; hashCTX->hashsize = 28; hashCTX->process = (void*) sCCHashUpdateSHA224; hashCTX->done = (void*) sCCHashFinalSHA224; CC_SHA224_Init(&hashCTX->state.ccSHA256_state); break; case kHASH_Algorithm_SHA256: hashCTX->ccAlgor = kCCHmacAlgSHA256; hashCTX->hashsize = 32; hashCTX->process = (void*) sCCHashUpdateSHA256; hashCTX->done = (void*) sCCHashFinalSHA256;; CC_SHA256_Init(&hashCTX->state.ccSHA256_state); break; case kHASH_Algorithm_SHA384: hashCTX->ccAlgor = kCCHmacAlgSHA384; hashCTX->hashsize = 48; hashCTX->process = (void*) sCCHashUpdateSHA384; hashCTX->done = (void*) sCCHashFinalSHA384; CC_SHA384_Init(&hashCTX->state.ccSHA512_state); break; case kHASH_Algorithm_SHA512: hashCTX->ccAlgor = kCCHmacAlgSHA512; hashCTX->hashsize = 64; hashCTX->process = (void*) sCCHashUpdateSHA512; hashCTX->done = (void*) sCCHashFinalSHA512; CC_SHA512_Init(&hashCTX->state.ccSHA512_state); break; default: hashCTX->ccAlgor = kCCHmacAlgInvalid; break; } if(hashCTX->ccAlgor == kCCHmacAlgInvalid) { desc = sDescriptorForHash(algorithm); hashCTX->hashsize = desc->hashsize; hashCTX->process = (void*) desc->process; hashCTX->done = (void*) desc->done; if(IsNull(desc)) RETERR( kC4Err_BadHashNumber); if(desc->init) err = (desc->init)(&hashCTX->state.tc_state); CKERR; } #else desc = sDescriptorForHash(algorithm); hashCTX->hashsize = desc->hashsize; hashCTX->process = (void*) desc->process; hashCTX->done = (void*) desc->done; if(IsNull(desc)) RETERR( kC4Err_BadHashNumber); if(desc->init) err = (desc->init)(&hashCTX->state.tc_state); CKERR; #endif *ctx = hashCTX; done: if(IsC4Err(err)) { if(IsntNull(hashCTX)) { XFREE(hashCTX); } } return err; }
C4Err PASS_TO_KEY_SETUP( unsigned long password_len, unsigned long key_len, uint8_t *salt, unsigned long salt_len, uint32_t *rounds_out) { C4Err err = kC4Err_NoErr; uint8_t *password = NULL; uint8_t *key = NULL; uint32_t rounds = MIN_ROUNDS; #if _USES_COMMON_CRYPTO_ rounds = CCCalibratePBKDF(kCCPBKDF2,password_len, salt_len, kCCPRFHmacAlgSHA256, key_len, 100 ); rounds = rounds > MIN_ROUNDS?rounds:MIN_ROUNDS; *rounds_out = rounds; #else uint64_t startTime, endTime, elapsedTime; uint64_t msec = 100; // 0.1s ? int i; // random password and salt password = XMALLOC(password_len); CKNULL(password); key = XMALLOC(key_len); CKNULL(key); err = RNG_GetBytes( password, password_len ); CKERR; err = RNG_GetBytes( salt, salt_len ); CKERR; // run and calculate elapsed time. for(elapsedTime = 0, i=0; i < 10 && elapsedTime == 0; i++) { startTime = clock(); err = PASS_TO_KEY (password, password_len, salt, salt_len, ROUNDMEASURE, key, key_len); CKERR; endTime = clock(); elapsedTime = endTime - startTime; } if(elapsedTime == 0) RETERR(kC4Err_UnknownError); // How many rounds to use so that it takes 0.1s ? rounds = (uint32_t) ((uint64_t)(msec * ROUNDMEASURE * 1000) / elapsedTime); rounds = rounds > MIN_ROUNDS?rounds:MIN_ROUNDS; *rounds_out = rounds; #endif done: if(password) XFREE(password); if(key) XFREE(key); return err; } // PASS_TO_KEY_SETUP()
SCLError Siren_ComputeHash( HASH_Algorithm hash, const char* sirenData, uint8_t* hashOut, bool sorted) { SCLError err = kSCLError_NoErr; yajl_gen_status stat = yajl_gen_status_ok; yajl_handle pHand = NULL; SirenJSONcontext *jctx = NULL; static yajl_callbacks callbacks = { NULL, sParse_bool, NULL, NULL, sParse_number, sParse_string, sParse_start_map, sParse_map_key, sParse_end_map, NULL, NULL }; yajl_alloc_funcs allocFuncs = { yajlMalloc, yajlRealloc, yajlFree, (void *) NULL }; jctx = XMALLOC(sizeof (SirenJSONcontext)); CKNULL(jctx); ZERO(jctx, sizeof(SirenJSONcontext)); err = HASH_Init(hash, &jctx->hash); CKERR; // use yajl to fill the hashableItems with tags and values we can hash pHand = yajl_alloc(&callbacks, &allocFuncs, (void *) jctx); yajl_config(pHand, yajl_allow_comments, 1); stat = (yajl_gen_status) yajl_parse(pHand, (uint8_t*)sirenData, strlen(sirenData)); CKSTAT; stat = (yajl_gen_status) yajl_complete_parse(pHand); CKSTAT; // hash the items found in hashableItems using sHashable_tags_list order int items2Hash = jctx->hashableItemsCount; #if DEBUG_HASH DPRINTF(XCODE_COLORS_RED_TXT,"\nSiren_ComputeHash %s\n", sorted?"sorted":"" ); #endif if(sorted) { for(int j = 0; sHashable_tags_list[j] && items2Hash > 0; j++) { for(int i = 0; i < jctx->hashableItemsCount; i++) { char* tag = sHashable_tags_list[j]; HashableItem *item = &jctx->hashableItems[i]; if(item->tag && strncmp(tag, item->tag, strlen(tag)) == 0 ) { err = shashItem(jctx->hash, item); items2Hash--; break; } } } } else { for(int i = 0; i < items2Hash; i++) { HashableItem *item = &jctx->hashableItems[i]; if(item->tag) { err = shashItem(jctx->hash, item); } } } err = HASH_Final(jctx->hash, hashOut); CKERR; #if DEBUG_HASH DPRINTF(XCODE_COLORS_RED_TXT,"\n"); dumpHex(hashOut, 32, 0); DPRINTF(XCODE_COLORS_RED_TXT,"\n"); #endif done: if(IsntNull(jctx)) { ZERO(jctx, sizeof(SirenJSONcontext)); XFREE(jctx); } if(IsntNull(pHand)) yajl_free(pHand); return err; }