static int hmac_dbrg_update(struct ccdrbg_state *drbg, unsigned long daLen, const void *da, unsigned long dbLen, const void *db, unsigned long dcLen, const void *dc ) { struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; const struct ccdrbg_nisthmac_custom *custom = state->info->custom; const struct ccdigest_info *di = custom->di; const unsigned char cZero = 0x00; const unsigned char cOne = 0x01; cchmac_ctx_decl(di->state_size, di->block_size, ctx); cchmac_init(di, ctx, state->keysize, state->key); // 1. K = HMAC (K, V || 0x00 || provided_data). cchmac_update(di, ctx, state->vsize, state->v); cchmac_update(di, ctx, 1, &cZero); if (da && daLen) cchmac_update(di, ctx, daLen, da); if (db && dbLen) cchmac_update(di, ctx, dbLen, db); if (dc && dcLen) cchmac_update(di, ctx, dcLen, dc); cchmac_final(di, ctx, state->key); // 2. V=HMAC(K,V). cchmac(di, state->keysize, state->key, state->vsize, state->v, state->v); // 3. If (provided_data = Null), then return K and V. // One parameter must be non-empty, or return if (!((da && daLen) || (db && dbLen) || (dc && dcLen))) return 0; // 4. K = HMAC (K, V || 0x01 || provided_data). cchmac_init(di, ctx, state->keysize, state->key); cchmac_update(di, ctx, state->vsize, state->v); cchmac_update(di, ctx, 1, &cOne); if (da && daLen) cchmac_update(di, ctx, daLen, da); if (db && dbLen) cchmac_update(di, ctx, dbLen, db); if (dc && dcLen) cchmac_update(di, ctx, dcLen, dc); cchmac_final(di, ctx, state->key); // 5. V=HMAC(K,V). cchmac(di, state->keysize, state->key, state->vsize, state->v, state->v); return 0; }
static int hmac_dbrg_update(struct ccdrbg_state *drbg, size_t daLen, const void *da, size_t dbLen, const void *db, size_t dcLen, const void *dc ) { int rc=CCDRBG_STATUS_ERROR; struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; const struct ccdigest_info *di = state->custom->di; const unsigned char cZero = 0x00; const unsigned char cOne = 0x01; cchmac_ctx_decl(di->state_size, di->block_size, ctx); cchmac_init(di, ctx, state->keysize, state->key); // 1. K = HMAC (K, V || 0x00 || provided_data). cchmac_update(di, ctx, state->vsize, state->vptr); cchmac_update(di, ctx, 1, &cZero); if (da && daLen) cchmac_update(di, ctx, daLen, da); if (db && dbLen) cchmac_update(di, ctx, dbLen, db); if (dc && dcLen) cchmac_update(di, ctx, dcLen, dc); cchmac_final(di, ctx, state->key); // One parameter must be non-empty, or return if (((da && daLen) || (db && dbLen) || (dc && dcLen))) { // 2. V=HMAC(K,V). cchmac(di, state->keysize, state->key, state->vsize, state->vptr, state->vptr); // 4. K = HMAC (K, V || 0x01 || provided_data). cchmac_init(di, ctx, state->keysize, state->key); cchmac_update(di, ctx, state->vsize, state->vptr); cchmac_update(di, ctx, 1, &cOne); if (da && daLen) cchmac_update(di, ctx, daLen, da); if (db && dbLen) cchmac_update(di, ctx, dbLen, db); if (dc && dcLen) cchmac_update(di, ctx, dcLen, dc); cchmac_final(di, ctx, state->key); } // If additional data 5. V=HMAC(K,V) // If no addtional data, this is step 2. V=HMAC(K,V). state->bytesLeft = 0; // FIPS 140-2 4.9.2 Conditional Tests // "the first n-bit block generated after power-up, initialization, or reset shall not be used, but shall be saved for comparison with the next n-bit block to be generated" // Generate the first block and the second block. Compare for FIPS and discard the first block // We keep the second block as the first set of data to be returned cchmac(di, state->keysize, state->key, state->vsize, state->vptr, state->vptr); // First block cchmac(di, state->keysize, state->key, state->vsize, state->vptr, state->nextvptr); // First to be returned if (0==cc_cmp_safe(state->vsize, state->vptr, state->nextvptr)) { //The world as we know it has come to an end //the DRBG data structure is zeroized. subsequent calls to //DRBG ends up in NULL dereferencing and/or unpredictable state. //catastrophic error in SP 800-90A done(drbg); rc=CCDRBG_STATUS_ABORT; cc_abort(NULL); goto errOut; } rc=CCDRBG_STATUS_OK; errOut: return rc; }
static int Integrity_POST(kmod_info_t* pkmod, void* d, int verbose) { int result = -1; // Set to zero for sucesses until it all works size_t sha256DigestBufferLength = 32; if (NULL == d) { if (verbose) { kprintf("The AppleTEXTHash_t pointer was NOT passed to the Integrity_POST function\n"); } return result; } AppleTEXTHash_t* pHashData = (AppleTEXTHash_t*)d; if (pHashData->ath_version != 1 || pHashData->ath_length != (int)sha256DigestBufferLength) { if (verbose) { kprintf("The AppleTEXTHash_t pointer passed to Integrity_POST function, is invalid\n"); } return result; } if (NULL == pHashData->ath_hash) { if (verbose) { kprintf("The AppleTEXTHash_t pointer passed to Integrity_POST function,has a null HASH pointer\n"); } return result; } unsigned long plist_hash_output_buffer_size = (sha256DigestBufferLength * 2) + 1; unsigned char plist_hash_output_buffer[plist_hash_output_buffer_size]; char* pPlistHexBuf = (char*)bytesToHexString(pHashData->ath_hash, pHashData->ath_length, plist_hash_output_buffer, plist_hash_output_buffer_size); if (verbose) { kprintf("Plist hmac value is %s\n", pPlistHexBuf); } // Now calcuate the HMAC struct mach_header* pmach_header = (struct mach_header*)pkmod->address; struct load_command* pLoadCommand = NULL; uint32_t num_load_commands = 0; if (pmach_header->magic == MH_MAGIC_64) { struct mach_header_64* pmach64_header = (struct mach_header_64*)pmach_header; num_load_commands = pmach64_header->ncmds; pLoadCommand = (struct load_command*)(((unsigned char*)pmach_header) + sizeof(struct mach_header_64)); } else if (pmach_header->magic == MH_MAGIC) { num_load_commands = pmach_header->ncmds; pLoadCommand = (struct load_command*)(((unsigned char*)pmach_header) + sizeof(struct mach_header)); } if (NULL == pLoadCommand) { if (verbose) { kprintf("pLoadCommand is NULL!\n"); } return result; } const struct ccdigest_info* di = ccsha256_di(); unsigned char hmac_key = 0; cchmac_ctx_decl(di->state_size, di->block_size, ctx); cchmac_init(di, ctx, 1, &hmac_key); int hashCreated = 0; unsigned long iCnt; unsigned long jCnt; struct segment_command* pSniffPtr = (struct segment_command*)pLoadCommand; // Loop through the Segments to find the __TEXT, __text segment for (iCnt = 0; iCnt < num_load_commands; iCnt++) { // The struct segment_command and the struct segment_command_64 have the same // first three fields so sniff the name by casting to a struct segment_command if (strncmp("__TEXT", pSniffPtr->segname, strlen("__TEXT"))) { // These are not the droids we are looking for // MOve the SniffPtr to the next segment; if (LC_SEGMENT_64 == pSniffPtr->cmd) { struct segment_command_64* pSegmentPtr = (struct segment_command_64*)pSniffPtr; pSniffPtr = (struct segment_command*)(((unsigned char *)pSegmentPtr) + pSegmentPtr->cmdsize); } else if (LC_SEGMENT == pSniffPtr->cmd) { pSniffPtr = (struct segment_command*)(((unsigned char *)pSniffPtr) + pSniffPtr->cmdsize); } // Go back to the top of the loop and look again continue; } // Bingo! We found the __TEXT segment! // Deal with a 64 bit segment if (LC_SEGMENT_64 == pLoadCommand->cmd) { struct segment_command_64* pSegmentPtr = NULL; // This is a 64 bit load segment command pSegmentPtr = (struct segment_command_64*)pSniffPtr; unsigned int numSections = (unsigned int)pSegmentPtr->nsects; struct section_64* pSectionPtr = (struct section_64*)(((unsigned char*)pSegmentPtr) + sizeof(struct segment_command_64)); int texttextsectionprocessed = 0; // Need to find the __text __TEXT section for (jCnt = 0; jCnt < numSections; jCnt++) { if ( !strcmp(pSectionPtr->sectname, "__text") && !strcmp(pSectionPtr->segname, "__TEXT")) { // Found it unsigned char* pSectionData = (unsigned char*)(((unsigned char*)pmach_header) + pSectionPtr->offset); cchmac_update(di, ctx, (unsigned long)pSectionPtr->size, pSectionData); hashCreated = 1; texttextsectionprocessed = 1; break; } else { // Move to the next section record pSectionPtr++; } } if (texttextsectionprocessed) { // The text text section was found and processed break; } } else if (LC_SEGMENT == pLoadCommand->cmd) // Deal with a 32 bit segment { struct segment_command* pSegmentPtr = NULL; // This is a 32 bit load segment command pSegmentPtr = (struct segment_command*)pLoadCommand; unsigned int numSections = (unsigned int)pSegmentPtr->nsects; struct section* pSectionPtr = (struct section*)(((unsigned char*)pSegmentPtr) + sizeof(struct segment_command)); int texttextsectionprocessed = 0; // Need to find the __text __TEXT section for (jCnt = 0; jCnt < numSections; jCnt++) { if ( !strcmp(pSectionPtr->sectname, "__text") && !strcmp(pSectionPtr->segname, "__TEXT")) { // Found it unsigned char* pSectionData = (unsigned char*)(((unsigned char*)pmach_header) + pSectionPtr->offset); cchmac_update(di, ctx, (unsigned long)pSectionPtr->size, pSectionData); hashCreated = 1; texttextsectionprocessed = 1; break; } else { // Move to the next section record pSectionPtr++; } } if (texttextsectionprocessed) { // The text text section was found and processed // Time to bail on the loop break; } } } unsigned long hash_output_buffer_size = (sha256DigestBufferLength * 2) + 1; unsigned char hash_output_buffer[hash_output_buffer_size]; unsigned char hmac_buffer[sha256DigestBufferLength]; memset(hmac_buffer, 0, sha256DigestBufferLength); // Check to see if the hash was created if (hashCreated) { // finalize the HMAC cchmac_final(di, ctx, hmac_buffer); char* pHexBuf = (char*)bytesToHexString(hmac_buffer, sha256DigestBufferLength, hash_output_buffer, hash_output_buffer_size); if (verbose) { kprintf("Computed hmac value is %s\n", pHexBuf); } } else { if (verbose) { kprintf("Integrity_POST: WARNING! could not create the hash!\n"); } return -1; } #ifdef FORCE_FAIL // futz with the generated hmac hash_output_buffer[0] = 0; // This will always work because it is the charter representation of the // hash that is being checked. #endif result = memcmp(hash_output_buffer, plist_hash_output_buffer, hash_output_buffer_size); return result; }