/*----------------------------------------------------------------------------*/ int zrtp_randstr(zrtp_global_t* zrtp, unsigned char *buffer, uint32_t length) { //TODO: replace bg_aes_xxx() with our own block cipher component. //TODO: Do the same with the hash functions. aes_encrypt_ctx aes_ctx; MD_CTX rand_ctx2; unsigned char md[MD_DIGEST_LENGTH]; unsigned char ctr[AES_BLOCK_SIZE]; unsigned char rdata[AES_BLOCK_SIZE]; uint32_t generated = length; /* * In few cases we need to gerate random value before initializing libzrtp engine. * Following trick makes it possible. */ if (!zrtp->rand_initialized) { if (zrtp_status_ok != zrtp_init_rng(zrtp)) { return -1; } } zrtp_mutex_lock(zrtp->rng_protector); /* * Add entropy from system state * We will include whatever happens to be in the buffer, it can't hurt */ if ( 0 > zrtp_entropy_add(zrtp, buffer, length) ) { zrtp_mutex_unlock(zrtp->rng_protector); return -1; } /* Copy the zrtp->rand_ctx and finalize it into the md buffer */ rand_ctx2 = zrtp->rand_ctx; MD_Final(&rand_ctx2, md); zrtp_mutex_unlock(zrtp->rng_protector); /* Key an AES context from this buffer */ zrtp_bg_aes_encrypt_key256(md, &aes_ctx); /* Initialize counter, using excess from md if available */ zrtp_memset (ctr, 0, sizeof(ctr)); if (MD_DIGEST_LENGTH > (256/8)) { uint32_t ctrbytes = MD_DIGEST_LENGTH - (256/8); if (ctrbytes > AES_BLOCK_SIZE) ctrbytes = AES_BLOCK_SIZE; zrtp_memcpy(ctr + sizeof(ctr) - ctrbytes, md + (256/8), ctrbytes); } /* Encrypt counter, copy to destination buffer, increment counter */ while (length) { unsigned char *ctrptr; uint32_t copied; zrtp_bg_aes_encrypt(ctr, rdata, &aes_ctx); copied = (sizeof(rdata) < length) ? sizeof(rdata) : length; zrtp_memcpy (buffer, rdata, copied); buffer += copied; length -= copied; /* Increment counter */ ctrptr = ctr + sizeof(ctr) - 1; while (ctrptr >= ctr) { if ((*ctrptr-- += 1) != 0) { break; } } } /* Done! Cleanup and exit */ MD_Cleanup (&rand_ctx2); MD_Cleanup (md); MD_Cleanup (&aes_ctx); MD_Cleanup (ctr); MD_Cleanup (rdata); return generated; }
zrtp_status_t zrtp_init(zrtp_config_t* config, zrtp_global_t** zrtp) { zrtp_global_t* new_zrtp; zrtp_status_t s = zrtp_status_ok; ZRTP_LOG(3, (_ZTU_,"INITIALIZING LIBZRTP...\n")); /* Print out configuration setting */ zrtp_print_env_settings(config); new_zrtp = zrtp_sys_alloc(sizeof(zrtp_global_t)); if (!new_zrtp) { return zrtp_status_alloc_fail; } zrtp_memset(new_zrtp, 0, sizeof(zrtp_global_t)); /* * Apply configuration according to the config */ new_zrtp->lic_mode = config->lic_mode; new_zrtp->is_mitm = config->is_mitm; ZSTR_SET_EMPTY(new_zrtp->def_cache_path); zrtp_zstrcpy(ZSTR_GV(new_zrtp->def_cache_path), ZSTR_GV(config->def_cache_path)); zrtp_memcpy(&new_zrtp->cb, &config->cb, sizeof(zrtp_callback_t)); new_zrtp->cache_auto_store = config->cache_auto_store; ZSTR_SET_EMPTY(new_zrtp->client_id); zrtp_memset(new_zrtp->client_id.buffer, ' ', sizeof(zrtp_client_id_t)); zrtp_zstrncpyc( ZSTR_GV(new_zrtp->client_id), (const char*)config->client_id, sizeof(zrtp_client_id_t)); /* * General Initialization */ init_mlist(&new_zrtp->sessions_head); zrtp_mutex_init(&new_zrtp->sessions_protector); init_mlist(&new_zrtp->hash_head); init_mlist(&new_zrtp->cipher_head); init_mlist(&new_zrtp->atl_head); init_mlist(&new_zrtp->pktype_head); init_mlist(&new_zrtp->sas_head); /* Init RNG context */ s = zrtp_init_rng(new_zrtp); if (zrtp_status_ok != s) { ZRTP_LOG(1, (_ZTU_,"ERROR! zrtp_init_rng() failed:%s.\n", zrtp_log_status2str(s))); return zrtp_status_rng_fail; } /* Initialize SRTP engine */ s = zrtp_srtp_init(new_zrtp); if (zrtp_status_ok != s) { ZRTP_LOG(1, (_ZTU_,"ERROR! zrtp_srtp_init() failed:<%s>\n", zrtp_log_status2str(s))); return zrtp_status_fail; } if (new_zrtp->cb.cache_cb.on_init) { s = new_zrtp->cb.cache_cb.on_init(new_zrtp); if (zrtp_status_ok != s) { ZRTP_LOG(1, (_ZTU_,"ERROR! cache on_init() callback failed <%s>\n", zrtp_log_status2str(s))); zrtp_srtp_down(new_zrtp); return zrtp_status_fail; } } if (new_zrtp->cb.sched_cb.on_init) { s = new_zrtp->cb.sched_cb.on_init(new_zrtp); if (zrtp_status_ok != s) { ZRTP_LOG(1, (_ZTU_,"ERROR! scheduler on_init() callback failed <%s>\n", zrtp_log_status2str(s))); zrtp_srtp_down(new_zrtp); return zrtp_status_fail; } } /* Load default crypto-components */ zrtp_prepare_pkt(new_zrtp); zrtp_defaults_sas(new_zrtp); zrtp_defaults_pkt(new_zrtp); zrtp_defaults_atl(new_zrtp); zrtp_defaults_aes_cipher(new_zrtp); zrtp_defaults_hash(new_zrtp); *zrtp = new_zrtp; ZRTP_LOG(3, (_ZTU_,"INITIALIZING LIBZRTP - DONE\n")); return s; }