crypt_dh.c
来自「ipsec vpn」· C语言 代码 · 共 539 行 · 第 1/2 页
C
539 行
/* * Cryptographic helper function - calculate KE and nonce * Copyright (C) 2004 Michael C. Richardson <mcr@xelerance.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * This code was developed with the support of IXIA communications. * * RCSID $Id: crypt_dh.c,v 1.8.2.1 2006/03/20 13:32:03 paul Exp $ */#include <stdlib.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <sys/queue.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/types.h>#include <signal.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include "constants.h"#include "defs.h"#include "packet.h"#include "demux.h"#include "crypto.h"#include "rnd.h"#include "state.h"#include "pluto_crypt.h"#include "oswlog.h"#include "log.h"#include "timer.h"#include "ike_alg.h"#include "secrets.h"/** Compute DH shared secret from our local secret and the peer's public value. * We make the leap that the length should be that of the group * (see quoted passage at start of ACCEPT_KE). */static voidcalc_dh_shared(chunk_t *shared, const chunk_t g , const MP_INT *sec , const struct oakley_group_desc *group){ MP_INT mp_g, mp_shared; struct timeval tv0, tv1; unsigned long tv_diff; gettimeofday(&tv0, NULL); n_to_mpz(&mp_g, g.ptr, g.len); mpz_init(&mp_shared); mpz_powm(&mp_shared, &mp_g, sec, group->modulus); mpz_clear(&mp_g); *shared = mpz_to_n(&mp_shared, group->bytes); mpz_clear(&mp_shared); gettimeofday(&tv1, NULL); tv_diff=(tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec); DBG(DBG_CRYPT, DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec" , enum_show(&oakley_group_names, group->group) , tv_diff); ); /* if took more than 200 msec ... */ if (tv_diff > 200000) { loglog(RC_LOG_SERIOUS, "WARNING: calc_dh_shared(): for %s took " "%ld usec" , enum_show(&oakley_group_names, group->group) , tv_diff); } DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", *shared);}/* SKEYID for preshared keys. * See draft-ietf-ipsec-ike-01.txt 4.1 */static voidskeyid_preshared(const chunk_t pss , const chunk_t ni , const chunk_t nr , const struct hash_desc *hasher , chunk_t *skeyid){ struct hmac_ctx ctx; passert(hasher != NULL); DBG(DBG_CRYPT, DBG_log("Skey inputs (PSK+NI+NR)"); DBG_dump_chunk("ni: ", ni); DBG_dump_chunk("nr: ", nr)); hmac_init_chunk(&ctx, hasher, pss); hmac_update_chunk(&ctx, ni); hmac_update_chunk(&ctx, nr); hmac_final_chunk(*skeyid, "st_skeyid in skeyid_preshared()", &ctx); DBG(DBG_CRYPT, DBG_dump_chunk("keyid: ", *skeyid));}static voidskeyid_digisig(const chunk_t ni , const chunk_t nr , const chunk_t shared , const struct hash_desc *hasher , chunk_t *skeyid){ struct hmac_ctx ctx; chunk_t nir; DBG(DBG_CRYPT, DBG_log("skeyid inputs (digi+NI+NR+shared) hasher: %s", hasher->common.name); DBG_dump_chunk("shared: ", shared); DBG_dump_chunk("ni: ", ni); DBG_dump_chunk("nr: ", nr)); /* We need to hmac_init with the concatenation of Ni_b and Nr_b, * so we have to build a temporary concatentation. */ nir.len = ni.len + nr.len; nir.ptr = alloc_bytes(nir.len, "Ni + Nr in skeyid_digisig"); memcpy(nir.ptr, ni.ptr, ni.len); memcpy(nir.ptr+ ni.len, nr.ptr, nr.len); hmac_init_chunk(&ctx, hasher, nir); pfree(nir.ptr); hmac_update_chunk(&ctx, shared); hmac_final_chunk(*skeyid, "st_skeyid in skeyid_digisig()", &ctx); DBG(DBG_CRYPT, DBG_dump_chunk("keyid: ", *skeyid));}/* Generate the SKEYID_* and new IV * See draft-ietf-ipsec-ike-01.txt 4.1 */static voidcalc_skeyids_iv(struct pcr_skeyid_q *skq , chunk_t shared , const size_t keysize /* = st->st_oakley.enckeylen/BITS_PER_BYTE; */ , chunk_t *skeyid /* output */ , chunk_t *skeyid_d /* output */ , chunk_t *skeyid_a /* output */ , chunk_t *skeyid_e /* output */ , chunk_t *new_iv , chunk_t *enc_key ){ oakley_auth_t auth = skq->auth; oakley_hash_t hash = skq->hash; const struct hash_desc *hasher = crypto_get_hasher(hash); chunk_t pss; chunk_t ni; chunk_t nr; chunk_t gi; chunk_t gr; chunk_t icookie; chunk_t rcookie; /* this doesn't take any memory */ setchunk_fromwire(gi, &skq->gi, skq); setchunk_fromwire(gr, &skq->gr, skq); setchunk_fromwire(ni, &skq->ni, skq); setchunk_fromwire(nr, &skq->nr, skq); setchunk_fromwire(icookie, &skq->icookie, skq); setchunk_fromwire(rcookie, &skq->rcookie, skq); /* Generate the SKEYID */ switch (auth) { case OAKLEY_PRESHARED_KEY: setchunk_fromwire(pss, &skq->pss, skq); skeyid_preshared(pss, ni, nr, hasher, skeyid); break; case OAKLEY_RSA_SIG: skeyid_digisig(ni, nr, shared, hasher, skeyid); break; case OAKLEY_DSS_SIG: /* XXX */ case OAKLEY_RSA_ENC: case OAKLEY_RSA_ENC_REV: case OAKLEY_ELGAMAL_ENC: case OAKLEY_ELGAMAL_ENC_REV: /* XXX */ default: bad_case(auth); } /* generate SKEYID_* from SKEYID */ { struct hmac_ctx ctx; /* SKEYID_D */ hmac_init_chunk(&ctx, hasher, *skeyid); hmac_update_chunk(&ctx, shared); hmac_update_chunk(&ctx, icookie); hmac_update_chunk(&ctx, rcookie); hmac_update(&ctx, "\0", 1); hmac_final_chunk(*skeyid_d, "st_skeyid_d in generate_skeyids_iv()", &ctx); /* SKEYID_A */ hmac_reinit(&ctx); hmac_update_chunk(&ctx, *skeyid_d); hmac_update_chunk(&ctx, shared); hmac_update_chunk(&ctx, icookie); hmac_update_chunk(&ctx, rcookie); hmac_update(&ctx, "\1", 1); hmac_final_chunk(*skeyid_a, "st_skeyid_a in generate_skeyids_iv()", &ctx); /* SKEYID_E */ hmac_reinit(&ctx); hmac_update_chunk(&ctx, *skeyid_a); hmac_update_chunk(&ctx, shared); hmac_update_chunk(&ctx, icookie); hmac_update_chunk(&ctx, rcookie); hmac_update(&ctx, "\2", 1); hmac_final_chunk(*skeyid_e, "st_skeyid_e in generate_skeyids_iv()", &ctx); } /* generate IV */ { union hash_ctx hash_ctx; new_iv->len = hasher->hash_digest_len; new_iv->ptr = alloc_bytes(new_iv->len, "calculated new iv"); DBG(DBG_CRYPT, DBG_dump_chunk("DH_i:", gi); DBG_dump_chunk("DH_r:", gr); ); hasher->hash_init(&hash_ctx); hasher->hash_update(&hash_ctx, gi.ptr, gi.len); hasher->hash_update(&hash_ctx, gr.ptr, gr.len); hasher->hash_final(new_iv->ptr, &hash_ctx); } /* Oakley Keying Material * Derived from Skeyid_e: if it is not big enough, generate more * using the PRF. * See RFC 2409 "IKE" Appendix B */ { u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN]; u_char *k = skeyid_e->ptr; if (keysize > skeyid_e->len) { struct hmac_ctx ctx; size_t i = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?