/* * Processing FOR KE values. */ void unpack_KE(struct state *st , struct pluto_crypto_req *r , chunk_t *g) { struct pcr_kenonce *kn = &r->pcr_d.kn; if (!st->st_sec_in_use) { st->st_sec_in_use = TRUE; freeanychunk(*g); /* happens in odd error cases */ clonetochunk(*g, wire_chunk_ptr(kn, &(kn->gi)) , kn->gi.len, "saved gi value"); #ifdef HAVE_LIBNSS DBG(DBG_CRYPT, DBG_log("saving DH priv (local secret) and pub key into state struc")); clonetochunk(st->st_sec_chunk , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len, "pointer to DH private key (secret)"); clonetochunk(st->pubk , wire_chunk_ptr(kn, &(kn->pubk)) , kn->pubk.len, "pointer to DH public key"); #else n_to_mpz(&st->st_sec , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len); clonetochunk(st->st_sec_chunk , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len, "long term secret"); #endif } }
void calc_nonce(struct pluto_crypto_req *r) { struct pcr_kenonce *kn = &r->pcr_d.kn; pluto_crypto_allocchunk(&kn->thespace, &kn->n, DEFAULT_NONCE_SIZE); get_rnd_bytes(wire_chunk_ptr(kn, &(kn->n)), DEFAULT_NONCE_SIZE); DBG(DBG_CRYPT, DBG_dump("Generated nonce:\n" , wire_chunk_ptr(kn, &(kn->n)) , DEFAULT_NONCE_SIZE)); }
void unpack_nonce(chunk_t *n, struct pluto_crypto_req *r) { struct pcr_kenonce *kn = &r->pcr_d.kn; freeanychunk(*n); clonetochunk(*n, wire_chunk_ptr(kn, &(kn->n)), DEFAULT_NONCE_SIZE, "initiator nonce"); }
void finish_dh_secret(struct state *st, struct pluto_crypto_req *r) { struct pcr_skeyid_r *dhr = &r->pcr_d.dhr; clonetochunk(st->st_shared, wire_chunk_ptr(dhr, &(dhr->shared)) , dhr->shared.len, "calculated shared secret"); }
void finish_dh_secretiv(struct state *st, struct pluto_crypto_req *r) { struct pcr_skeyid_r *dhr = &r->pcr_d.dhr; clonetochunk(st->st_shared, wire_chunk_ptr(dhr, &(dhr->shared)) , dhr->shared.len, "calculated shared secret"); clonetochunk(st->st_skeyid, wire_chunk_ptr(dhr, &(dhr->skeyid)) , dhr->skeyid.len, "calculated skeyid secret"); clonetochunk(st->st_skeyid_d, wire_chunk_ptr(dhr, &(dhr->skeyid_d)) , dhr->skeyid_d.len, "calculated skeyid_d secret"); clonetochunk(st->st_skeyid_a, wire_chunk_ptr(dhr, &(dhr->skeyid_a)) , dhr->skeyid_a.len, "calculated skeyid_a secret"); clonetochunk(st->st_skeyid_e, wire_chunk_ptr(dhr, &(dhr->skeyid_e)) , dhr->skeyid_e.len, "calculated skeyid_a secret"); clonetochunk(st->st_enc_key, wire_chunk_ptr(dhr, &(dhr->enc_key)) , dhr->enc_key.len, "calculated key for phase 1"); passert(dhr->new_iv.len <= MAX_DIGEST_LEN); passert(dhr->new_iv.len > 0); memcpy(st->st_new_iv, wire_chunk_ptr(dhr, &(dhr->new_iv)),dhr->new_iv.len); st->st_new_iv_len = dhr->new_iv.len; st->hidden_variables.st_skeyid_calculated = TRUE; }
void calc_ke(struct pluto_crypto_req *r) { MP_INT mp_g; MP_INT secret; chunk_t gi; struct pcr_kenonce *kn = &r->pcr_d.kn; const struct oakley_group_desc *group; group = lookup_group(kn->oakley_group); pluto_crypto_allocchunk(&kn->thespace , &kn->secret , LOCALSECRETSIZE); get_rnd_bytes(wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE); n_to_mpz(&secret, wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE); mpz_init(&mp_g); oswcrypto.mod_exp(&mp_g, group->generator, &secret, group->modulus); gi = mpz_to_n(&mp_g, group->bytes); pluto_crypto_allocchunk(&kn->thespace, &kn->gi, gi.len); { char *gip = wire_chunk_ptr(kn, &(kn->gi)); memcpy(gip, gi.ptr, gi.len); } DBG(DBG_CRYPT, DBG_dump("Local DH secret:\n" , wire_chunk_ptr(kn, &(kn->secret)) , LOCALSECRETSIZE); DBG_dump_chunk("Public DH value sent:\n", gi)); /* clean up after ourselves */ mpz_clear(&mp_g); mpz_clear(&secret); freeanychunk(gi); }
/* * Processing FOR KE values. */ void unpack_KE(struct state *st , struct pluto_crypto_req *r , chunk_t *g) { struct pcr_kenonce *kn = &r->pcr_d.kn; if (!st->st_sec_in_use) { st->st_sec_in_use = TRUE; freeanychunk(*g); /* happens in odd error cases */ clonetochunk(*g, wire_chunk_ptr(kn, &(kn->gi)) , kn->gi.len, "saved gi value"); n_to_mpz(&st->st_sec , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len); clonetochunk(st->st_sec_chunk , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len, "long term secret"); } }
/******************************************************************************* 函数名称: calc_ke 功能描述: 当模长度是1024时,可以使用硬件来加速模幂运算 输入参数: 输出参数: 无 返 回 值: 无 -------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者: 李 志 修改目的: 性能优化 修改日期: 2011-1-15 *******************************************************************************/ void calc_ke(struct pluto_crypto_req *r) { s32 ret = -1; const struct oakley_group_desc *group; chunk_t gi; struct pcr_kenonce *kn = &r->pcr_d.kn; group = lookup_group(kn->oakley_group); pluto_crypto_allocchunk(&kn->thespace, &kn->secret, LOCALSECRETSIZE); get_rnd_bytes(wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE); if(OAKLEY_GROUP_MODP1024 == kn->oakley_group && (!g_ipsec_device_is_dpx)) { /*由于硬件只支持1024和512位的模运算,而ipsec最低使用768位的模运算,故只有1024位时才可以使用硬件计算*/ chunk_t secret_chunk; IPSEC_DEBUG(DBG_CRYPT, IPSEC_dbg("hardware calc_ke mod exp, group:%d\n", kn->oakley_group););
void finish_dh_v2(struct state *st, struct pluto_crypto_req *r) { struct pcr_skeycalc_v2 *dhv2 = &r->pcr_d.dhv2; clonetochunk(st->st_shared, wire_chunk_ptr(dhv2, &(dhv2->shared)) , dhv2->shared.len, "calculated shared secret"); clonetochunk(st->st_skey_d, wire_chunk_ptr(dhv2, &(dhv2->skeyid_d)) , dhv2->skeyid_d.len, "calculated skeyid secret"); clonetochunk(st->st_skey_ai, wire_chunk_ptr(dhv2, &(dhv2->skeyid_ai)) , dhv2->skeyid_ai.len, "calculated skeyid_ai secret"); clonetochunk(st->st_skey_ar, wire_chunk_ptr(dhv2, &(dhv2->skeyid_ar)) , dhv2->skeyid_ar.len, "calculated skeyid_ar secret"); clonetochunk(st->st_skey_pi, wire_chunk_ptr(dhv2, &(dhv2->skeyid_pi)) , dhv2->skeyid_pi.len, "calculated skeyid_pi secret"); clonetochunk(st->st_skey_pr, wire_chunk_ptr(dhv2, &(dhv2->skeyid_pr)) , dhv2->skeyid_pr.len, "calculated skeyid_pr secret"); clonetochunk(st->st_skey_ei, wire_chunk_ptr(dhv2, &(dhv2->skeyid_ei)) , dhv2->skeyid_ei.len, "calculated skeyid_ei secret"); clonetochunk(st->st_skey_er, wire_chunk_ptr(dhv2, &(dhv2->skeyid_er)) , dhv2->skeyid_er.len, "calculated skeyid_er secret"); st->hidden_variables.st_skeyid_calculated = TRUE; }
chunk_t gi; struct pcr_kenonce *kn = &r->pcr_d.kn; group = lookup_group(kn->oakley_group); pluto_crypto_allocchunk(&kn->thespace, &kn->secret, LOCALSECRETSIZE); get_rnd_bytes(wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE); if(OAKLEY_GROUP_MODP1024 == kn->oakley_group && (!g_ipsec_device_is_dpx)) { /*由于硬件只支持1024和512位的模运算,而ipsec最低使用768位的模运算,故只有1024位时才可以使用硬件计算*/ chunk_t secret_chunk; IPSEC_DEBUG(DBG_CRYPT, IPSEC_dbg("hardware calc_ke mod exp, group:%d\n", kn->oakley_group);); secret_chunk.ptr = wire_chunk_ptr(kn, &(kn->secret)); secret_chunk.len = LOCALSECRETSIZE; ret = ipsec_child_rsa_proc(&gi, &g_ipsec_groupgenerator, &secret_chunk, &g_ipsec_groupmod_1024, &g_ipsec_const_1024); } /*使用硬件处理失败,或模位数为768,1536,2048等其他位数的仍然使用GMP库来进行软件计算*/ if(ret < 0) { MP_INT mp_g; MP_INT secret; IPSEC_DEBUG(DBG_CRYPT,IPSEC_dbg("using software mpz_pown to calc_ke mod exp...\n");); n_to_mpz(&secret, wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE);
void calc_ke(struct pluto_crypto_req *r) { chunk_t prime; chunk_t base; SECKEYDHParams dhp; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privk; SECKEYPublicKey *pubk; struct pcr_kenonce *kn = &r->pcr_d.kn; const struct oakley_group_desc *group; group = lookup_group(kn->oakley_group); base = mpz_to_n2(group->generator); prime = mpz_to_n2(group->modulus); DBG(DBG_CRYPT,DBG_dump_chunk("NSS: Value of Prime:\n", prime)); DBG(DBG_CRYPT,DBG_dump_chunk("NSS: Value of base:\n", base)); dhp.prime.data=prime.ptr; dhp.prime.len=prime.len; dhp.base.data=base.ptr; dhp.base.len=base.len; slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,osw_return_nss_password_file_info()); if(!slot) { loglog(RC_LOG_SERIOUS, "NSS: slot for DH key gen is NULL"); } PR_ASSERT(slot!=NULL); while(1) { privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, &dhp, &pubk, PR_FALSE, PR_TRUE, osw_return_nss_password_file_info()); if(!privk) { loglog(RC_LOG_SERIOUS, "NSS: DH private key creation failed (err %d)", PR_GetError()); } PR_ASSERT(privk!=NULL); if( group-> bytes == pubk->u.dh.publicValue.len ) { DBG(DBG_CRYPT, DBG_log("NSS: generated dh priv and pub keys: %d\n", pubk->u.dh.publicValue.len)); break; } else { DBG(DBG_CRYPT, DBG_log("NSS: generating dh priv and pub keys")); if (privk) SECKEY_DestroyPrivateKey(privk); if (pubk) SECKEY_DestroyPublicKey(pubk); } } pluto_crypto_allocchunk(&kn->thespace, &kn->secret, sizeof(SECKEYPrivateKey*)); { char *gip = wire_chunk_ptr(kn, &(kn->secret)); memcpy(gip, &privk, sizeof(SECKEYPrivateKey *)); } pluto_crypto_allocchunk(&kn->thespace, &kn->gi, pubk->u.dh.publicValue.len); { char *gip = wire_chunk_ptr(kn, &(kn->gi)); memcpy(gip, pubk->u.dh.publicValue.data, pubk->u.dh.publicValue.len); } pluto_crypto_allocchunk(&kn->thespace, &kn->pubk, sizeof(SECKEYPublicKey*)); { char *gip = wire_chunk_ptr(kn, &(kn->pubk)); memcpy(gip, &pubk, sizeof(SECKEYPublicKey*)); } DBG(DBG_CRYPT, DBG_dump("NSS: Local DH secret:\n" , wire_chunk_ptr(kn, &(kn->secret)) , sizeof(SECKEYPrivateKey*)); DBG_dump("NSS: Public DH value sent(computed in NSS):\n", wire_chunk_ptr(kn, &(kn->gi)),pubk->u.dh.publicValue.len)); DBG(DBG_CRYPT, DBG_dump("NSS: Local DH public value (pointer):\n" , wire_chunk_ptr(kn, &(kn->pubk)) , sizeof(SECKEYPublicKey*))); /* clean up after ourselves */ if (slot) { PK11_FreeSlot(slot); } /* if (privk){SECKEY_DestroyPrivateKey(privk);} */ /* if (pubk){SECKEY_DestroyPublicKey(pubk);} */ freeanychunk(prime); freeanychunk(base); }
/* * invoke helper to do DH work. */ stf_status start_dh_secretiv(struct pluto_crypto_req_cont *cn , struct state *st , enum crypto_importance importance , enum phase1_role init /* TRUE=g_init,FALSE=g_r */ , u_int16_t oakley_group2) { struct pluto_crypto_req r; struct pcr_skeyid_q *dhq; const chunk_t *pss = get_preshared_secret(st->st_connection); err_t e; bool toomuch = FALSE; pcr_init(&r, pcr_compute_dh_iv, importance); dhq = &r.pcr_d.dhq; passert(st->st_sec_in_use); /* convert appropriate data to dhq */ dhq->auth = st->st_oakley.auth; dhq->prf_hash = st->st_oakley.prf_hash; dhq->oakley_group = oakley_group2; dhq->init = init; dhq->keysize = st->st_oakley.enckeylen/BITS_PER_BYTE; passert(r.pcr_d.dhq.oakley_group != 0); DBG(DBG_CONTROL | DBG_CRYPT, DBG_log("parent1 type: %d group: %d len: %d\n", r.pcr_type, r.pcr_d.dhq.oakley_group, (int)r.pcr_len)); if(pss) { pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->pss, *pss); } pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->ni, st->st_ni); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->nr, st->st_nr); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->gi, st->st_gi); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->gr, st->st_gr); pluto_crypto_copychunk(&dhq->thespace, dhq->space , &dhq->secret, st->st_sec_chunk); #ifdef HAVE_LIBNSS /*copying required encryption algo*/ /*dhq->encrypt_algo = st->st_oakley.encrypt;*/ dhq->encrypter = st->st_oakley.encrypter; DBG(DBG_CRYPT, DBG_log("Copying DH pub key pointer to be sent to a thread helper")); pluto_crypto_copychunk(&dhq->thespace, dhq->space , &dhq->pubk, st->pubk); #endif pluto_crypto_allocchunk(&dhq->thespace, &dhq->icookie, COOKIE_SIZE); memcpy(wire_chunk_ptr(dhq, &dhq->icookie) , st->st_icookie, COOKIE_SIZE); pluto_crypto_allocchunk(&dhq->thespace, &dhq->rcookie, COOKIE_SIZE); memcpy(wire_chunk_ptr(dhq, &dhq->rcookie) , st->st_rcookie, COOKIE_SIZE); passert(dhq->oakley_group != 0); e = send_crypto_helper_request(&r, cn, &toomuch); if(e != NULL) { loglog(RC_LOG_SERIOUS, "can not start crypto helper: %s", e); if(toomuch) { return STF_TOOMUCHCRYPTO; } else { return STF_FAIL; } } else if(!toomuch) { st->st_calculating = TRUE; delete_event(st); event_schedule(EVENT_CRYPTO_FAILED, EVENT_CRYPTO_FAILED_DELAY, st); return STF_SUSPEND; } else { /* we must have run the continuation directly, so * complete_state_transition already got called. */ return STF_INLINE; } }
/* * invoke helper to do DH work. */ stf_status start_dh_v2(struct pluto_crypto_req_cont *cn, struct state *st, enum crypto_importance importance, enum phase1_role init, /* TRUE=g_init,FALSE=g_r */ u_int16_t oakley_group2) { struct pluto_crypto_req r; struct pcr_skeyid_q *dhq; err_t e; bool toomuch = FALSE; pcr_init(&r, pcr_compute_dh_v2, importance); dhq = &r.pcr_d.dhq; passert(st->st_sec_in_use); DBG(DBG_CONTROLMORE, DBG_log("calculating skeyseed using prf=%s integ=%s cipherkey=%s", enum_name(&ikev2_trans_type_prf_names, st->st_oakley.prf_hash), enum_name(&ikev2_trans_type_integ_names, st->st_oakley.integ_hash), enum_name(&ikev2_trans_type_encr_names, st->st_oakley.encrypt))); /* convert appropriate data to dhq */ dhq->auth = st->st_oakley.auth; dhq->prf_hash = st->st_oakley.prf_hash; dhq->integ_hash = st->st_oakley.integ_hash; dhq->oakley_group = oakley_group2; dhq->init = init; dhq->keysize = st->st_oakley.enckeylen / BITS_PER_BYTE; passert(r.pcr_d.dhq.oakley_group != 0); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->ni, st->st_ni); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->nr, st->st_nr); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->gi, st->st_gi); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->gr, st->st_gr); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->secret, st->st_sec_chunk); /*copying required encryption algo*/ /*dhq->encrypt_algo = st->st_oakley.encrypter->common.algo_v2id;*/ dhq->encrypter = st->st_oakley.encrypter; DBG(DBG_CRYPT, DBG_log("Copying DH pub key pointer to be sent to a thread helper")); pluto_crypto_copychunk(&dhq->thespace, dhq->space, &dhq->pubk, st->pubk); pluto_crypto_allocchunk(&dhq->thespace, &dhq->icookie, COOKIE_SIZE); memcpy(wire_chunk_ptr(dhq, &dhq->icookie), st->st_icookie, COOKIE_SIZE); pluto_crypto_allocchunk(&dhq->thespace, &dhq->rcookie, COOKIE_SIZE); memcpy(wire_chunk_ptr(dhq, &dhq->rcookie), st->st_rcookie, COOKIE_SIZE); passert(dhq->oakley_group != 0); e = send_crypto_helper_request(&r, cn, &toomuch); if (e != NULL) { loglog(RC_LOG_SERIOUS, "can not start crypto helper: %s", e); if (toomuch) return STF_TOOMUCHCRYPTO; else return STF_FAIL; } else if (!toomuch) { st->st_calculating = TRUE; delete_event(st); event_schedule(EVENT_CRYPTO_FAILED, EVENT_CRYPTO_FAILED_DELAY, st); return STF_SUSPEND; } else { /* we must have run the continuation directly, so * complete_state_transition already got called. */ return STF_INLINE; } }
int main(int argc, char *argv[]) { struct pluto_crypto_req r; struct pcr_skeyid_r *skr = &r.pcr_d.dhr; struct pcr_skeyid_q *skq = &r.pcr_d.dhq; progname = argv[0]; /* initialize list of moduli */ init_crypto(); skq->thespace.start = 0; skq->thespace.len = sizeof(skq->space); skq->auth = tc2_auth; skq->prf_hash = tc2_hash; skq->oakley_group = tc2_oakleygroup; skq->init = tc2_init; skq->keysize = tc2_encrypter->keydeflen/BITS_PER_BYTE; #define copydatlen(field, data, len) do { \ chunk_t tchunk; \ setchunk(tchunk, data, len); \ pluto_crypto_copychunk(&skq->thespace, skq->space \ , &skq->field, tchunk); } \ while(0) copydatlen(ni, tc2_ni, tc2_ni_len); copydatlen(nr, tc2_nr, tc2_nr_len); copydatlen(gi, tc2_gi, tc2_gi_len); copydatlen(gr, tc2_gr, tc2_gr_len); copydatlen(secret, tc2_secret, tc2_secret_len); copydatlen(icookie, tc2_icookie, tc2_icookie_len); copydatlen(rcookie, tc2_rcookie, tc2_rcookie_len); #define dumpdat(field) \ libreswan_DBG_dump(#field, \ wire_chunk_ptr(skq, &skq->field), \ skq->field.len); dumpdat(icookie); dumpdat(rcookie); dumpdat(ni); dumpdat(nr); dumpdat(gi); dumpdat(gr); dumpdat(secret); fflush(stdout); fflush(stderr); calc_dh_iv(&r); printf("\noutput:\n"); { void *shared = wire_chunk_ptr(skr, &skr->shared); libreswan_DBG_dump("shared", shared, skr->shared.len); } exit(4); }