⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipsec_doi.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    /* actual exponentiation; see PKCS#1 v2.0 5.1 */    {	chunk_t temp_s;	mpz_t c;	n_to_mpz(c, sig_val, sig_len);	mpz_powm(c, c, &k->e, &k->n);	temp_s = mpz_to_n(c, sig_len);	/* back to octets */	memcpy(s, temp_s.ptr, sig_len);	pfree(temp_s.ptr);	mpz_clear(c);    }    /* sanity check on signature: see if it matches     * PKCS#1 v1.5 8.1 encryption-block formatting     */    {	err_t ugh = NULL;	if (s[0] != 0x00)	    ugh = "2" "no leading 00";	else if (hash_in_s[-1] != 0x00)	    ugh = "3" "00 separator not present";	else if (s[1] == 0x01)	{	    const u_char *p;	    for (p = &s[2]; p != hash_in_s - 1; p++)	    {		if (*p != 0xFF)		{		    ugh = "4" "invalid Padding String";		    break;		}	    }	}	else if (s[1] == 0x02)	{	    const u_char *p;	    for (p = &s[2]; p != hash_in_s - 1; p++)	    {		if (*p == 0x00)		{		    ugh = "5" "invalid Padding String";		    break;		}	    }	}	else	    ugh = "6" "Block Type not 01 or 02";	if (ugh != NULL)	{	    /* note: it might be a good idea to make sure that	     * an observer cannot tell what kind of failure happened.	     * I don't know what this means in practice.	     */	    /* We probably selected the wrong public key for peer:	     * SIG Payload decrypted into malformed ECB	     */	    /* XXX notification: INVALID_KEY_INFORMATION */	    return ugh;	}    }    /* We have the decoded hash: see if it matches. */    if (memcmp(hash_val, hash_in_s, hash_len) != 0)    {	/* good: header, hash, signature, and other payloads well-formed	 * good: we could find an RSA Sig key for the peer.	 * bad: hash doesn't match	 * Guess: sides disagree about key to be used.	 */	DBG_cond_dump(DBG_CRYPT, "decrypted SIG", s, sig_len);	DBG_cond_dump(DBG_CRYPT, "computed HASH", hash_val, hash_len);	/* XXX notification: INVALID_HASH_INFORMATION */	return "9" "authentication failure: received SIG does not match computed HASH, but message is well-formed";    }    /* Success: copy successful key into state.     * There might be an old one if we previously aborted this     * state transition.     */    unreference_key(&st->st_peer_pubkey);    st->st_peer_pubkey = reference_key(kr);    return NULL;    /* happy happy */}/* Check signature against all RSA public keys we can find. * If we need keys from DNS KEY records, and they haven't been fetched, * return STF_SUSPEND to ask for asynch DNS lookup. * * Note: parameter keys_from_dns contains results of DNS lookup for key * or is NULL indicating lookup not yet tried. * * take_a_crack is a helper function.  Mostly forensic. * If only we had coroutines. */struct tac_state {    /* RSA_check_signature's args that take_a_crack needs */    struct state *st;    const u_char *hash_val;    size_t hash_len;    const pb_stream *sig_pbs;    /* state carried between calls */    err_t best_ugh;	/* most successful failure */    int tried_cnt;	/* number of keys tried */    char tried[50];	/* keyids of tried public keys */    char *tn;	/* roof of tried[] */};static booltake_a_crack(struct tac_state *s, struct pubkey *kr, const char *story USED_BY_DEBUG){    err_t ugh = try_RSA_signature(s->hash_val, s->hash_len, s->sig_pbs	, kr, s->st);    const struct RSA_public_key *k = &kr->u.rsa;    s->tried_cnt++;    if (ugh == NULL)    {	DBG(DBG_CRYPT | DBG_CONTROL	    , DBG_log("an RSA Sig check passed with *%s [%s]"		, k->keyid, story));	return TRUE;    }    else    {	DBG(DBG_CRYPT	    , DBG_log("an RSA Sig check failure %s with *%s [%s]"		, ugh + 1, k->keyid, story));	if (s->best_ugh == NULL || s->best_ugh[0] < ugh[0])	    s->best_ugh = ugh;	if (ugh[0] > '0'	&& s->tn - s->tried + KEYID_BUF + 2 < (ptrdiff_t)sizeof(s->tried))	{	    strcpy(s->tn, " *");	    strcpy(s->tn + 2, k->keyid);	    s->tn += strlen(s->tn);	}	return FALSE;    }}static stf_statusRSA_check_signature(struct state *st, const u_char hash_val[MAX_DIGEST_LEN], size_t hash_len, const pb_stream *sig_pbs#ifdef USE_KEYRR, const struct pubkey_list *keys_from_dns#endif /* USE_KEYRR */, const struct gw_info *gateways_from_dns){    const struct connection *c = st->st_connection;    struct tac_state s;    err_t dns_ugh = NULL;    s.st = st;    s.hash_val = hash_val;    s.hash_len = hash_len;    s.sig_pbs = sig_pbs;    s.best_ugh = NULL;    s.tried_cnt = 0;    s.tn = s.tried;    /* try all gateway records hung off c */    if ((c->policy & POLICY_OPPO))    {	struct gw_info *gw;	for (gw = c->gw_info; gw != NULL; gw = gw->next)	{	    /* only consider entries that have a key and are for our peer */	    if (gw->gw_key_present	    && same_id(&gw->gw_id, &c->spd.that.id)	    && take_a_crack(&s, gw->key, "key saved from DNS TXT"))		return STF_OK;	}    }    /* try all appropriate Public keys */    {	struct pubkey_list *p, **pp;	int pathlen;	pp = &pubkeys;	pathlen = pathlen;      /* make sure it used even with !X509 */	{	  char buf[IDTOA_BUF];	  	  DBG(DBG_CONTROL,	      dntoa_or_null(buf, IDTOA_BUF, c->spd.that.ca, "%any");	      DBG_log("required CA is '%s'", buf));	}  	for (p = pubkeys; p != NULL; p = *pp)	{	    struct pubkey *key = p->key;	    if (key->alg == PUBKEY_ALG_RSA && same_id(&c->spd.that.id, &key->id)	    && trusted_ca(key->issuer, c->spd.that.ca, &pathlen))	    {		time_t now;		{		  char buf[IDTOA_BUF];		  		  DBG(DBG_CONTROL,		      dntoa_or_null(buf, IDTOA_BUF, key->issuer, "%any");		      DBG_log("key issuer CA is '%s'", buf));		}		/* check if found public key has expired */		time(&now);		if (key->until_time != UNDEFINED_TIME && key->until_time < now)		{		    loglog(RC_LOG_SERIOUS,			"cached RSA public key has expired and has been deleted");		    *pp = free_public_keyentry(p);		    continue; /* continue with next public key */		}		if (take_a_crack(&s, key, "preloaded key"))		return STF_OK;	    }	    pp = &p->next;	}   }    /* if no key was found (evidenced by best_ugh == NULL)     * and that side of connection is key_from_DNS_on_demand     * then go search DNS for keys for peer.     */    if (s.best_ugh == NULL && c->spd.that.key_from_DNS_on_demand)    {	if (gateways_from_dns != NULL)	{	    /* TXT keys */	    const struct gw_info *gwp;	    for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next)		if (gwp->gw_key_present		&& take_a_crack(&s, gwp->key, "key from DNS TXT"))		    return STF_OK;	}#ifdef USE_KEYRR	else if (keys_from_dns != NULL)	{	    /* KEY keys */	    const struct pubkey_list *kr;	    for (kr = keys_from_dns; kr != NULL; kr = kr->next)		if (kr->key->alg == PUBKEY_ALG_RSA		&& take_a_crack(&s, kr->key, "key from DNS KEY"))		    return STF_OK;	}#endif /* USE_KEYRR */	else	{	    /* nothing yet: ask for asynch DNS lookup */	    return STF_SUSPEND;	}    }    /* no acceptable key was found: diagnose */    {	char id_buf[IDTOA_BUF];	/* arbitrary limit on length of ID reported */	(void) idtoa(&st->st_connection->spd.that.id, id_buf, sizeof(id_buf));	if (s.best_ugh == NULL)	{	    if (dns_ugh == NULL)		loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"		    , id_buf);	    else		loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"		    "; DNS search for KEY failed (%s)"		    , id_buf, dns_ugh);	    /* ??? is this the best code there is? */	    return STF_FAIL + INVALID_KEY_INFORMATION;	}	if (s.best_ugh[0] == '9')	{	    loglog(RC_LOG_SERIOUS, "%s", s.best_ugh + 1);	    /* XXX Could send notification back */	    return STF_FAIL + INVALID_HASH_INFORMATION;	}	else	{	    if (s.tried_cnt == 1)	    {		loglog(RC_LOG_SERIOUS		    , "Signature check (on %s) failed (wrong key?); tried%s"		    , id_buf, s.tried);		DBG(DBG_CONTROL,		    DBG_log("public key for %s failed:"			" decrypted SIG payload into a malformed ECB (%s)"			, id_buf, s.best_ugh + 1));	    }	    else	    {		loglog(RC_LOG_SERIOUS		    , "Signature check (on %s) failed:"		      " tried%s keys but none worked."		    , id_buf, s.tried);		DBG(DBG_CONTROL,		    DBG_log("all %d public keys for %s failed:"			" best decrypted SIG payload into a malformed ECB (%s)"			, s.tried_cnt, id_buf, s.best_ugh + 1));	    }	    return STF_FAIL + INVALID_KEY_INFORMATION;	}    }}static notification_taccept_nonce(struct msg_digest *md, chunk_t *dest, const char *name){    pb_stream *nonce_pbs = &md->chain[ISAKMP_NEXT_NONCE]->pbs;    size_t len = pbs_left(nonce_pbs);    if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len)    {	loglog(RC_LOG_SERIOUS, "%s length not between %d and %d"	    , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE);	return PAYLOAD_MALFORMED;	/* ??? */    }    clonereplacechunk(*dest, nonce_pbs->cur, len, "nonce");    return NOTHING_WRONG;}/* encrypt message, sans fixed part of header * IV is fetched from st->st_new_iv and stored into st->st_iv. * The theory is that there will be no "backing out", so we commit to IV. * We also close the pbs. */boolencrypt_message(pb_stream *pbs, struct state *st){    const struct encrypt_desc *e = st->st_oakley.encrypter;    u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr);    size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr);    DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len);    /* Pad up to multiple of encryption blocksize.     * See the description associated with the definition of     * struct isakmp_hdr in packet.h.     */    {	size_t padding = pad_up(enc_len, e->enc_blocksize);	if (padding != 0)	{	    if (!out_zero(padding, pbs, "encryption padding"))		return FALSE;	    enc_len += padding;	}    }    DBG(DBG_CRYPT, DBG_log("encrypting using %s", enum_show(&oakley_enc_names, st->st_oakley.encrypt)));    /* e->crypt(TRUE, enc_start, enc_len, st); */    crypto_cbc_encrypt(e, TRUE, enc_start, enc_len, st);    update_iv(st);    DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len);    close_message(pbs);    return TRUE;}/* Compute HASH(1), HASH(2) of Quick Mode. * HASH(1) is part of Quick I1 message. * HASH(2) is part of Quick R1 message. * Used by: quick_outI1, quick_inI1_outR1 (twice), quick_inR1_outI2 * (see RFC 2409 "IKE" 5.5, pg. 18 or draft-ietf-ipsec-ike-01.txt 6.2 pg 25) */static size_tquick_mode_hash12(u_char *dest, const u_char *start, const u_char *roof, const struct state *st, const msgid_t *msgid, bool hash2){    struct hmac_ctx ctx;#if 0	/* if desperate to debug hashing */#   define hmac_update(ctx, ptr, len) { \	DBG_dump("hash input", (ptr), (len)); \	(hmac_update)((ctx), (ptr), (len)); \    }    DBG_dump("hash key", st->st_skeyid_a.ptr, st->st_skeyid_a.len);#endif    hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);    hmac_update(&ctx, (const void *) msgid, sizeof(msgid_t));    if (hash2)	hmac_update_chunk(&ctx, st->st_ni);	/* include Ni_b in the hash */    hmac_update(&ctx, start, roof-start);    hmac_final(dest, &ctx);    DBG(DBG_CRYPT,	DBG_log("HASH(%d) computed:", hash2 + 1);	DBG_dump("", dest, ctx.hmac_digest_len));    return ctx.hmac_digest_len;#   undef hmac_update}/* Compute HASH(3) in Quick Mode (part of Quick I2 message). * Used by: quick_inR1_outI2, quick_inI2 * See RFC2409 "The Internet Key Exchange (IKE)" 5.5. * NOTE: this hash (unlike HASH(1) and HASH(2)) ONLY covers the * Message ID and Nonces.  This is a mistake. */static size_tquick_mode_hash3(u_char *dest, struct state *st){    struct hmac_ctx ctx;    hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);    hmac_update(&ctx, "\0", 1);    hmac_update(&ctx, (u_char *) &st->st_msgid, sizeof(st->st_msgid));    hmac_update_chunk(&ctx, st->st_ni);    hmac_update_chunk(&ctx, st->st_nr);    hmac_final(dest, &ctx);    DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, ctx.hmac_digest_len);    return ctx.hmac_digest_len;}/* Compute Phase 2 IV. * Uses Phase 1 IV from st_iv; puts result in st_new_iv. */voidinit_phase2_iv(struct state *st, const msgid_t *msgid){    const struct hash_desc *h = st->st_oakley.hasher;    union hash_ctx ctx;    DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:"		  , st->st_ph1_iv, st->st_ph1_iv_len);      st->st_new_iv_len = h->hash_digest_len;    passert(st->st_new_iv_len <= sizeof(st->st_new_iv));    DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:"	, st->st_iv, st->st_iv_len);    h->hash_init(&ctx);    h->hash_update(&ctx, st->st_ph1_iv, st->st_ph1_iv_len);    passert(*msgid != 0);    h->hash_update(&ctx, (const u_char *)msgid, sizeof(*msgid));    h->hash_final(st->st_new_iv, &ctx);    DBG_cond_dump(DBG_CRYPT, "computed Ph

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -