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

📄 keys.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 3 页
字号:
/* mechanisms for preshared keys (public, private, and preshared secrets) * Copyright (C) 1998-2001  D. Hugh Redelmeier. * * 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. * * RCSID $Id: keys.c,v 1.97 2004/10/21 19:08:29 mcr Exp $ */#include <stddef.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <errno.h>#include <time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <resolv.h>#include <arpa/nameser.h>	/* missing from <resolv.h> on old systems */#include <sys/queue.h>#include <glob.h>#ifndef GLOB_ABORTED# define GLOB_ABORTED    GLOB_ABEND	/* fix for old versions */#endif#include <openswan.h>#include <openswan/ipsec_policy.h>#include "constants.h"#include "defs.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h"	/* needs id.h */#include "state.h"#include "lex.h"#include "keys.h"#include "adns.h"	/* needs <resolv.h> */#include "dnskey.h"	/* needs keys.h and adns.h */#include "log.h"#include "whack.h"	/* for RC_LOG_SERIOUS */#include "timer.h"#include "fetch.h"#include "x509more.h"/* Maximum length of filename and passphrase buffer */#define BUF_LEN		256#ifdef NAT_TRAVERSAL#define PB_STREAM_UNDEFINED#include "nat_traversal.h"#endifstruct fld {    const char *name;    size_t offset;};static const struct fld RSA_private_field[] ={    { "Modulus", offsetof(struct RSA_private_key, pub.n) },    { "PublicExponent", offsetof(struct RSA_private_key, pub.e) },    { "PrivateExponent", offsetof(struct RSA_private_key, d) },    { "Prime1", offsetof(struct RSA_private_key, p) },    { "Prime2", offsetof(struct RSA_private_key, q) },    { "Exponent1", offsetof(struct RSA_private_key, dP) },    { "Exponent2", offsetof(struct RSA_private_key, dQ) },    { "Coefficient", offsetof(struct RSA_private_key, qInv) },};#ifdef DEBUGstatic voidRSA_show_key_fields(struct RSA_private_key *k, int fieldcnt){    const struct fld *p;    DBG_log(" keyid: *%s", k->pub.keyid);    for (p = RSA_private_field; p < &RSA_private_field[fieldcnt]; p++)    {	MP_INT *n = (MP_INT *) ((char *)k + p->offset);	size_t sz = mpz_sizeinbase(n, 16);	char buf[RSA_MAX_OCTETS * 2 + 2];	/* ought to be big enough */	passert(sz <= sizeof(buf));	mpz_get_str(buf, 16, n);	DBG_log(" %s: %s", p->name, buf);    }}/* debugging info that compromises security! */static voidRSA_show_private_key(struct RSA_private_key *k){    RSA_show_key_fields(k, elemsof(RSA_private_field));}static voidRSA_show_public_key(struct RSA_public_key *k){    /* Kludge: pretend that it is a private key, but only display the     * first two fields (which are the public key).     */    passert(offsetof(struct RSA_private_key, pub) == 0);    RSA_show_key_fields((struct RSA_private_key *)k, 2);}#endifstatic const char *RSA_private_key_sanity(struct RSA_private_key *k){    /* note that the *last* error found is reported */    err_t ugh = NULL;    mpz_t t, u, q1;#ifdef DEBUG	/* debugging info that compromises security */    DBG(DBG_PRIVATE, RSA_show_private_key(k));#endif    /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.     * We actually require more (for security).     */    if (k->pub.k < RSA_MIN_OCTETS)	return RSA_MIN_OCTETS_UGH;    /* we picked a max modulus size to simplify buffer allocation */    if (k->pub.k > RSA_MAX_OCTETS)	return RSA_MAX_OCTETS_UGH;    mpz_init(t);    mpz_init(u);    mpz_init(q1);    /* check that n == p * q */    mpz_mul(u, &k->p, &k->q);    if (mpz_cmp(u, &k->pub.n) != 0)	ugh = "n != p * q";    /* check that e divides neither p-1 nor q-1 */    mpz_sub_ui(t, &k->p, 1);    mpz_mod(t, t, &k->pub.e);    if (mpz_cmp_ui(t, 0) == 0)	ugh = "e divides p-1";    mpz_sub_ui(t, &k->q, 1);    mpz_mod(t, t, &k->pub.e);    if (mpz_cmp_ui(t, 0) == 0)	ugh = "e divides q-1";    /* check that d is e^-1 (mod lcm(p-1, q-1)) */    /* see PKCS#1v2, aka RFC 2437, for the "lcm" */    mpz_sub_ui(q1, &k->q, 1);    mpz_sub_ui(u, &k->p, 1);    mpz_gcd(t, u, q1);		/* t := gcd(p-1, q-1) */    mpz_mul(u, u, q1);		/* u := (p-1) * (q-1) */    mpz_divexact(u, u, t);	/* u := lcm(p-1, q-1) */    mpz_mul(t, &k->d, &k->pub.e);    mpz_mod(t, t, u);    if (mpz_cmp_ui(t, 1) != 0)	ugh = "(d * e) mod (lcm(p-1, q-1)) != 1";    /* check that dP is d mod (p-1) */    mpz_sub_ui(u, &k->p, 1);    mpz_mod(t, &k->d, u);    if (mpz_cmp(t, &k->dP) != 0)	ugh = "dP is not congruent to d mod (p-1)";    /* check that dQ is d mod (q-1) */    mpz_sub_ui(u, &k->q, 1);    mpz_mod(t, &k->d, u);    if (mpz_cmp(t, &k->dQ) != 0)	ugh = "dQ is not congruent to d mod (q-1)";    /* check that qInv is (q^-1) mod p */    mpz_mul(t, &k->qInv, &k->q);    mpz_mod(t, t, &k->p);    if (mpz_cmp_ui(t, 1) != 0)	ugh = "qInv is not conguent ot (q^-1) mod p";    mpz_clear(t);    mpz_clear(u);    mpz_clear(q1);    return ugh;}/* * compute an RSA signature with PKCS#1 padding */voidsign_hash(const struct RSA_private_key *k, const u_char *hash_val, size_t hash_len    , u_char *sig_val, size_t sig_len){    chunk_t ch;    mpz_t t1, t2;    size_t padlen;    u_char *p = sig_val;    DBG(DBG_CONTROL | DBG_CRYPT,	DBG_log("signing hash with RSA Key *%s", k->pub.keyid)    )    /* PKCS#1 v1.5 8.1 encryption-block formatting */    *p++ = 0x00;    *p++ = 0x01;	/* BT (block type) 01 */    padlen = sig_len - 3 - hash_len;    memset(p, 0xFF, padlen);    p += padlen;    *p++ = 0x00;    memcpy(p, hash_val, hash_len);    passert(p + hash_len - sig_val == (ptrdiff_t)sig_len);    /* PKCS#1 v1.5 8.2 octet-string-to-integer conversion */    n_to_mpz(t1, sig_val, sig_len);	/* (could skip leading 0x00) */    /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n     * Better described in PKCS#1 v2.0 5.1 RSADP.     * There are two methods, depending on the form of the private key.     * We use the one based on the Chinese Remainder Theorem.     */    mpz_init(t2);    mpz_powm(t2, t1, &k->dP, &k->p);	/* m1 = c^dP mod p */    mpz_powm(t1, t1, &k->dQ, &k->q);	/* m2 = c^dQ mod Q */    mpz_sub(t2, t2, t1);	/* h = qInv (m1 - m2) mod p */    mpz_mod(t2, t2, &k->p);    mpz_mul(t2, t2, &k->qInv);    mpz_mod(t2, t2, &k->p);    mpz_mul(t2, t2, &k->q);	/* m = m2 + h q */    mpz_add(t1, t1, t2);    /* PKCS#1 v1.5 8.4 integer-to-octet-string conversion */    ch = mpz_to_n(t1, sig_len);    memcpy(sig_val, ch.ptr, sig_len);    pfree(ch.ptr);    mpz_clear(t1);    mpz_clear(t2);}const char *shared_secrets_file = SHARED_SECRETS_FILE;struct id_list {    struct id id;    struct id_list *next;};struct secret {    struct id_list *ids;    int             secretlineno;    enum PrivateKeyKind kind;    union {	chunk_t preshared_secret;	struct RSA_private_key RSA_private_key;	smartcard_t *smartcard;    } u;    struct secret *next;};/* * forms the keyid from the public exponent e and modulus n */voidform_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize){    /* eliminate leading zero byte in modulus from ASN.1 coding */    if (*n.ptr == 0x00)    {	n.ptr++;  n.len--;    }    /* form the FreeS/WAN keyid */    keyid[0] = '\0';	/* in case of splitkeytoid failure */    splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF);    /* return the RSA modulus size in octets */    *keysize = n.len;}struct pubkey*allocate_RSA_public_key(const cert_t cert){    struct pubkey *pk = alloc_thing(struct pubkey, "pubkey");    chunk_t e, n;    switch (cert.type)    {    case CERT_PGP:	e = cert.u.pgp->publicExponent;	n = cert.u.pgp->modulus;	break;    case CERT_X509_SIGNATURE:	e = cert.u.x509->publicExponent;	n = cert.u.x509->modulus;	break;    default:	openswan_log("RSA public key allocation error");	return NULL;    }    n_to_mpz(&pk->u.rsa.e, e.ptr, e.len);    n_to_mpz(&pk->u.rsa.n, n.ptr, n.len);    form_keyid(e, n, pk->u.rsa.keyid, &pk->u.rsa.k);#ifdef DEBUG    DBG(DBG_PRIVATE, RSA_show_public_key(&pk->u.rsa));#endif    pk->alg = PUBKEY_ALG_RSA;    pk->id  = empty_id;    pk->issuer = empty_chunk;    return pk;}/* * free a public key struct */voidfree_public_key(struct pubkey *pk){    free_id_content(&pk->id);    freeanychunk(pk->issuer);    /* algorithm-specific freeing */    switch (pk->alg)    {    case PUBKEY_ALG_RSA:	free_RSA_public_content(&pk->u.rsa);	break;    default:	bad_case(pk->alg);    }    pfree(pk);}struct secret *secrets = NULL;/* find the struct secret associated with the combination of * me and the peer.  We match the Id (if none, the IP address). * Failure is indicated by a NULL. */static const struct secret *get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym){    enum {	/* bits */	match_default = 01,	match_him = 02,	match_me = 04    };    unsigned char idstr1[IDTOA_BUF], idme[IDTOA_BUF]	, idhim[IDTOA_BUF], idhim2[IDTOA_BUF];    unsigned int best_match = 0;    struct secret *best = NULL;    struct secret *s;    const struct id *my_id = &c->spd.this.id	, *his_id = &c->spd.that.id;    struct id rw_id;    idtoa(my_id,  idme,  IDTOA_BUF);    idtoa(his_id, idhim, IDTOA_BUF);    strcpy(idhim2, idhim);    DBG(DBG_CONTROL,	DBG_log("started looking for secret for %s->%s of kind %s"		, idme, idhim		, enum_name(&ppk_names, kind)));    /* is there a certificate assigned to this connection? */    if (kind == PPK_RSA	&& c->spd.this.sendcert != cert_forcedtype	&& (c->spd.this.cert.type == CERT_X509_SIGNATURE ||	    c->spd.this.cert.type == CERT_PKCS7_WRAPPED_X509 ||	    c->spd.this.cert.type == CERT_PGP))    {	struct pubkey *my_public_key = allocate_RSA_public_key(c->spd.this.cert);	passert(my_public_key != NULL);	for (s = secrets; s != NULL; s = s->next)	{	    DBG(DBG_CONTROL,		DBG_log("searching for certificate %s:%s vs %s:%s"			, enum_name(&ppk_names, s->kind)			, s->u.RSA_private_key.pub.keyid			, enum_name(&ppk_names, kind)			, my_public_key->u.rsa.keyid)	      );	    if (s->kind == kind &&		same_RSA_public_key(&s->u.RSA_private_key.pub				    , &my_public_key->u.rsa))	    {		best = s;		break; /* we have found the private key - no sense in searching further */	    }	}	free_public_key(my_public_key);	return best;    }    if (his_id_was_instantiated(c) && !(c->policy&AGGRESSIVE))    {	DBG(DBG_CONTROL,	    DBG_log("instantiating him to 0.0.0.0"));	/* roadwarrior: replace him with 0.0.0.0 */	rw_id.kind = addrtypeof(&c->spd.that.host_addr) == AF_INET ?	    ID_IPV4_ADDR : ID_IPV6_ADDR;	happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));	his_id = &rw_id;	idtoa(his_id, idhim2, IDTOA_BUF);    }#ifdef NAT_TRAVERSAL    else if ((nat_traversal_enabled)	     && (c->policy & POLICY_PSK)	     && (kind == PPK_PSK)	     && (((c->kind == CK_TEMPLATE)		  && (c->spd.that.id.kind == ID_NONE))		 || ((c->kind == CK_INSTANCE)		     && (id_is_ipaddr(&c->spd.that.id)))))    {	DBG(DBG_CONTROL,	    DBG_log("replace him to 0.0.0.0"));	/* roadwarrior: replace him with 0.0.0.0 */	rw_id.kind = ID_IPV4_ADDR;	happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));	his_id = &rw_id;	idtoa(his_id, idhim2, IDTOA_BUF);    }#endif    DBG(DBG_CONTROL,	DBG_log("actually looking for secret for %s->%s of kind %s"		, idme, idhim2		, enum_name(&ppk_names, kind)));    for (s = secrets; s != NULL; s = s->next)    {	if (s->kind == kind)	{	    unsigned int match = 0;	    if (s->ids == NULL)	    {		/* a default (signified by lack of ids):		 * accept if no more specific match found		 */		match = match_default;	    }	    else	    {		/* check if both ends match ids */		struct id_list *i;		int idnum = 0;		for (i = s->ids; i != NULL; i = i->next)		{		    idnum++;		    idtoa(&i->id, idstr1, IDTOA_BUF);		    if (same_id(my_id, &i->id))			match |= match_me;		    if (same_id(his_id, &i->id))			match |= match_him;		    DBG(DBG_CONTROL,			DBG_log("%d: compared PSK %s to %s / %s -> %d",				idnum, idstr1, idme, idhim, match));		}		/* If our end matched the only id in the list,		 * default to matching any peer.		 * A more specific match will trump this.		 */		if (match == match_me		    && s->ids->next == NULL)		    match |= match_default;	    }	    switch (match)	    {	    case match_me:		/* if this is an asymmetric (eg. public key) system,		 * allow this-side-only match to count, even if		 * there are other ids in the list.		 */		if (!asym)		    break;		/* FALLTHROUGH */	    case match_default:	/* default all */	    case match_me | match_default:	/* default peer */	    case match_me | match_him:	/* explicit */		if (match == best_match)		{		    /* two good matches are equally good:		     * do they agree?		     */		    bool same;		    switch (kind)		    {		    case PPK_PSK:			same = s->u.preshared_secret.len == best->u.preshared_secret.len			    && memcmp(s->u.preshared_secret.ptr				      , best->u.preshared_secret.ptr				      , s->u.preshared_secret.len) == 0;			break;		    case PPK_RSA:			/* Dirty trick: since we have code to compare			 * RSA public keys, but not private keys, we			 * make the assumption that equal public keys			 * mean equal private keys.  This ought to work.			 */			same = same_RSA_public_key(&s->u.RSA_private_key.pub						   , &best->u.RSA_private_key.pub);			break;		    default:			bad_case(kind);		    }		    if (!same)		    {			loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:"			    " first secret used");

⌨️ 快捷键说明

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