static bool GetSha1ForFile( RageFileBasic &f, unsigned char *szHash ) { hash_state sha1e; sha1_init(&sha1e); int origpos = f.Tell(); f.Seek(0); unsigned char buf[4096]; int got = f.Read(buf, 4096); if ( got == -1 ) return false; while (got > 0) { sha1_process(&sha1e, buf, got); got = f.Read(buf, 4096); if ( got == -1 ) return false; } sha1_done(&sha1e, szHash); f.Seek(origpos); return true; }
/** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha1_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { char *msg; unsigned char hash[20]; } tests[] = { { "abc", { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 } } }; int i; unsigned char tmp[20]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha1_init(&md); sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); sha1_done(&md, tmp); if (XMEMCMP(tmp, tests[i].hash, 20) != 0) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif }
static void sha1_process_wrap( void *ctx, const unsigned char *data ) { sha1_process( (sha1_context *) ctx, data ); }
/* Generate our side of the diffie-hellman key exchange value (dh_f), and * calculate the session key using the diffie-hellman algorithm. Following * that, the session hash is calculated, and signed with RSA or DSS. The * result is sent to the client. * * See the ietf-secsh-transport draft, section 6, for details */ static void send_msg_kexdh_reply(mp_int *dh_e) { mp_int dh_p, dh_q, dh_g, dh_y, dh_f; unsigned char randbuf[DH_P_LEN]; int dh_q_len; hash_state hs; TRACE(("enter send_msg_kexdh_reply")); assert(ses.kexstate.recvkexinit); m_mp_init_multi(&dh_g, &dh_p, &dh_q, &dh_y, &dh_f, NULL); /* read the prime and generator*/ if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); } if (mp_set_int(&dh_g, dh_g_val) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); } /* calculate q = (p-1)/2 */ if (mp_sub_d(&dh_p, 1, &dh_y) != MP_OKAY) { /*dh_y is just a temp var here*/ dropbear_exit("Diffie-Hellman error"); } if (mp_div_2(&dh_y, &dh_q) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); } dh_q_len = mp_unsigned_bin_size(&dh_q); /* calculate our random value dh_y */ do { assert((unsigned int)dh_q_len <= sizeof(randbuf)); genrandom(randbuf, dh_q_len); if (mp_read_unsigned_bin(&dh_y, randbuf, dh_q_len) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); } } while (mp_cmp(&dh_y, &dh_q) == MP_GT || mp_cmp_d(&dh_y, 0) != MP_GT); /* f = g^y mod p */ if (mp_exptmod(&dh_g, &dh_y, &dh_p, &dh_f) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); } mp_clear(&dh_g); /* K = e^y mod p */ ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int)); m_mp_init(ses.dh_K); if (mp_exptmod(dh_e, &dh_y, &dh_p, ses.dh_K) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); } /* clear no longer needed vars */ mp_clear_multi(&dh_y, &dh_p, &dh_q, NULL); /* Create the remainder of the hash buffer, to generate the exchange hash */ /* K_S, the host key */ buf_put_pub_key(ses.kexhashbuf, ses.opts->hostkey, ses.newkeys->algo_hostkey); /* e, exchange value sent by the client */ buf_putmpint(ses.kexhashbuf, dh_e); /* f, exchange value sent by the server */ buf_putmpint(ses.kexhashbuf, &dh_f); /* K, the shared secret */ buf_putmpint(ses.kexhashbuf, ses.dh_K); /* calculate the hash H to sign */ sha1_init(&hs); buf_setpos(ses.kexhashbuf, 0); sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len), ses.kexhashbuf->len); sha1_done(&hs, ses.hash); buf_free(ses.kexhashbuf); ses.kexhashbuf = NULL; /* first time around, we set the session_id to H */ if (ses.session_id == NULL) { /* create the session_id, this never needs freeing */ ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE); memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE); } /* we can start creating the kexdh_reply packet */ CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY); buf_put_pub_key(ses.writepayload, ses.opts->hostkey, ses.newkeys->algo_hostkey); /* put f */ buf_putmpint(ses.writepayload, &dh_f); mp_clear(&dh_f); /* calc the signature */ buf_put_sign(ses.writepayload, ses.opts->hostkey, ses.newkeys->algo_hostkey, ses.hash, SHA1_HASH_SIZE); /* the SSH_MSG_KEXDH_REPLY is done */ encrypt_packet(); TRACE(("leave send_msg_kexdh_reply")); }
/* Generate the actual encryption/integrity keys, using the results of the * key exchange, as specified in section 5.2 of the IETF secsh-transport * draft. This occurs after the DH key-exchange. * * ses.newkeys is the new set of keys which are generated, these are only * taken into use after both sides have sent a newkeys message */ static void gen_new_keys() { unsigned char IV[MAX_IV_LEN]; unsigned char key[MAX_KEY_LEN]; hash_state hs; unsigned int keysize; TRACE(("enter gen_new_keys")); /* the dh_K and hash are the start of all hashes, we make use of that */ sha1_init(&hs); sha1_process_mp(&hs, ses.dh_K); mp_clear(ses.dh_K); m_free(ses.dh_K); sha1_process(&hs, ses.hash, SHA1_HASH_SIZE); m_burn(ses.hash, SHA1_HASH_SIZE); /* client->server IV */ hashkeys(IV, SHA1_HASH_SIZE, &hs, 'A'); /* client->server encryption key */ keysize = ses.newkeys->recv_algo_crypt->keysize; hashkeys(key, keysize, &hs, 'C'); if (cbc_start( find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name), IV, key, keysize, 0, &ses.newkeys->recv_symmetric_struct) != CRYPT_OK) { dropbear_exit("crypto error"); } /* server->client IV */ hashkeys(IV, SHA1_HASH_SIZE, &hs, 'B'); /* server->client encryption key */ keysize = ses.newkeys->trans_algo_crypt->keysize; hashkeys(key, keysize, &hs, 'D'); if (cbc_start( find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name), IV, key, keysize, 0, &ses.newkeys->trans_symmetric_struct) != CRYPT_OK) { dropbear_exit("crypto error"); } /* MAC key client->server */ keysize = ses.newkeys->recv_algo_mac->keysize; hashkeys(ses.newkeys->recvmackey, keysize, &hs, 'E'); /* MAC key server->client */ keysize = ses.newkeys->trans_algo_mac->keysize; hashkeys(ses.newkeys->transmackey, keysize, &hs, 'F'); #ifndef DISABLE_ZLIB gen_new_zstreams(); #endif /* Switch over to the new keys */ m_burn(ses.keys, sizeof(struct key_context)); m_free(ses.keys); ses.keys = ses.newkeys; ses.newkeys = NULL; TRACE(("leave gen_new_keys")); }
/* Pass len=0 to hash an entire file */ static int process_file(hash_state *hs, const char *filename, unsigned int len, int prngd) { static int already_blocked = 0; int readfd; unsigned int readcount; int ret = DROPBEAR_FAILURE; #ifdef DROPBEAR_PRNGD_SOCKET if (prngd) { readfd = connect_unix(filename); } else #endif { readfd = open(filename, O_RDONLY); } if (readfd < 0) { goto out; } readcount = 0; while (len == 0 || readcount < len) { int readlen, wantread; unsigned char readbuf[4096]; if (!already_blocked && !prngd) { int res; struct timeval timeout; fd_set read_fds; timeout.tv_sec = 2; timeout.tv_usec = 0; FD_ZERO(&read_fds); FD_SET(readfd, &read_fds); res = select(readfd + 1, &read_fds, NULL, NULL, &timeout); if (res == 0) { dropbear_log(LOG_WARNING, "Warning: Reading the randomness source '%s' seems to have blocked.\nYou may need to find a better entropy source.", filename); already_blocked = 1; } } if (len == 0) { wantread = sizeof(readbuf); } else { wantread = MIN(sizeof(readbuf), len-readcount); } #ifdef DROPBEAR_PRNGD_SOCKET if (prngd) { char egdcmd[2]; egdcmd[0] = 0x02; /* blocking read */ egdcmd[1] = (unsigned char)wantread; if (write(readfd, egdcmd, 2) < 0) { dropbear_exit("Can't send command to egd"); } } #endif readlen = read(readfd, readbuf, wantread); if (readlen <= 0) { if (readlen < 0 && errno == EINTR) { continue; } if (readlen == 0 && len == 0) { /* whole file was read as requested */ break; } goto out; } sha1_process(hs, readbuf, readlen); readcount += readlen; } ret = DROPBEAR_SUCCESS; out: close(readfd); return ret; }
/* Initialise the prng from /dev/urandom or prngd. This function can * be called multiple times */ void seedrandom() { hash_state hs; pid_t pid; struct timeval tv; clock_t clockval; /* hash in the new seed data */ sha1_init(&hs); /* existing state */ sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); #ifdef DROPBEAR_PRNGD_SOCKET if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1) != DROPBEAR_SUCCESS) { dropbear_exit("Failure reading random device %s", DROPBEAR_PRNGD_SOCKET); } #else /* non-blocking random source (probably /dev/urandom) */ if (process_file(&hs, DROPBEAR_URANDOM_DEV, INIT_SEED_SIZE, 0) != DROPBEAR_SUCCESS) { dropbear_exit("Failure reading random device %s", DROPBEAR_URANDOM_DEV); } #endif /* A few other sources to fall back on. * Add more here for other platforms */ #ifdef __linux__ /* Seems to be a reasonable source of entropy from timers. Possibly hard * for even local attackers to reproduce */ process_file(&hs, "/proc/timer_list", 0, 0); /* Might help on systems with wireless */ process_file(&hs, "/proc/interrupts", 0, 0); process_file(&hs, "/proc/loadavg", 0, 0); process_file(&hs, "/proc/sys/kernel/random/entropy_avail", 0, 0); /* Mostly network visible but useful in some situations. * Limit size to avoid slowdowns on systems with lots of routes */ process_file(&hs, "/proc/net/netstat", 4096, 0); process_file(&hs, "/proc/net/dev", 4096, 0); process_file(&hs, "/proc/net/tcp", 4096, 0); /* Also includes interface lo */ process_file(&hs, "/proc/net/rt_cache", 4096, 0); process_file(&hs, "/proc/vmstat", 0, 0); #endif pid = getpid(); sha1_process(&hs, (void*)&pid, sizeof(pid)); /* gettimeofday() doesn't completely fill out struct timeval on OS X (10.8.3), avoid valgrind warnings by clearing it first */ memset(&tv, 0x0, sizeof(tv)); gettimeofday(&tv, NULL); sha1_process(&hs, (void*)&tv, sizeof(tv)); clockval = clock(); sha1_process(&hs, (void*)&clockval, sizeof(clockval)); /* When a private key is read by the client or server it will * be added to the hashpool - see runopts.c */ sha1_done(&hs, hashpool); counter = 0; donerandinit = 1; /* Feed it all back into /dev/urandom - this might help if Dropbear * is running from inetd and gets new state each time */ write_urandom(); }
static bool CalculateMpqHashSha1( TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSI, unsigned char * sha1_tail0, unsigned char * sha1_tail1, unsigned char * sha1_tail2) { ULONGLONG BeginBuffer; hash_state sha1_state_temp; hash_state sha1_state; LPBYTE pbDigestBuffer = NULL; char szPlainName[MAX_PATH]; // Allocate buffer for creating the MPQ digest. pbDigestBuffer = ALLOCMEM(BYTE, MPQ_DIGEST_UNIT_SIZE); if(pbDigestBuffer == NULL) return false; // Initialize SHA1 state structure sha1_init(&sha1_state); // Calculate begin of data to be hashed BeginBuffer = pSI->BeginMpqData; // Create the digest for(;;) { ULONGLONG BytesRemaining; DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE; // Check the number of bytes remaining BytesRemaining = pSI->EndMpqData - BeginBuffer; if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE) dwToRead = (DWORD)BytesRemaining; if(dwToRead == 0) break; // Read the next chunk if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead)) { FREEMEM(pbDigestBuffer); return false; } // Pass the buffer to the hashing function sha1_process(&sha1_state, pbDigestBuffer, dwToRead); // Move pointers BeginBuffer += dwToRead; } // Add all three known tails and generate three hashes memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state)); sha1_done(&sha1_state_temp, sha1_tail0); memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state)); GetPlainAnsiFileName(ha->pStream->szFileName, szPlainName); AddTailToSha1(&sha1_state_temp, szPlainName); sha1_done(&sha1_state_temp, sha1_tail1); memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state)); AddTailToSha1(&sha1_state_temp, "ARCHIVE"); sha1_done(&sha1_state_temp, sha1_tail2); // Finalize the MD5 hash FREEMEM(pbDigestBuffer); return true; }
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt) { byte AESKey[16],AESInit[16]; bool Cached=false; for (uint I=0;I<ASIZE(KDF3Cache);I++) if (KDF3Cache[I].Pwd==*Password && (Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL && KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0)) { memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey)); memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit)); Cached=true; break; } if (!Cached) { byte RawPsw[2*MAXPASSWORD+SIZE_SALT30]; WideToRaw(PwdW,RawPsw,ASIZE(RawPsw)); size_t RawLength=2*wcslen(PwdW); if (Salt!=NULL) { memcpy(RawPsw+RawLength,Salt,SIZE_SALT30); RawLength+=SIZE_SALT30; } sha1_context c; sha1_init(&c); const int HashRounds=0x40000; for (int I=0;I<HashRounds;I++) { sha1_process( &c, RawPsw, RawLength, false); byte PswNum[3]; PswNum[0]=(byte)I; PswNum[1]=(byte)(I>>8); PswNum[2]=(byte)(I>>16); sha1_process( &c, PswNum, 3, false); if (I%(HashRounds/16)==0) { sha1_context tempc=c; uint32 digest[5]; sha1_done( &tempc, digest, false); AESInit[I/(HashRounds/16)]=(byte)digest[4]; } } uint32 digest[5]; sha1_done( &c, digest, false); for (int I=0;I<4;I++) for (int J=0;J<4;J++) AESKey[I*4+J]=(byte)(digest[I]>>(J*8)); KDF3Cache[KDF3CachePos].Pwd=*Password; if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true) memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30); memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey)); memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit)); KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache); cleandata(RawPsw,sizeof(RawPsw)); }
/** * End of copied SHA1 code. * * ------------------------------------------------------------------------ */ void getDigest_1(void *digest,void *input,int len){ struct sha1_state mystate; sha1_init(&mystate); sha1_process(&mystate,input,len); sha1_done(&mystate,digest); }
static void send_some_more_messages_normal (void) { msg_t my_msg; struct iovec iov[2]; int i; int send_now; size_t payload_size; hash_state sha1_hash; cs_error_t res; cpg_flow_control_state_t fc_state; int retries = 0; time_t before; if (cpg_fd < 0) return; send_now = my_msgs_to_send; //syslog (LOG_DEBUG,"%s() send_now:%d", __func__, send_now); my_msg.pid = my_pid; my_msg.nodeid = my_nodeid; payload_size = (rand() % 100000); my_msg.size = sizeof (msg_t) + payload_size; my_msg.seq = 0; for (i = 0; i < payload_size; i++) { buffer[i] = i; } sha1_init (&sha1_hash); sha1_process (&sha1_hash, buffer, payload_size); sha1_done (&sha1_hash, my_msg.sha1); iov[0].iov_len = sizeof (msg_t); iov[0].iov_base = &my_msg; iov[1].iov_len = payload_size; iov[1].iov_base = buffer; for (i = 0; i < send_now; i++) { if (in_cnchg && pcmk_test) { retries = 0; before = time(NULL); cs_repeat(retries, 30, res = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2)); if (retries > 20) { syslog (LOG_ERR, "%s() -> cs_repeat: blocked for :%lu secs.", __func__, (unsigned long)(time(NULL) - before)); } if (res != CS_OK) { syslog (LOG_ERR, "%s() -> cpg_mcast_joined error:%d.", __func__, res); return; } } else { res = cpg_flow_control_state_get (cpg_handle, &fc_state); if (res == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) { /* lets do this later */ send_some_more_messages_later (); syslog (LOG_INFO, "%s() flow control enabled.", __func__); return; } res = cpg_mcast_joined (cpg_handle, CPG_TYPE_AGREED, iov, 2); if (res == CS_ERR_TRY_AGAIN) { /* lets do this later */ send_some_more_messages_later (); if (i > 0) { syslog (LOG_INFO, "%s() TRY_AGAIN %d to send.", __func__, my_msgs_to_send); } return; } else if (res != CS_OK) { syslog (LOG_ERR, "%s() -> cpg_mcast_joined error:%d, exiting.", __func__, res); exit (-2); } } my_msgs_to_send--; } }
static void send_some_more_messages_zcb (void) { msg_t *my_msg; int i; int send_now; size_t payload_size; size_t total_size; hash_state sha1_hash; cs_error_t res; cpg_flow_control_state_t fc_state; void *zcb_buffer; if (cpg_fd < 0) return; send_now = my_msgs_to_send; payload_size = (rand() % 100000); total_size = payload_size + sizeof (msg_t); cpg_zcb_alloc (cpg_handle, total_size, &zcb_buffer); my_msg = (msg_t*)zcb_buffer; //syslog (LOG_DEBUG,"%s() send_now:%d", __func__, send_now); my_msg->pid = my_pid; my_msg->nodeid = my_nodeid; my_msg->size = sizeof (msg_t) + payload_size; my_msg->seq = 0; for (i = 0; i < payload_size; i++) { my_msg->payload[i] = i; } sha1_init (&sha1_hash); sha1_process (&sha1_hash, my_msg->payload, payload_size); sha1_done (&sha1_hash, my_msg->sha1); for (i = 0; i < send_now; i++) { res = cpg_flow_control_state_get (cpg_handle, &fc_state); if (res == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) { /* lets do this later */ send_some_more_messages_later (); syslog (LOG_INFO, "%s() flow control enabled.", __func__); goto free_buffer; } res = cpg_zcb_mcast_joined (cpg_handle, CPG_TYPE_AGREED, zcb_buffer, total_size); if (res == CS_ERR_TRY_AGAIN) { /* lets do this later */ send_some_more_messages_later (); // if (i > 0) { // syslog (LOG_INFO, "%s() TRY_AGAIN %d to send.", // __func__, my_msgs_to_send); // } goto free_buffer; } else if (res != CS_OK) { syslog (LOG_ERR, "%s() -> cpg_mcast_joined error:%d, exiting.", __func__, res); exit (-2); } my_msgs_to_send--; } free_buffer: cpg_zcb_free (cpg_handle, zcb_buffer); }