xref: /openbsd-src/sbin/isakmpd/ike_auth.c (revision fe755d9c321afef4f2dd7d6b167b5b3d34d0d7ce)
1*fe755d9cStobhe /* $OpenBSD: ike_auth.c,v 1.118 2020/07/07 17:33:40 tobhe Exp $	 */
28bd04e71Sniklas /* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $	 */
32040585eSniklas 
42040585eSniklas /*
542af7185Sniklas  * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist.  All rights reserved.
6fb1921ccSniklas  * Copyright (c) 1999 Niels Provos.  All rights reserved.
7bdbf6df3Sniklas  * Copyright (c) 1999 Angelos D. Keromytis.  All rights reserved.
84a2e0fb7Sho  * Copyright (c) 2000, 2001, 2003 H�kan Olsson.  All rights reserved.
92040585eSniklas  *
102040585eSniklas  * Redistribution and use in source and binary forms, with or without
112040585eSniklas  * modification, are permitted provided that the following conditions
122040585eSniklas  * are met:
132040585eSniklas  * 1. Redistributions of source code must retain the above copyright
142040585eSniklas  *    notice, this list of conditions and the following disclaimer.
152040585eSniklas  * 2. Redistributions in binary form must reproduce the above copyright
162040585eSniklas  *    notice, this list of conditions and the following disclaimer in the
172040585eSniklas  *    documentation and/or other materials provided with the distribution.
182040585eSniklas  *
192040585eSniklas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
202040585eSniklas  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
212040585eSniklas  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
222040585eSniklas  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
232040585eSniklas  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
242040585eSniklas  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252040585eSniklas  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262040585eSniklas  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272040585eSniklas  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
282040585eSniklas  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292040585eSniklas  */
302040585eSniklas 
312040585eSniklas /*
322040585eSniklas  * This code was written under funding by Ericsson Radio Systems.
332040585eSniklas  */
342040585eSniklas 
352040585eSniklas #include <sys/types.h>
36b3bd141eSniklas #include <sys/stat.h>
37b697c86aSniklas #include <netinet/in.h>
38b697c86aSniklas #include <arpa/inet.h>
392872008fShshoexer 
402872008fShshoexer #include <errno.h>
412872008fShshoexer #include <fcntl.h>
422040585eSniklas #include <stdlib.h>
432040585eSniklas #include <string.h>
442872008fShshoexer #include <unistd.h>
45b3bd141eSniklas #include <regex.h>
46b3bd141eSniklas #include <keynote.h>
47b3bd141eSniklas #include <policy.h>
482040585eSniklas 
492040585eSniklas #include "cert.h"
502040585eSniklas #include "conf.h"
517c990f9aSniklas #include "constants.h"
5293da7598Sho #if defined (USE_DNSSEC)
5393da7598Sho #include "dnssec.h"
5493da7598Sho #endif
552040585eSniklas #include "exchange.h"
562040585eSniklas #include "hash.h"
572040585eSniklas #include "ike_auth.h"
582040585eSniklas #include "ipsec.h"
592040585eSniklas #include "ipsec_doi.h"
60cfe26d10Sniklas #include "libcrypto.h"
612040585eSniklas #include "log.h"
622040585eSniklas #include "message.h"
63da35d433Sho #include "monitor.h"
642040585eSniklas #include "prf.h"
65b697c86aSniklas #include "transport.h"
66b697c86aSniklas #include "util.h"
67271226ebSangelos #include "key.h"
682c07259bSangelos #include "x509.h"
692040585eSniklas 
7068f2431dSniklas #ifdef notyet
7130618ddbSniklas static u_int8_t *enc_gen_skeyid(struct exchange *, size_t *);
7268f2431dSniklas #endif
732040585eSniklas static u_int8_t *pre_shared_gen_skeyid(struct exchange *, size_t *);
742040585eSniklas 
752040585eSniklas static int      pre_shared_decode_hash(struct message *);
762040585eSniklas static int      pre_shared_encode_hash(struct message *);
772040585eSniklas 
7868f2431dSniklas static u_int8_t *sig_gen_skeyid(struct exchange *, size_t *);
7968f2431dSniklas static int      rsa_sig_decode_hash(struct message *);
8068f2431dSniklas static int      rsa_sig_encode_hash(struct message *);
812040585eSniklas 
820b880a72Sho static int      get_raw_key_from_file(int, u_int8_t *, size_t, RSA **);
830b880a72Sho 
8468f2431dSniklas static int      ike_auth_hash(struct exchange *, u_int8_t *);
8568f2431dSniklas 
862040585eSniklas static struct ike_auth ike_auth[] = {
877c990f9aSniklas 	{
8850eea14cSho 		IKE_AUTH_PRE_SHARED, pre_shared_gen_skeyid,
8950eea14cSho 		pre_shared_decode_hash,
907c990f9aSniklas 		pre_shared_encode_hash
917c990f9aSniklas 	},
9268f2431dSniklas #ifdef notdef
937c990f9aSniklas 	{
9450eea14cSho 		IKE_AUTH_DSS, sig_gen_skeyid,
9550eea14cSho 		pre_shared_decode_hash,
967c990f9aSniklas 		pre_shared_encode_hash
977c990f9aSniklas 	},
9868f2431dSniklas #endif
997c990f9aSniklas 	{
10050eea14cSho 		IKE_AUTH_RSA_SIG, sig_gen_skeyid,
10150eea14cSho 		rsa_sig_decode_hash,
1027c990f9aSniklas 		rsa_sig_encode_hash
1037c990f9aSniklas 	},
10468f2431dSniklas #ifdef notdef
1057c990f9aSniklas 	{
10650eea14cSho 		IKE_AUTH_RSA_ENC, enc_gen_skeyid,
10750eea14cSho 		pre_shared_decode_hash,
1087c990f9aSniklas 		pre_shared_encode_hash
1097c990f9aSniklas 	},
1107c990f9aSniklas 	{
11150eea14cSho 		IKE_AUTH_RSA_ENC_REV, enc_gen_skeyid,
11250eea14cSho 		pre_shared_decode_hash,
1137c990f9aSniklas 		pre_shared_encode_hash
1147c990f9aSniklas 	},
11568f2431dSniklas #endif
1162040585eSniklas };
1172040585eSniklas 
1182040585eSniklas struct ike_auth *
ike_auth_get(u_int16_t id)1192040585eSniklas ike_auth_get(u_int16_t id)
1202040585eSniklas {
121c7c448f9Sho 	size_t	i;
1222040585eSniklas 
1232040585eSniklas 	for (i = 0; i < sizeof ike_auth / sizeof ike_auth[0]; i++)
1242040585eSniklas 		if (id == ike_auth[i].id)
1252040585eSniklas 			return &ike_auth[i];
1262040585eSniklas 	return 0;
1272040585eSniklas }
1282040585eSniklas 
1297c990f9aSniklas /*
1307c990f9aSniklas  * Find and decode the configured key (pre-shared or public) for the
1317c990f9aSniklas  * peer denoted by ID.  Stash the len in KEYLEN.
1327c990f9aSniklas  */
133fb1921ccSniklas static void *
ike_auth_get_key(int type,char * id,char * local_id,size_t * keylen)134b3bd141eSniklas ike_auth_get_key(int type, char *id, char *local_id, size_t *keylen)
1357c990f9aSniklas {
1367c990f9aSniklas 	char	*key, *buf;
137db26b2b9Smsf 	char	*keyfile, *privkeyfile;
13831516eecShshoexer 	FILE	*keyfp;
139fb1921ccSniklas 	RSA	*rsakey;
140db26b2b9Smsf 	size_t	 fsize, pkflen;
141db26b2b9Smsf 	int	 fd;
1427c990f9aSniklas 
143fb9475d6Sderaadt 	switch (type) {
144fb1921ccSniklas 	case IKE_AUTH_PRE_SHARED:
1457c990f9aSniklas 		/* Get the pre-shared key for our peer.  */
1467c990f9aSniklas 		key = conf_get_str(id, "Authentication");
147b3bd141eSniklas 		if (!key && local_id)
148b3bd141eSniklas 			key = conf_get_str(local_id, "Authentication");
149b3bd141eSniklas 
150fb9475d6Sderaadt 		if (!key) {
151e41f210aSniklas 			log_print("ike_auth_get_key: "
152e41f210aSniklas 			    "no key found for peer \"%s\" or local ID \"%s\"",
153924a95b5Shshoexer 			    id, local_id ? local_id : "<none>");
1547c990f9aSniklas 			return 0;
1557c990f9aSniklas 		}
1567c990f9aSniklas 		/* If the key starts with 0x it is in hex format.  */
157fb9475d6Sderaadt 		if (strncasecmp(key, "0x", 2) == 0) {
1587c990f9aSniklas 			*keylen = (strlen(key) - 1) / 2;
1597c990f9aSniklas 			buf = malloc(*keylen);
160fb9475d6Sderaadt 			if (!buf) {
16112f43dabShshoexer 				log_error("ike_auth_get_key: malloc (%lu) "
16212f43dabShshoexer 				    "failed", (unsigned long)*keylen);
1637c990f9aSniklas 				return 0;
1647c990f9aSniklas 			}
165fb9475d6Sderaadt 			if (hex2raw(key + 2, (unsigned char *)buf, *keylen)) {
1667c990f9aSniklas 				free(buf);
16712f43dabShshoexer 				log_print("ike_auth_get_key: invalid hex key "
16812f43dabShshoexer 				    "%s", key);
1697c990f9aSniklas 				return 0;
1707c990f9aSniklas 			}
1717c990f9aSniklas 			key = buf;
172fb9475d6Sderaadt 		} else {
1738822032dSho 			buf = key;
1748822032dSho 			key = strdup(buf);
175fb9475d6Sderaadt 			if (!key) {
1768822032dSho 				log_error("ike_auth_get_key: strdup() failed");
1778822032dSho 				return 0;
1788822032dSho 			}
1797c990f9aSniklas 			*keylen = strlen(key);
1808822032dSho 		}
181fb1921ccSniklas 		break;
182fb1921ccSniklas 
183fb1921ccSniklas 	case IKE_AUTH_RSA_SIG:
18412f43dabShshoexer 		if (local_id && (keyfile = conf_get_str("KeyNote",
18512f43dabShshoexer 		    "Credential-directory")) != 0) {
186b3bd141eSniklas 			struct stat     sb;
187b3bd141eSniklas 			struct keynote_deckey dc;
188b3bd141eSniklas 			char           *privkeyfile, *buf2;
18952e9f6e6Sho 			size_t          size;
190cfe26d10Sniklas 
191e9cbd6b9Sderaadt 			if (asprintf(&privkeyfile, "%s/%s/%s", keyfile,
192e9cbd6b9Sderaadt 			    local_id, PRIVATE_KEY_FILE) == -1) {
193e9cbd6b9Sderaadt 				log_print("ike_auth_get_key: failed to asprintf()");
194b3bd141eSniklas 				return 0;
195b3bd141eSniklas 			}
196b3bd141eSniklas 			keyfile = privkeyfile;
197b3bd141eSniklas 
1982872008fShshoexer 			fd = monitor_open(keyfile, O_RDONLY, 0);
1992872008fShshoexer 			if (fd < 0) {
200990feec7Sho 				free(keyfile);
201b3bd141eSniklas 				goto ignorekeynote;
202990feec7Sho 			}
203b3bd141eSniklas 
204df69c215Sderaadt 			if (fstat(fd, &sb) == -1) {
2052872008fShshoexer 				log_print("ike_auth_get_key: fstat failed");
206b3bd141eSniklas 				free(keyfile);
2072872008fShshoexer 				close(fd);
208b3bd141eSniklas 				return 0;
209b3bd141eSniklas 			}
2102872008fShshoexer 			size = (size_t)sb.st_size;
2112872008fShshoexer 
21252e9f6e6Sho 			buf = calloc(size + 1, sizeof(char));
213fb9475d6Sderaadt 			if (!buf) {
21412f43dabShshoexer 				log_print("ike_auth_get_key: failed allocating"
21512f43dabShshoexer 				    " %lu bytes", (unsigned long)size + 1);
216b3bd141eSniklas 				free(keyfile);
2179a53f048Shshoexer 				close(fd);
218b3bd141eSniklas 				return 0;
219b3bd141eSniklas 			}
220fb9475d6Sderaadt 			if (read(fd, buf, size) != (ssize_t)size) {
221b3bd141eSniklas 				free(buf);
222e41f210aSniklas 				log_print("ike_auth_get_key: "
2237eb3b581Sderaadt 				    "failed reading %lu bytes from \"%s\"",
2247eb3b581Sderaadt 				    (unsigned long)size, keyfile);
225b3bd141eSniklas 				free(keyfile);
2269a53f048Shshoexer 				close(fd);
227b3bd141eSniklas 				return 0;
228b3bd141eSniklas 			}
229b3bd141eSniklas 			close(fd);
230b3bd141eSniklas 
231b3bd141eSniklas 			/* Parse private key string */
232b3bd141eSniklas 			buf2 = kn_get_string(buf);
233b3bd141eSniklas 			free(buf);
234b3bd141eSniklas 
235aa8de426Shshoexer 			if (!buf2 || kn_decode_key(&dc, buf2,
236aa8de426Shshoexer 			    KEYNOTE_PRIVATE_KEY) == -1) {
237b3bd141eSniklas 				free(buf2);
23812f43dabShshoexer 				log_print("ike_auth_get_key: failed decoding "
23912f43dabShshoexer 				    "key in \"%s\"", keyfile);
240b3bd141eSniklas 				free(keyfile);
241b3bd141eSniklas 				return 0;
242b3bd141eSniklas 			}
243b3bd141eSniklas 			free(buf2);
244b3bd141eSniklas 
245fb9475d6Sderaadt 			if (dc.dec_algorithm != KEYNOTE_ALGORITHM_RSA) {
24612f43dabShshoexer 				log_print("ike_auth_get_key: wrong algorithm "
24712f43dabShshoexer 				    "type %d in \"%s\"", dc.dec_algorithm,
24812f43dabShshoexer 				    keyfile);
249b3bd141eSniklas 				free(keyfile);
250f61a65acSho 				kn_free_key(&dc);
251b3bd141eSniklas 				return 0;
252b3bd141eSniklas 			}
253b3bd141eSniklas 			free(keyfile);
254b3bd141eSniklas 			return dc.dec_key;
255b3bd141eSniklas 		}
256b3bd141eSniklas ignorekeynote:
257b3bd141eSniklas 		/* Otherwise, try X.509 */
258fb1921ccSniklas 
259db26b2b9Smsf 		privkeyfile = keyfile = NULL;
260db26b2b9Smsf 		fd = -1;
261db26b2b9Smsf 
262db26b2b9Smsf 		if (local_id) {
263db26b2b9Smsf 			/* Look in Private-key-directory. */
264db26b2b9Smsf 			keyfile = conf_get_str("X509-certificates",
265db26b2b9Smsf 			    "Private-key-directory");
266db26b2b9Smsf 			pkflen = strlen(keyfile) + strlen(local_id) + sizeof "/";
267db26b2b9Smsf 			privkeyfile = calloc(pkflen, sizeof(char));
268db26b2b9Smsf 			if (!privkeyfile) {
269db26b2b9Smsf 				log_print("ike_auth_get_key: failed to "
270db26b2b9Smsf 				    "allocate %lu bytes", (unsigned long)pkflen);
27131516eecShshoexer 				return 0;
27231516eecShshoexer 			}
273cbe56935Shshoexer 
274db26b2b9Smsf 			snprintf(privkeyfile, pkflen, "%s/%s", keyfile,
275db26b2b9Smsf 			    local_id);
276db26b2b9Smsf 			keyfile = privkeyfile;
277db26b2b9Smsf 
278db26b2b9Smsf 			fd = monitor_open(keyfile, O_RDONLY, 0);
279df69c215Sderaadt 			if (fd == -1 && errno != ENOENT) {
280db26b2b9Smsf 				log_print("ike_auth_get_key: failed opening "
281db26b2b9Smsf 				    "\"%s\"", keyfile);
282db26b2b9Smsf 				free(privkeyfile);
283d7e1523bSdoug 				privkeyfile = NULL;
284d7e1523bSdoug 				keyfile = NULL;
285db26b2b9Smsf 			}
286db26b2b9Smsf 		}
287db26b2b9Smsf 
288df69c215Sderaadt 		if (fd == -1) {
289db26b2b9Smsf 			/* No key found, try default key. */
290db26b2b9Smsf 			keyfile = conf_get_str("X509-certificates",
291db26b2b9Smsf 			    "Private-key");
292db26b2b9Smsf 
293db26b2b9Smsf 			fd = monitor_open(keyfile, O_RDONLY, 0);
294df69c215Sderaadt 			if (fd == -1) {
295db26b2b9Smsf 				log_print("ike_auth_get_key: failed opening "
296db26b2b9Smsf 				    "\"%s\"", keyfile);
297db26b2b9Smsf 				return 0;
298db26b2b9Smsf 			}
299db26b2b9Smsf 		}
300db26b2b9Smsf 
301db26b2b9Smsf 		if (check_file_secrecy_fd(fd, keyfile, &fsize)) {
302db26b2b9Smsf 			free(privkeyfile);
303996733b2Sdoug 			close(fd);
304cbe56935Shshoexer 			return 0;
305cbe56935Shshoexer 		}
306cbe56935Shshoexer 
307cbe56935Shshoexer 		if ((keyfp = fdopen(fd, "r")) == NULL) {
308cbe56935Shshoexer 			log_print("ike_auth_get_key: fdopen failed");
309db26b2b9Smsf 			free(privkeyfile);
310996733b2Sdoug 			close(fd);
311cbe56935Shshoexer 			return 0;
312cbe56935Shshoexer 		}
31331516eecShshoexer #if SSLEAY_VERSION_NUMBER >= 0x00904100L
31431516eecShshoexer 		rsakey = PEM_read_RSAPrivateKey(keyfp, NULL, NULL, NULL);
31531516eecShshoexer #else
31631516eecShshoexer 		rsakey = PEM_read_RSAPrivateKey(keyfp, NULL, NULL);
31731516eecShshoexer #endif
31831516eecShshoexer 		fclose(keyfp);
31931516eecShshoexer 
320db26b2b9Smsf 		free(privkeyfile);
321db26b2b9Smsf 
322fb9475d6Sderaadt 		if (!rsakey) {
32350eea14cSho 			log_print("ike_auth_get_key: "
32450eea14cSho 			    "PEM_read_bio_RSAPrivateKey failed");
325fb1921ccSniklas 			return 0;
326fb1921ccSniklas 		}
327fb1921ccSniklas 		return rsakey;
328fb1921ccSniklas 
329fb1921ccSniklas 	default:
330fb1921ccSniklas 		log_print("ike_auth_get_key: unknown key type %d", type);
331fb1921ccSniklas 		return 0;
332fb1921ccSniklas 	}
3337c990f9aSniklas 
3347c990f9aSniklas 	return key;
3357c990f9aSniklas }
3367c990f9aSniklas 
3372040585eSniklas static u_int8_t *
pre_shared_gen_skeyid(struct exchange * exchange,size_t * sz)3382040585eSniklas pre_shared_gen_skeyid(struct exchange *exchange, size_t *sz)
3392040585eSniklas {
3402040585eSniklas 	struct prf     *prf;
3412040585eSniklas 	struct ipsec_exch *ie = exchange->data;
342fb9475d6Sderaadt 	u_int8_t       *skeyid, *buf = 0;
343b26670e8Sho 	unsigned char  *key;
344b697c86aSniklas 	size_t          keylen;
345cfe26d10Sniklas 
34668f2431dSniklas 	/*
34768f2431dSniklas 	 * If we're the responder and have the initiator's ID (which is the
34868f2431dSniklas 	 * case in Aggressive mode), try to find the preshared key in the
349b3bd141eSniklas 	 * section of the initiator's Phase 1 ID.  This allows us to do
350b3bd141eSniklas 	 * mobile user support with preshared keys.
35168f2431dSniklas 	 */
352fb9475d6Sderaadt 	if (!exchange->initiator && exchange->id_i) {
353fb9475d6Sderaadt 		switch (exchange->id_i[0]) {
354cfe26d10Sniklas 		case IPSEC_ID_IPV4_ADDR:
3550eb823c5Sniklas 		case IPSEC_ID_IPV6_ADDR:
3560eb823c5Sniklas 			util_ntoa((char **) &buf,
35712f43dabShshoexer 			    exchange->id_i[0] == IPSEC_ID_IPV4_ADDR ? AF_INET :
35812f43dabShshoexer 			    AF_INET6, exchange->id_i + ISAKMP_ID_DATA_OFF -
35912f43dabShshoexer 			    ISAKMP_GEN_SZ);
360cfe26d10Sniklas 			if (!buf)
36168f2431dSniklas 				return 0;
362cfe26d10Sniklas 			break;
363cfe26d10Sniklas 
364cfe26d10Sniklas 		case IPSEC_ID_FQDN:
365cfe26d10Sniklas 		case IPSEC_ID_USER_FQDN:
366fb9475d6Sderaadt 			buf = calloc(exchange->id_i_len - ISAKMP_ID_DATA_OFF +
367fb9475d6Sderaadt 			    ISAKMP_GEN_SZ + 1, sizeof(char));
368fb9475d6Sderaadt 			if (!buf) {
36912f43dabShshoexer 				log_print("pre_shared_gen_skeyid: malloc (%lu"
37012f43dabShshoexer 				    ") failed",
371fb9475d6Sderaadt 				    (unsigned long)exchange->id_i_len -
372fb9475d6Sderaadt 				    ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1);
37368f2431dSniklas 				return 0;
37468f2431dSniklas 			}
375fb9475d6Sderaadt 			memcpy(buf,
37650eea14cSho 			    exchange->id_i + ISAKMP_ID_DATA_OFF -
37750eea14cSho 			    ISAKMP_GEN_SZ,
37812f43dabShshoexer 			    exchange->id_i_len - ISAKMP_ID_DATA_OFF +
37912f43dabShshoexer 			    ISAKMP_GEN_SZ);
380cfe26d10Sniklas 			break;
381cfe26d10Sniklas 
382cfe26d10Sniklas 			/* XXX Support more ID types ? */
383cfe26d10Sniklas 		default:
384b3bd141eSniklas 			break;
385b3bd141eSniklas 		}
386cfe26d10Sniklas 	}
387271226ebSangelos 	/*
388271226ebSangelos 	 * Get the pre-shared key for our peer. This will work even if the key
389271226ebSangelos 	 * has been passed to us through a mechanism like PFKEYv2.
390271226ebSangelos 	 */
391fb9475d6Sderaadt 	key = ike_auth_get_key(IKE_AUTH_PRE_SHARED, exchange->name,
392fb9475d6Sderaadt 	    (char *)buf, &keylen);
393cfe26d10Sniklas 	free(buf);
394b697c86aSniklas 
395a7b8c2e4Sniklas 	/* Fail if no key could be found.  */
396a7b8c2e4Sniklas 	if (!key)
397de162f7aSniklas 		return 0;
398de162f7aSniklas 
39968f2431dSniklas 	/* Store the secret key for later policy processing.  */
4003ec292cfSangelos 	exchange->recv_key = calloc(keylen + 1, sizeof(char));
401271226ebSangelos 	exchange->recv_keytype = ISAKMP_KEY_PASSPHRASE;
402fb9475d6Sderaadt 	if (!exchange->recv_key) {
4037eb3b581Sderaadt 		log_error("pre_shared_gen_skeyid: malloc (%lu) failed",
4047eb3b581Sderaadt 		    (unsigned long)keylen);
4058822032dSho 		free(key);
406fb1921ccSniklas 		return 0;
407fb1921ccSniklas 	}
408271226ebSangelos 	memcpy(exchange->recv_key, key, keylen);
409fb1921ccSniklas 	exchange->recv_certtype = ISAKMP_CERTENC_NONE;
4108822032dSho 	free(key);
411fb1921ccSniklas 
41250eea14cSho 	prf = prf_alloc(ie->prf_type, ie->hash->type, exchange->recv_key,
41350eea14cSho 	    keylen);
4142040585eSniklas 	if (!prf)
4152040585eSniklas 		return 0;
4162040585eSniklas 
4172040585eSniklas 	*sz = prf->blocksize;
4182040585eSniklas 	skeyid = malloc(*sz);
419fb9475d6Sderaadt 	if (!skeyid) {
4207eb3b581Sderaadt 		log_error("pre_shared_gen_skeyid: malloc (%lu) failed",
4217eb3b581Sderaadt 		    (unsigned long)*sz);
4222040585eSniklas 		prf_free(prf);
4232040585eSniklas 		return 0;
4242040585eSniklas 	}
4252040585eSniklas 	prf->Init(prf->prfctx);
4262040585eSniklas 	prf->Update(prf->prfctx, exchange->nonce_i, exchange->nonce_i_len);
4272040585eSniklas 	prf->Update(prf->prfctx, exchange->nonce_r, exchange->nonce_r_len);
4282040585eSniklas 	prf->Final(skeyid, prf->prfctx);
4292040585eSniklas 	prf_free(prf);
4302040585eSniklas 	return skeyid;
4312040585eSniklas }
4322040585eSniklas 
433b3bd141eSniklas /* Both DSS & RSA signature authentication use this algorithm.  */
4342040585eSniklas static u_int8_t *
sig_gen_skeyid(struct exchange * exchange,size_t * sz)4352040585eSniklas sig_gen_skeyid(struct exchange *exchange, size_t *sz)
4362040585eSniklas {
4372040585eSniklas 	struct prf     *prf;
4382040585eSniklas 	struct ipsec_exch *ie = exchange->data;
439b26670e8Sho 	u_int8_t       *skeyid;
440b26670e8Sho 	unsigned char  *key;
4412040585eSniklas 
4422040585eSniklas 	key = malloc(exchange->nonce_i_len + exchange->nonce_r_len);
4432040585eSniklas 	if (!key)
4442040585eSniklas 		return 0;
4452040585eSniklas 	memcpy(key, exchange->nonce_i, exchange->nonce_i_len);
4462040585eSniklas 	memcpy(key + exchange->nonce_i_len, exchange->nonce_r,
4472040585eSniklas 	    exchange->nonce_r_len);
448fdae6d0dSangelos 
449fdae6d0dSangelos 	LOG_DBG((LOG_NEGOTIATION, 80, "sig_gen_skeyid: PRF type %d, hash %d",
450fdae6d0dSangelos 	    ie->prf_type, ie->hash->type));
45112f43dabShshoexer 	LOG_DBG_BUF((LOG_NEGOTIATION, 80,
45212f43dabShshoexer 	    "sig_gen_skeyid: SKEYID initialized with",
453fb9475d6Sderaadt 	    (u_int8_t *)key, exchange->nonce_i_len + exchange->nonce_r_len));
454fdae6d0dSangelos 
4552040585eSniklas 	prf = prf_alloc(ie->prf_type, ie->hash->type, key,
4562040585eSniklas 	    exchange->nonce_i_len + exchange->nonce_r_len);
4572040585eSniklas 	free(key);
4582040585eSniklas 	if (!prf)
4592040585eSniklas 		return 0;
4602040585eSniklas 
4612040585eSniklas 	*sz = prf->blocksize;
4622040585eSniklas 	skeyid = malloc(*sz);
463fb9475d6Sderaadt 	if (!skeyid) {
4647eb3b581Sderaadt 		log_error("sig_gen_skeyid: malloc (%lu) failed",
4657eb3b581Sderaadt 		    (unsigned long)*sz);
4662040585eSniklas 		prf_free(prf);
4672040585eSniklas 		return 0;
4682040585eSniklas 	}
4697eb3b581Sderaadt 	LOG_DBG((LOG_NEGOTIATION, 80, "sig_gen_skeyid: g^xy length %lu",
470*fe755d9cStobhe 	    (unsigned long)ie->g_xy_len));
47112f43dabShshoexer 	LOG_DBG_BUF((LOG_NEGOTIATION, 80,
472f2c2b5e4Spatrick 	    "sig_gen_skeyid: SKEYID fed with g^xy", ie->g_xy, ie->g_xy_len));
473fdae6d0dSangelos 
4742040585eSniklas 	prf->Init(prf->prfctx);
475f2c2b5e4Spatrick 	prf->Update(prf->prfctx, ie->g_xy, ie->g_xy_len);
4762040585eSniklas 	prf->Final(skeyid, prf->prfctx);
4772040585eSniklas 	prf_free(prf);
4782040585eSniklas 	return skeyid;
4792040585eSniklas }
4802040585eSniklas 
48168f2431dSniklas #ifdef notdef
48230618ddbSniklas /*
483b3bd141eSniklas  * Both standard and revised RSA encryption authentication use this SKEYID
48430618ddbSniklas  * computation.
48530618ddbSniklas  */
48630618ddbSniklas static u_int8_t *
enc_gen_skeyid(struct exchange * exchange,size_t * sz)48730618ddbSniklas enc_gen_skeyid(struct exchange *exchange, size_t *sz)
48830618ddbSniklas {
48930618ddbSniklas 	struct prf     *prf;
49030618ddbSniklas 	struct ipsec_exch *ie = exchange->data;
49130618ddbSniklas 	struct hash    *hash = ie->hash;
49230618ddbSniklas 	u_int8_t       *skeyid;
49330618ddbSniklas 
49430618ddbSniklas 	hash->Init(hash->ctx);
49530618ddbSniklas 	hash->Update(hash->ctx, exchange->nonce_i, exchange->nonce_i_len);
49630618ddbSniklas 	hash->Update(hash->ctx, exchange->nonce_r, exchange->nonce_r_len);
49730618ddbSniklas 	hash->Final(hash->digest, hash->ctx);
49830618ddbSniklas 	prf = prf_alloc(ie->prf_type, hash->type, hash->digest, *sz);
49930618ddbSniklas 	if (!prf)
50030618ddbSniklas 		return 0;
50130618ddbSniklas 
50230618ddbSniklas 	*sz = prf->blocksize;
50330618ddbSniklas 	skeyid = malloc(*sz);
504fb9475d6Sderaadt 	if (!skeyid) {
5057c990f9aSniklas 		log_error("enc_gen_skeyid: malloc (%d) failed", *sz);
50630618ddbSniklas 		prf_free(prf);
50730618ddbSniklas 		return 0;
50830618ddbSniklas 	}
50930618ddbSniklas 	prf->Init(prf->prfctx);
51030618ddbSniklas 	prf->Update(prf->prfctx, exchange->cookies, ISAKMP_HDR_COOKIES_LEN);
51130618ddbSniklas 	prf->Final(skeyid, prf->prfctx);
51230618ddbSniklas 	prf_free(prf);
51330618ddbSniklas 	return skeyid;
51430618ddbSniklas }
51568f2431dSniklas #endif				/* notdef */
51630618ddbSniklas 
5172040585eSniklas static int
pre_shared_decode_hash(struct message * msg)5182040585eSniklas pre_shared_decode_hash(struct message *msg)
5192040585eSniklas {
5202040585eSniklas 	struct exchange *exchange = msg->exchange;
5212040585eSniklas 	struct ipsec_exch *ie = exchange->data;
5222040585eSniklas 	struct payload *payload;
5232040585eSniklas 	size_t          hashsize = ie->hash->hashsize;
5242040585eSniklas 	char            header[80];
5252040585eSniklas 	int             initiator = exchange->initiator;
5262040585eSniklas 	u_int8_t      **hash_p;
5272040585eSniklas 
5282040585eSniklas 	/* Choose the right fields to fill-in.  */
5292040585eSniklas 	hash_p = initiator ? &ie->hash_r : &ie->hash_i;
5302040585eSniklas 
53177fa3de5Sho 	payload = payload_first(msg, ISAKMP_PAYLOAD_HASH);
532fb9475d6Sderaadt 	if (!payload) {
533ad336730Sniklas 		log_print("pre_shared_decode_hash: no HASH payload found");
5342040585eSniklas 		return -1;
535ad336730Sniklas 	}
5362040585eSniklas 	/* Check that the hash is of the correct size.  */
5372040585eSniklas 	if (GET_ISAKMP_GEN_LENGTH(payload->p) - ISAKMP_GEN_SZ != hashsize)
5382040585eSniklas 		return -1;
5392040585eSniklas 
5402040585eSniklas 	/* XXX Need this hash be in the SA?  */
5412040585eSniklas 	*hash_p = malloc(hashsize);
542fb9475d6Sderaadt 	if (!*hash_p) {
5437eb3b581Sderaadt 		log_error("pre_shared_decode_hash: malloc (%lu) failed",
5447eb3b581Sderaadt 		    (unsigned long)hashsize);
5452040585eSniklas 		return -1;
5467c990f9aSniklas 	}
5472040585eSniklas 	memcpy(*hash_p, payload->p + ISAKMP_HASH_DATA_OFF, hashsize);
548f799be47Sho 	snprintf(header, sizeof header, "pre_shared_decode_hash: HASH_%c",
5492040585eSniklas 	    initiator ? 'R' : 'I');
55051ca15aeSniklas 	LOG_DBG_BUF((LOG_MISC, 80, header, *hash_p, hashsize));
5512040585eSniklas 
5522040585eSniklas 	payload->flags |= PL_MARK;
5532040585eSniklas 	return 0;
5542040585eSniklas }
5552040585eSniklas 
5567c990f9aSniklas /* Decrypt the HASH in SIG, we already need a parsed ID payload.  */
55730618ddbSniklas static int
rsa_sig_decode_hash(struct message * msg)55830618ddbSniklas rsa_sig_decode_hash(struct message *msg)
55930618ddbSniklas {
56030618ddbSniklas 	struct cert_handler *handler;
56130618ddbSniklas 	struct exchange *exchange = msg->exchange;
56230618ddbSniklas 	struct ipsec_exch *ie = exchange->data;
56330618ddbSniklas 	struct payload *p;
564438b52e4Sangelos 	void           *cert = 0;
565fb9475d6Sderaadt 	u_int8_t       *rawcert = 0, **hash_p, **id_cert, *id;
566fb9475d6Sderaadt 	u_int32_t       rawcertlen, *id_cert_len;
567438b52e4Sangelos 	RSA            *key = 0;
568fb9475d6Sderaadt 	size_t          hashsize = ie->hash->hashsize, id_len;
56930618ddbSniklas 	char            header[80];
570fb9475d6Sderaadt 	int             len, initiator = exchange->initiator;
571d45180a1Sniklas 	int             found = 0, n, i, id_found;
572d30b96b8Sho #if defined (USE_DNSSEC)
5730eb823c5Sniklas 	u_int8_t       *rawkey = 0;
574d30b96b8Sho 	u_int32_t       rawkeylen;
575d30b96b8Sho #endif
57630618ddbSniklas 
57730618ddbSniklas 	/* Choose the right fields to fill-in.  */
57830618ddbSniklas 	hash_p = initiator ? &ie->hash_r : &ie->hash_i;
57930618ddbSniklas 	id = initiator ? exchange->id_r : exchange->id_i;
58030618ddbSniklas 	id_len = initiator ? exchange->id_r_len : exchange->id_i_len;
58130618ddbSniklas 
582fb9475d6Sderaadt 	if (!id || id_len == 0) {
583fb1921ccSniklas 		log_print("rsa_sig_decode_hash: ID is missing");
58430618ddbSniklas 		return -1;
58530618ddbSniklas 	}
58694de5165Sniklas 	/*
58712f43dabShshoexer 	 * XXX Assume we should use the same kind of certification as the
58812f43dabShshoexer 	 * remote...  moreover, just use the first CERT payload to decide what
58912f43dabShshoexer 	 * to use.
59094de5165Sniklas 	 */
59177fa3de5Sho 	p = payload_first(msg, ISAKMP_PAYLOAD_CERT);
592b3bd141eSniklas 	if (!p)
593b3bd141eSniklas 		handler = cert_get(ISAKMP_CERTENC_KEYNOTE);
594b3bd141eSniklas 	else
595b3bd141eSniklas 		handler = cert_get(GET_ISAKMP_CERT_ENCODING(p->p));
596fb9475d6Sderaadt 	if (!handler) {
5970eb823c5Sniklas 		log_print("rsa_sig_decode_hash: cert_get (%d) failed",
5980eb823c5Sniklas 		    p ? GET_ISAKMP_CERT_ENCODING(p->p) : -1);
599fb1921ccSniklas 		return -1;
600fb1921ccSniklas 	}
601b3bd141eSniklas 	/*
602b3bd141eSniklas 	 * We need the policy session initialized now, so we can add
603b3bd141eSniklas 	 * credentials etc.
604b3bd141eSniklas 	 */
605f61a65acSho 	exchange->policy_id = kn_init();
606fb9475d6Sderaadt 	if (exchange->policy_id == -1) {
60712f43dabShshoexer 		log_print("rsa_sig_decode_hash: failed to initialize policy "
60812f43dabShshoexer 		    "session");
609b3bd141eSniklas 		return -1;
610b3bd141eSniklas 	}
611b3bd141eSniklas 
612a7b8c2e4Sniklas 	/* Obtain a certificate from our certificate storage.  */
613fb9475d6Sderaadt 	if (handler->cert_obtain(id, id_len, 0, &rawcert, &rawcertlen)) {
614fb9475d6Sderaadt 		if (handler->id == ISAKMP_CERTENC_X509_SIG) {
615d30b96b8Sho 			cert = handler->cert_get(rawcert, rawcertlen);
616fb1921ccSniklas 			if (!cert)
61712f43dabShshoexer 				LOG_DBG((LOG_CRYPTO, 50, "rsa_sig_decode_hash:"
61812f43dabShshoexer 				    " certificate malformed"));
619fb9475d6Sderaadt 			else {
620fb9475d6Sderaadt 				if (!handler->cert_get_key(cert, &key)) {
621e41f210aSniklas 					log_print("rsa_sig_decode_hash: "
622e41f210aSniklas 					    "decoding certificate failed");
623fb1921ccSniklas 					handler->cert_free(cert);
624fb9475d6Sderaadt 				} else {
625fb1921ccSniklas 					found++;
62651ca15aeSniklas 					LOG_DBG((LOG_CRYPTO, 40,
62712f43dabShshoexer 					    "rsa_sig_decode_hash: using cert "
62812f43dabShshoexer 					    "of type %d", handler->id));
629fb1921ccSniklas 					exchange->recv_cert = cert;
630fb1921ccSniklas 					exchange->recv_certtype = handler->id;
63150eea14cSho 					x509_generate_kn(exchange->policy_id,
63250eea14cSho 					    cert);
633fb1921ccSniklas 				}
634fb1921ccSniklas 			}
635fb9475d6Sderaadt 		} else if (handler->id == ISAKMP_CERTENC_KEYNOTE)
636b3bd141eSniklas 			handler->cert_insert(exchange->policy_id, rawcert);
637fb1921ccSniklas 		free(rawcert);
638fb1921ccSniklas 	}
639fb1921ccSniklas 	/*
640fb1921ccSniklas 	 * Walk over potential CERT payloads in this message.
641fb1921ccSniklas 	 * XXX I believe this is the wrong spot for this.  CERTs can appear
642fb1921ccSniklas 	 * anytime.
643fb1921ccSniklas 	 */
644ed76d6b8Shshoexer 	TAILQ_FOREACH(p, &msg->payload[ISAKMP_PAYLOAD_CERT], link) {
6457c990f9aSniklas 		p->flags |= PL_MARK;
6467c990f9aSniklas 
647fb9475d6Sderaadt 		/*
648fb9475d6Sderaadt 		 * When we have found a key, just walk over the rest, marking
649fb9475d6Sderaadt 		 * them.
650fb9475d6Sderaadt 		 */
6517c990f9aSniklas 		if (found)
6527c990f9aSniklas 			continue;
6537c990f9aSniklas 
6547c990f9aSniklas 		handler = cert_get(GET_ISAKMP_CERT_ENCODING(p->p));
655fb9475d6Sderaadt 		if (!handler) {
65650eea14cSho 			LOG_DBG((LOG_MISC, 30, "rsa_sig_decode_hash: "
65750eea14cSho 			    "no handler for %s CERT encoding",
658107c5904Sho 			    constant_name(isakmp_certenc_cst,
659107c5904Sho 			    GET_ISAKMP_CERT_ENCODING(p->p))));
6607c990f9aSniklas 			continue;
66130618ddbSniklas 		}
662fb1921ccSniklas 		cert = handler->cert_get(p->p + ISAKMP_CERT_DATA_OFF,
663fb9475d6Sderaadt 		    GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_CERT_DATA_OFF);
664fb9475d6Sderaadt 		if (!cert) {
66550eea14cSho 			log_print("rsa_sig_decode_hash: "
66650eea14cSho 			    "can not get data from CERT");
667fb1921ccSniklas 			continue;
668fb1921ccSniklas 		}
669fb9475d6Sderaadt 		if (!handler->cert_validate(cert)) {
670fb1921ccSniklas 			handler->cert_free(cert);
67112f43dabShshoexer 			log_print("rsa_sig_decode_hash: received CERT can't "
67212f43dabShshoexer 			    "be validated");
673fb1921ccSniklas 			continue;
674fb1921ccSniklas 		}
67550eea14cSho 		if (GET_ISAKMP_CERT_ENCODING(p->p) ==
67650eea14cSho 		    ISAKMP_CERTENC_X509_SIG) {
677fb9475d6Sderaadt 			if (!handler->cert_get_subjects(cert, &n, &id_cert,
678fb9475d6Sderaadt 			    &id_cert_len)) {
679fb1921ccSniklas 				handler->cert_free(cert);
68012f43dabShshoexer 				log_print("rsa_sig_decode_hash: can not get "
68112f43dabShshoexer 				    "subject from CERT");
6827c990f9aSniklas 				continue;
68330618ddbSniklas 			}
684d45180a1Sniklas 			id_found = 0;
685d45180a1Sniklas 			for (i = 0; i < n; i++)
686fb9475d6Sderaadt 				if (id_cert_len[i] == id_len &&
687fb9475d6Sderaadt 				    id[0] == id_cert[i][0] &&
68812f43dabShshoexer 				    memcmp(id + 4, id_cert[i] + 4, id_len - 4)
68912f43dabShshoexer 				    == 0) {
690d45180a1Sniklas 					id_found++;
691d45180a1Sniklas 					break;
692d45180a1Sniklas 				}
693fb9475d6Sderaadt 			if (!id_found) {
694fb1921ccSniklas 				handler->cert_free(cert);
69512f43dabShshoexer 				log_print("rsa_sig_decode_hash: no CERT "
69612f43dabShshoexer 				    "subject match the ID");
69730618ddbSniklas 				free(id_cert);
6987c990f9aSniklas 				continue;
69930618ddbSniklas 			}
700d45180a1Sniklas 			cert_free_subjects(n, id_cert, id_cert_len);
701b3bd141eSniklas 		}
702fb9475d6Sderaadt 		if (!handler->cert_get_key(cert, &key)) {
703fb1921ccSniklas 			handler->cert_free(cert);
70412f43dabShshoexer 			log_print("rsa_sig_decode_hash: decoding payload CERT "
70512f43dabShshoexer 			    "failed");
7067c990f9aSniklas 			continue;
70730618ddbSniklas 		}
708fb1921ccSniklas 		/* We validated the cert, cache it for later use.  */
709b3bd141eSniklas 		handler->cert_insert(exchange->policy_id, cert);
710fb1921ccSniklas 
711fb1921ccSniklas 		exchange->recv_cert = cert;
712fb1921ccSniklas 		exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING(p->p);
713fb1921ccSniklas 
714fb9475d6Sderaadt 		if (exchange->recv_certtype == ISAKMP_CERTENC_KEYNOTE) {
715b3bd141eSniklas 			struct keynote_deckey dc;
716b3bd141eSniklas 			char           *pp;
717b3bd141eSniklas 
718b3bd141eSniklas 			dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
719b3bd141eSniklas 			dc.dec_key = key;
720b3bd141eSniklas 
72150eea14cSho 			pp = kn_encode_key(&dc, INTERNAL_ENC_PKCS1,
72250eea14cSho 			    ENCODING_HEX, KEYNOTE_PUBLIC_KEY);
723fb9475d6Sderaadt 			if (pp == NULL) {
724f61a65acSho 				kn_free_key(&dc);
72512f43dabShshoexer 				log_print("rsa_sig_decode_hash: failed to "
72612f43dabShshoexer 				    "ASCII-encode key");
727b3bd141eSniklas 				return -1;
728b3bd141eSniklas 			}
729e9cbd6b9Sderaadt 			if (asprintf(&exchange->keynote_key, "rsa-hex:%s",
730e9cbd6b9Sderaadt 			    pp) == -1) {
7310a814270Smoritz 				free(pp);
732f61a65acSho 				kn_free_key(&dc);
733e9cbd6b9Sderaadt 				log_print("rsa_sig_decode_hash: failed to asprintf()");
734b3bd141eSniklas 				return -1;
735b3bd141eSniklas 			}
736b3bd141eSniklas 			free(pp);
737b3bd141eSniklas 		}
7387c990f9aSniklas 		found++;
7397c990f9aSniklas 	}
7407c990f9aSniklas 
741d30b96b8Sho #if defined (USE_DNSSEC)
742fb9475d6Sderaadt 	/*
743fb9475d6Sderaadt 	 * If no certificate provided a key, try to find a validated DNSSEC
744fb9475d6Sderaadt 	 * KEY.
745fb9475d6Sderaadt 	 */
746fb9475d6Sderaadt 	if (!found) {
747d30b96b8Sho 		rawkey = dns_get_key(IKE_AUTH_RSA_SIG, msg, &rawkeylen);
748d30b96b8Sho 
749d30b96b8Sho 		/* We need to convert 'void *rawkey' into 'RSA *key'.  */
7509cd964b1Sho 		if (dns_RSA_dns_to_x509(rawkey, rawkeylen, &key) == 0)
7519cd964b1Sho 			found++;
7529cd964b1Sho 		else
75312f43dabShshoexer 			log_print("rsa_sig_decode_hash: KEY to RSA key "
75412f43dabShshoexer 			    "conversion failed");
7559cd964b1Sho 
756d30b96b8Sho 		free(rawkey);
757d30b96b8Sho 	}
758d30b96b8Sho #endif				/* USE_DNSSEC */
759d30b96b8Sho 
7600b880a72Sho 	/* If we still have not found a key, try to read it from a file. */
7610b880a72Sho 	if (!found)
76212f43dabShshoexer 		if (get_raw_key_from_file(IKE_AUTH_RSA_SIG, id, id_len, &key)
76312f43dabShshoexer 		    != -1)
7640b880a72Sho 			found++;
7650b880a72Sho 
766fb9475d6Sderaadt 	if (!found) {
767438b52e4Sangelos 		log_print("rsa_sig_decode_hash: no public key found");
768438b52e4Sangelos 		return -1;
769438b52e4Sangelos 	}
77077fa3de5Sho 	p = payload_first(msg, ISAKMP_PAYLOAD_SIG);
771fb9475d6Sderaadt 	if (!p) {
7727c990f9aSniklas 		log_print("rsa_sig_decode_hash: missing signature payload");
773f61a65acSho 		RSA_free(key);
77430618ddbSniklas 		return -1;
77530618ddbSniklas 	}
77630618ddbSniklas 	/* Check that the sig is of the correct size.  */
777fb1921ccSniklas 	len = GET_ISAKMP_GEN_LENGTH(p->p) - ISAKMP_SIG_SZ;
778fb9475d6Sderaadt 	if (len != RSA_size(key)) {
779f61a65acSho 		RSA_free(key);
7807c990f9aSniklas 		log_print("rsa_sig_decode_hash: "
7817c990f9aSniklas 		    "SIG payload length does not match public key");
78230618ddbSniklas 		return -1;
78330618ddbSniklas 	}
784fb1921ccSniklas 	*hash_p = malloc(len);
785fb9475d6Sderaadt 	if (!*hash_p) {
786f61a65acSho 		RSA_free(key);
787fb1921ccSniklas 		log_error("rsa_sig_decode_hash: malloc (%d) failed", len);
78830618ddbSniklas 		return -1;
78930618ddbSniklas 	}
790f61a65acSho 	len = RSA_public_decrypt(len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key,
791f61a65acSho 	    RSA_PKCS1_PADDING);
792fb9475d6Sderaadt 	if (len == -1) {
793f61a65acSho 		RSA_free(key);
794fb1921ccSniklas 		log_print("rsa_sig_decode_hash: RSA_public_decrypt () failed");
795fb1921ccSniklas 		return -1;
796fb1921ccSniklas 	}
797271226ebSangelos 	/* Store key for later use */
798271226ebSangelos 	exchange->recv_key = key;
799271226ebSangelos 	exchange->recv_keytype = ISAKMP_KEY_RSA;
80030618ddbSniklas 
801fb9475d6Sderaadt 	if (len != (int)hashsize) {
80230618ddbSniklas 		free(*hash_p);
8037c990f9aSniklas 		*hash_p = 0;
8047eb3b581Sderaadt 		log_print("rsa_sig_decode_hash: len %lu != hashsize %lu",
8057eb3b581Sderaadt 		    (unsigned long)len, (unsigned long)hashsize);
80630618ddbSniklas 		return -1;
80730618ddbSniklas 	}
808f799be47Sho 	snprintf(header, sizeof header, "rsa_sig_decode_hash: HASH_%c",
809f799be47Sho 	    initiator ? 'R' : 'I');
81051ca15aeSniklas 	LOG_DBG_BUF((LOG_MISC, 80, header, *hash_p, hashsize));
81130618ddbSniklas 
81230618ddbSniklas 	p->flags |= PL_MARK;
81330618ddbSniklas 	return 0;
81430618ddbSniklas }
81530618ddbSniklas 
8162040585eSniklas static int
pre_shared_encode_hash(struct message * msg)8172040585eSniklas pre_shared_encode_hash(struct message *msg)
8182040585eSniklas {
8192040585eSniklas 	struct exchange *exchange = msg->exchange;
8202040585eSniklas 	struct ipsec_exch *ie = exchange->data;
8212040585eSniklas 	size_t          hashsize = ie->hash->hashsize;
8222040585eSniklas 	char            header[80];
8232040585eSniklas 	int             initiator = exchange->initiator;
8242040585eSniklas 	u_int8_t       *buf;
8252040585eSniklas 
826ad336730Sniklas 	buf = ipsec_add_hash_payload(msg, hashsize);
8272040585eSniklas 	if (!buf)
8282040585eSniklas 		return -1;
8292040585eSniklas 
8302040585eSniklas 	if (ike_auth_hash(exchange, buf + ISAKMP_HASH_DATA_OFF) == -1)
8312040585eSniklas 		return -1;
8322040585eSniklas 
833f799be47Sho 	snprintf(header, sizeof header, "pre_shared_encode_hash: HASH_%c",
8342040585eSniklas 	    initiator ? 'I' : 'R');
83550eea14cSho 	LOG_DBG_BUF((LOG_MISC, 80, header, buf + ISAKMP_HASH_DATA_OFF,
83650eea14cSho 	    hashsize));
8372040585eSniklas 	return 0;
8382040585eSniklas }
8392040585eSniklas 
8407c990f9aSniklas /* Encrypt the HASH into a SIG type.  */
84130618ddbSniklas static int
rsa_sig_encode_hash(struct message * msg)84230618ddbSniklas rsa_sig_encode_hash(struct message *msg)
84330618ddbSniklas {
84430618ddbSniklas 	struct exchange *exchange = msg->exchange;
84530618ddbSniklas 	struct ipsec_exch *ie = exchange->data;
846fb9475d6Sderaadt 	size_t          hashsize = ie->hash->hashsize, id_len;
84730618ddbSniklas 	struct cert_handler *handler;
84830618ddbSniklas 	char            header[80];
849fb9475d6Sderaadt 	int             initiator = exchange->initiator, idtype;
850fb9475d6Sderaadt 	u_int8_t       *buf, *data, *buf2, *id;
851fb1921ccSniklas 	u_int32_t       datalen;
8529183be26Sho 	int32_t         sigsize;
8536ff3914eSho 	void           *sent_key;
854fb1921ccSniklas 
855fb1921ccSniklas 	id = initiator ? exchange->id_i : exchange->id_r;
856fb1921ccSniklas 	id_len = initiator ? exchange->id_i_len : exchange->id_r_len;
85730618ddbSniklas 
858271226ebSangelos 	/* We may have been provided these by the kernel */
859b26670e8Sho 	buf = (u_int8_t *)conf_get_str(exchange->name, "Credentials");
86050eea14cSho 	if (buf && (idtype = conf_get_num(exchange->name, "Credential_Type",
8619c16cef7Shshoexer 	    -1)) != -1) {
862271226ebSangelos 		exchange->sent_certtype = idtype;
863b3bd141eSniklas 		handler = cert_get(idtype);
864fb9475d6Sderaadt 		if (!handler) {
86512f43dabShshoexer 			log_print("rsa_sig_encode_hash: cert_get (%d) failed",
86612f43dabShshoexer 			    idtype);
867271226ebSangelos 			return -1;
868271226ebSangelos 		}
86950eea14cSho 		exchange->sent_cert =
87050eea14cSho 		    handler->cert_from_printable((char *)buf);
871fb9475d6Sderaadt 		if (!exchange->sent_cert) {
87212f43dabShshoexer 			log_print("rsa_sig_encode_hash: failed to retrieve "
87312f43dabShshoexer 			    "certificate");
874271226ebSangelos 			return -1;
875271226ebSangelos 		}
876271226ebSangelos 		handler->cert_serialize(exchange->sent_cert, &data, &datalen);
877fb9475d6Sderaadt 		if (!data) {
87812f43dabShshoexer 			log_print("rsa_sig_encode_hash: cert serialization "
87912f43dabShshoexer 			    "failed");
880271226ebSangelos 			return -1;
881271226ebSangelos 		}
882271226ebSangelos 		goto aftercert;	/* Skip all the certificate discovery */
883271226ebSangelos 	}
884271226ebSangelos 	/* XXX This needs to be configurable.  */
885271226ebSangelos 	idtype = ISAKMP_CERTENC_KEYNOTE;
886271226ebSangelos 
887271226ebSangelos 	/* Find a certificate with subjectAltName = id.  */
888271226ebSangelos 	handler = cert_get(idtype);
889fb9475d6Sderaadt 	if (!handler) {
890271226ebSangelos 		idtype = ISAKMP_CERTENC_X509_SIG;
891271226ebSangelos 		handler = cert_get(idtype);
892fb9475d6Sderaadt 		if (!handler) {
89312f43dabShshoexer 			log_print("rsa_sig_encode_hash: cert_get(%d) failed",
89412f43dabShshoexer 			    idtype);
895271226ebSangelos 			return -1;
896271226ebSangelos 		}
897271226ebSangelos 	}
898fb9475d6Sderaadt 	if (handler->cert_obtain(id, id_len, 0, &data, &datalen) == 0) {
899fb9475d6Sderaadt 		if (idtype == ISAKMP_CERTENC_KEYNOTE) {
900d45180a1Sniklas 			idtype = ISAKMP_CERTENC_X509_SIG;
901271226ebSangelos 			handler = cert_get(idtype);
902fb9475d6Sderaadt 			if (!handler) {
90312f43dabShshoexer 				log_print("rsa_sig_encode_hash: cert_get(%d) "
90412f43dabShshoexer 				    "failed", idtype);
90530618ddbSniklas 				return -1;
90630618ddbSniklas 			}
90712f43dabShshoexer 			if (handler->cert_obtain(id, id_len, 0, &data,
90812f43dabShshoexer 			    &datalen) == 0) {
90950eea14cSho 				LOG_DBG((LOG_MISC, 10, "rsa_sig_encode_hash: "
910aa920ac7Sreyk 				    "no certificate to send for id %s",
911aa920ac7Sreyk 				    ipsec_id_string(id, id_len)));
912fb9475d6Sderaadt 				goto skipcert;
913fb9475d6Sderaadt 			}
914fb9475d6Sderaadt 		} else {
915271226ebSangelos 			LOG_DBG((LOG_MISC, 10,
916aa920ac7Sreyk 			    "rsa_sig_encode_hash: no certificate to send"
917aa920ac7Sreyk 			    " for id %s", ipsec_id_string(id, id_len)));
918271226ebSangelos 			goto skipcert;
919271226ebSangelos 		}
920271226ebSangelos 	}
921271226ebSangelos 	/* Let's store the certificate we are going to use */
922271226ebSangelos 	exchange->sent_certtype = idtype;
923271226ebSangelos 	exchange->sent_cert = handler->cert_get(data, datalen);
924fb9475d6Sderaadt 	if (!exchange->sent_cert) {
925271226ebSangelos 		free(data);
92612f43dabShshoexer 		log_print("rsa_sig_encode_hash: failed to get certificate "
92712f43dabShshoexer 		    "from wire encoding");
928271226ebSangelos 		return -1;
929271226ebSangelos 	}
930271226ebSangelos aftercert:
931271226ebSangelos 
93230618ddbSniklas 	buf = realloc(data, ISAKMP_CERT_SZ + datalen);
933fb9475d6Sderaadt 	if (!buf) {
9347c990f9aSniklas 		log_error("rsa_sig_encode_hash: realloc (%p, %d) failed", data,
9357c990f9aSniklas 		    ISAKMP_CERT_SZ + datalen);
93630618ddbSniklas 		free(data);
93730618ddbSniklas 		return -1;
93830618ddbSniklas 	}
93930618ddbSniklas 	memmove(buf + ISAKMP_CERT_SZ, buf, datalen);
940b3bd141eSniklas 	SET_ISAKMP_CERT_ENCODING(buf, idtype);
94130618ddbSniklas 	if (message_add_payload(msg, ISAKMP_PAYLOAD_CERT, buf,
942fb9475d6Sderaadt 	    ISAKMP_CERT_SZ + datalen, 1)) {
94330618ddbSniklas 		free(buf);
94430618ddbSniklas 		return -1;
94530618ddbSniklas 	}
946271226ebSangelos skipcert:
94730618ddbSniklas 
948ea1948caSho 	/* Again, we may have these from the kernel */
949ea1948caSho 	buf = (u_int8_t *)conf_get_str(exchange->name, "PKAuthentication");
950fb9475d6Sderaadt 	if (buf) {
95112f43dabShshoexer 		key_from_printable(ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE,
95212f43dabShshoexer 		    (char *)buf, &data, &datalen);
953fb9475d6Sderaadt 		if (!data) {
95412f43dabShshoexer 			log_print("rsa_sig_encode_hash: badly formatted RSA "
95512f43dabShshoexer 			    "private key");
956ea1948caSho 			return 0;
957ea1948caSho 		}
95812f43dabShshoexer 		sent_key = key_internalize(ISAKMP_KEY_RSA,
95912f43dabShshoexer 		    ISAKMP_KEYTYPE_PRIVATE, data, datalen);
960fb9475d6Sderaadt 		if (!sent_key) {
96112f43dabShshoexer 			log_print("rsa_sig_encode_hash: bad RSA private key "
96212f43dabShshoexer 			    "from dynamic SA acquisition subsystem");
963ea1948caSho 			return 0;
964ea1948caSho 		}
965fb9475d6Sderaadt 	} else {
966fb9475d6Sderaadt 		/* Try through the regular means.  */
967fb9475d6Sderaadt 		switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) {
968b3bd141eSniklas 		case IPSEC_ID_IPV4_ADDR:
969b7465804Sho 		case IPSEC_ID_IPV6_ADDR:
9700eb823c5Sniklas 			util_ntoa((char **)&buf2,
971fb9475d6Sderaadt 			    id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ] ==
972fb9475d6Sderaadt 			    IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6,
9730eb823c5Sniklas 			    id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ);
974b7465804Sho 			if (!buf2)
975b7465804Sho 				return 0;
976b3bd141eSniklas 			break;
977b3bd141eSniklas 
978b3bd141eSniklas 		case IPSEC_ID_FQDN:
979b3bd141eSniklas 		case IPSEC_ID_USER_FQDN:
98012f43dabShshoexer 			buf2 = calloc(id_len - ISAKMP_ID_DATA_OFF +
98112f43dabShshoexer 			    ISAKMP_GEN_SZ + 1, sizeof(char));
982fb9475d6Sderaadt 			if (!buf2) {
98312f43dabShshoexer 				log_print("rsa_sig_encode_hash: malloc (%lu) "
98412f43dabShshoexer 				    "failed", (unsigned long)id_len -
98512f43dabShshoexer 				    ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1);
986b3bd141eSniklas 				return 0;
987b3bd141eSniklas 			}
988b3bd141eSniklas 			memcpy(buf2, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ,
989b3bd141eSniklas 			    id_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ);
990b3bd141eSniklas 			break;
991b3bd141eSniklas 
992b3bd141eSniklas 			/* XXX Support more ID types?  */
993b3bd141eSniklas 		default:
9940eb823c5Sniklas 			buf2 = 0;
995271226ebSangelos 			return 0;
996271226ebSangelos 		}
997271226ebSangelos 
9986ff3914eSho 		sent_key = ike_auth_get_key(IKE_AUTH_RSA_SIG, exchange->name,
999b26670e8Sho 		    (char *)buf2, 0);
1000b3bd141eSniklas 		free(buf2);
1001271226ebSangelos 
1002271226ebSangelos 		/* Did we find a key?  */
1003fb9475d6Sderaadt 		if (!sent_key) {
100450eea14cSho 			log_print("rsa_sig_encode_hash: "
100550eea14cSho 			    "could not get private key");
100630618ddbSniklas 			return -1;
100730618ddbSniklas 		}
1008271226ebSangelos 	}
1009271226ebSangelos 
1010a705c23dSho 	/* Enable RSA blinding.  */
1011fb9475d6Sderaadt 	if (RSA_blinding_on(sent_key, NULL) != 1) {
1012a705c23dSho 		log_error("rsa_sig_encode_hash: RSA_blinding_on () failed.");
101364635110Smoritz 		RSA_free(sent_key);
1014a705c23dSho 		return -1;
1015a705c23dSho 	}
1016fb1921ccSniklas 	/* XXX hashsize is not necessarily prf->blocksize.  */
101730618ddbSniklas 	buf = malloc(hashsize);
1018fb9475d6Sderaadt 	if (!buf) {
10197eb3b581Sderaadt 		log_error("rsa_sig_encode_hash: malloc (%lu) failed",
10207eb3b581Sderaadt 		    (unsigned long)hashsize);
102164635110Smoritz 		RSA_free(sent_key);
102230618ddbSniklas 		return -1;
102330618ddbSniklas 	}
1024fb9475d6Sderaadt 	if (ike_auth_hash(exchange, buf) == -1) {
102530618ddbSniklas 		free(buf);
102664635110Smoritz 		RSA_free(sent_key);
102730618ddbSniklas 		return -1;
102830618ddbSniklas 	}
1029f799be47Sho 	snprintf(header, sizeof header, "rsa_sig_encode_hash: HASH_%c",
1030f799be47Sho 	    initiator ? 'I' : 'R');
103151ca15aeSniklas 	LOG_DBG_BUF((LOG_MISC, 80, header, buf, hashsize));
103230618ddbSniklas 
10336ff3914eSho 	data = malloc(RSA_size(sent_key));
1034fb9475d6Sderaadt 	if (!data) {
1035cfe26d10Sniklas 		log_error("rsa_sig_encode_hash: malloc (%d) failed",
10366ff3914eSho 		    RSA_size(sent_key));
103764635110Smoritz 		free(buf);
103864635110Smoritz 		RSA_free(sent_key);
103930618ddbSniklas 		return -1;
104030618ddbSniklas 	}
10419183be26Sho 	sigsize = RSA_private_encrypt(hashsize, buf, data, sent_key,
1042f61a65acSho 	    RSA_PKCS1_PADDING);
1043fb9475d6Sderaadt 	if (sigsize == -1) {
104450eea14cSho 		log_print("rsa_sig_encode_hash: "
104550eea14cSho 		    "RSA_private_encrypt () failed");
1046ea1948caSho 		free(data);
1047fb1921ccSniklas 		free(buf);
104831516eecShshoexer 		RSA_free(sent_key);
1049fb1921ccSniklas 		return -1;
1050fb1921ccSniklas 	}
10519183be26Sho 	datalen = (u_int32_t) sigsize;
1052fb1921ccSniklas 
105330618ddbSniklas 	free(buf);
105464635110Smoritz 	RSA_free(sent_key);
105530618ddbSniklas 
105630618ddbSniklas 	buf = realloc(data, ISAKMP_SIG_SZ + datalen);
1057fb9475d6Sderaadt 	if (!buf) {
10587c990f9aSniklas 		log_error("rsa_sig_encode_hash: realloc (%p, %d) failed", data,
10597c990f9aSniklas 		    ISAKMP_SIG_SZ + datalen);
106030618ddbSniklas 		free(data);
106130618ddbSniklas 		return -1;
106230618ddbSniklas 	}
106330618ddbSniklas 	memmove(buf + ISAKMP_SIG_SZ, buf, datalen);
106430618ddbSniklas 
1065f799be47Sho 	snprintf(header, sizeof header, "rsa_sig_encode_hash: SIG_%c",
1066f799be47Sho 	    initiator ? 'I' : 'R');
106750eea14cSho 	LOG_DBG_BUF((LOG_MISC, 80, header, buf + ISAKMP_SIG_DATA_OFF,
106850eea14cSho 	    datalen));
106930618ddbSniklas 	if (message_add_payload(msg, ISAKMP_PAYLOAD_SIG, buf,
1070fb9475d6Sderaadt 	    ISAKMP_SIG_SZ + datalen, 1)) {
107130618ddbSniklas 		free(buf);
107230618ddbSniklas 		return -1;
107330618ddbSniklas 	}
107430618ddbSniklas 	return 0;
107530618ddbSniklas }
107630618ddbSniklas 
10772040585eSniklas int
ike_auth_hash(struct exchange * exchange,u_int8_t * buf)10782040585eSniklas ike_auth_hash(struct exchange *exchange, u_int8_t *buf)
10792040585eSniklas {
10802040585eSniklas 	struct ipsec_exch *ie = exchange->data;
10812040585eSniklas 	struct prf     *prf;
10822040585eSniklas 	struct hash    *hash = ie->hash;
10832040585eSniklas 	int             initiator = exchange->initiator;
10842040585eSniklas 	u_int8_t       *id;
10852040585eSniklas 	size_t          id_len;
10862040585eSniklas 
10872040585eSniklas 	/* Choose the right fields to fill-in.  */
10882040585eSniklas 	id = initiator ? exchange->id_i : exchange->id_r;
10892040585eSniklas 	id_len = initiator ? exchange->id_i_len : exchange->id_r_len;
10902040585eSniklas 
10912040585eSniklas 	/* Allocate the prf and start calculating our HASH.  */
10922040585eSniklas 	prf = prf_alloc(ie->prf_type, hash->type, ie->skeyid, ie->skeyid_len);
10932040585eSniklas 	if (!prf)
10942040585eSniklas 		return -1;
10952040585eSniklas 
10962040585eSniklas 	prf->Init(prf->prfctx);
10972040585eSniklas 	prf->Update(prf->prfctx, initiator ? ie->g_xi : ie->g_xr, ie->g_x_len);
10982040585eSniklas 	prf->Update(prf->prfctx, initiator ? ie->g_xr : ie->g_xi, ie->g_x_len);
1099fb9475d6Sderaadt 	prf->Update(prf->prfctx, exchange->cookies +
1100fb9475d6Sderaadt 	    (initiator ? ISAKMP_HDR_ICOOKIE_OFF : ISAKMP_HDR_RCOOKIE_OFF),
11012040585eSniklas 	    ISAKMP_HDR_ICOOKIE_LEN);
1102fb9475d6Sderaadt 	prf->Update(prf->prfctx, exchange->cookies +
1103fb9475d6Sderaadt 	    (initiator ? ISAKMP_HDR_RCOOKIE_OFF : ISAKMP_HDR_ICOOKIE_OFF),
11042040585eSniklas 	    ISAKMP_HDR_ICOOKIE_LEN);
11052040585eSniklas 	prf->Update(prf->prfctx, ie->sa_i_b, ie->sa_i_b_len);
11062040585eSniklas 	prf->Update(prf->prfctx, id, id_len);
11072040585eSniklas 	prf->Final(buf, prf->prfctx);
11082040585eSniklas 	prf_free(prf);
11092040585eSniklas 	return 0;
11102040585eSniklas }
11110b880a72Sho 
11120b880a72Sho static int
get_raw_key_from_file(int type,u_int8_t * id,size_t id_len,RSA ** rsa)11130b880a72Sho get_raw_key_from_file(int type, u_int8_t *id, size_t id_len, RSA **rsa)
11140b880a72Sho {
11150b880a72Sho 	char            filename[FILENAME_MAX];
111607dfae01Sho 	char           *fstr;
111731516eecShshoexer 	FILE           *keyfp;
11180b880a72Sho 
1119fb9475d6Sderaadt 	if (type != IKE_AUTH_RSA_SIG) {	/* XXX More types? */
11200b880a72Sho 		LOG_DBG((LOG_NEGOTIATION, 20, "get_raw_key_from_file: "
11210b880a72Sho 		    "invalid auth type %d\n", type));
11220b880a72Sho 		return -1;
11230b880a72Sho 	}
11240b880a72Sho 	*rsa = 0;
11250b880a72Sho 
112607dfae01Sho 	fstr = conf_get_str("General", "Pubkey-directory");
112707dfae01Sho 	if (!fstr)
112897ba8a98Sho 		fstr = CONF_DFLT_PUBKEY_DIR;
11290b880a72Sho 
1130fb9475d6Sderaadt 	if (snprintf(filename, sizeof filename, "%s/", fstr) >
1131fb9475d6Sderaadt 	    (int)sizeof filename - 1)
113207dfae01Sho 		return -1;
11330b880a72Sho 
113407dfae01Sho 	fstr = ipsec_id_string(id, id_len);
1135fb9475d6Sderaadt 	if (!fstr) {
113607dfae01Sho 		LOG_DBG((LOG_NEGOTIATION, 50, "get_raw_key_from_file: "
113707dfae01Sho 		    "ipsec_id_string failed"));
11380b880a72Sho 		return -1;
11390b880a72Sho 	}
1140e2dc665bSho 	strlcat(filename, fstr, sizeof filename - strlen(filename));
114107dfae01Sho 	free(fstr);
11420b880a72Sho 
11430b880a72Sho 	/* If the file does not exist, fail silently.  */
114431516eecShshoexer 	keyfp = monitor_fopen(filename, "r");
11452872008fShshoexer 	if (keyfp) {
11462872008fShshoexer 		*rsa = PEM_read_RSA_PUBKEY(keyfp, NULL, NULL, NULL);
114729298bbcSmarkus 		if (!*rsa) {
114829298bbcSmarkus 			rewind(keyfp);
114929298bbcSmarkus 			*rsa = PEM_read_RSAPublicKey(keyfp, NULL, NULL, NULL);
115029298bbcSmarkus 		}
1151924a95b5Shshoexer 		if (!*rsa)
1152924a95b5Shshoexer 			log_print("get_raw_key_from_file: failed to get "
1153924a95b5Shshoexer 			    "public key %s", filename);
11542872008fShshoexer 		fclose(keyfp);
11552872008fShshoexer 	} else if (errno != ENOENT) {
115612f43dabShshoexer 		log_error("get_raw_key_from_file: monitor_fopen "
115712f43dabShshoexer 		    "(\"%s\", \"r\") failed", filename);
115831516eecShshoexer 		return -1;
1159fb9475d6Sderaadt 	} else
1160fb9475d6Sderaadt 		LOG_DBG((LOG_NEGOTIATION, 50,
1161fb9475d6Sderaadt 		    "get_raw_key_from_file: file %s not found", filename));
11620b880a72Sho 
11630b880a72Sho 	return (*rsa ? 0 : -1);
11640b880a72Sho }
1165