summaryrefslogtreecommitdiff
path: root/src/pluto/alg_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/alg_info.c')
-rw-r--r--src/pluto/alg_info.c683
1 files changed, 0 insertions, 683 deletions
diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c
deleted file mode 100644
index fe27c10b2..000000000
--- a/src/pluto/alg_info.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Algorithm info parsing and creation functions
- * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
- * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
- *
- * 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.
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <freeswan.h>
-#include <pfkeyv2.h>
-
-#include <utils.h>
-#include <utils/lexparser.h>
-#include <crypto/diffie_hellman.h>
-#include <crypto/transform.h>
-#include <crypto/proposal/proposal_keywords.h>
-
-
-#include "alg_info.h"
-#include "constants.h"
-#include "defs.h"
-#include "log.h"
-#include "whack.h"
-#include "crypto.h"
-#include "kernel_alg.h"
-#include "ike_alg.h"
-
-/*
- * sadb/ESP aa attrib converters
- */
-int alg_info_esp_aa2sadb(int auth)
-{
- int sadb_aalg = 0;
-
- switch(auth)
- {
- case AUTH_ALGORITHM_HMAC_MD5:
- case AUTH_ALGORITHM_HMAC_SHA1:
- sadb_aalg = auth + 1;
- break;
- default:
- sadb_aalg = auth;
- }
- return sadb_aalg;
-}
-
-int alg_info_esp_sadb2aa(int sadb_aalg)
-{
- int auth = 0;
-
- switch(sadb_aalg)
- {
- case SADB_AALG_MD5HMAC:
- case SADB_AALG_SHA1HMAC:
- auth = sadb_aalg - 1;
- break;
- default:
- auth = sadb_aalg;
- }
- return auth;
-}
-
-void alg_info_free(struct alg_info *alg_info)
-{
- free(alg_info);
-}
-
-/*
- * Raw add routine: only checks for no duplicates
- */
-static void __alg_info_esp_add(struct alg_info_esp *alg_info, int ealg_id,
- unsigned ek_bits, int aalg_id, unsigned ak_bits)
-{
- struct esp_info *esp_info = alg_info->esp;
- unsigned cnt = alg_info->alg_info_cnt, i;
-
- /* check for overflows */
- passert(cnt < countof(alg_info->esp));
-
- /* dont add duplicates */
- for (i = 0; i < cnt; i++)
- {
- if (esp_info[i].esp_ealg_id == ealg_id
- && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits)
- && esp_info[i].esp_aalg_id == aalg_id
- && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits))
- {
- return;
- }
- }
-
- esp_info[cnt].esp_ealg_id = ealg_id;
- esp_info[cnt].esp_ealg_keylen = ek_bits;
- esp_info[cnt].esp_aalg_id = aalg_id;
- esp_info[cnt].esp_aalg_keylen = ak_bits;
-
- /* sadb values */
- esp_info[cnt].encryptalg = ealg_id;
- esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id);
- alg_info->alg_info_cnt++;
-
- DBG(DBG_CRYPT,
- DBG_log("esp alg added: %s_%d/%s, cnt=%d",
- enum_show(&esp_transform_names, ealg_id), ek_bits,
- enum_show(&auth_alg_names, aalg_id),
- alg_info->alg_info_cnt)
- )
-}
-
-/**
- * Returns true if the given alg is an authenticated encryption algorithm
- */
-static bool is_authenticated_encryption(int ealg_id)
-{
- switch (ealg_id)
- {
- case ESP_AES_CCM_8:
- case ESP_AES_CCM_12:
- case ESP_AES_CCM_16:
- case ESP_AES_GCM_8:
- case ESP_AES_GCM_12:
- case ESP_AES_GCM_16:
- case ESP_AES_GMAC:
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- * Add ESP alg info _with_ logic (policy):
- */
-static void alg_info_esp_add(struct alg_info *alg_info, int ealg_id,
- int ek_bits, int aalg_id, int ak_bits)
-{
- /* Policy: default to 3DES */
- if (ealg_id == 0)
- {
- ealg_id = ESP_3DES;
- }
- if (ealg_id > 0)
- {
- if (is_authenticated_encryption(ealg_id))
- {
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_NONE, 0);
- }
- else if (aalg_id > 0)
- {
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- aalg_id, ak_bits);
- }
- else
- {
- /* Policy: default to SHA-1 and MD5 */
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
- __alg_info_esp_add((struct alg_info_esp *)alg_info,
- ealg_id, ek_bits,
- AUTH_ALGORITHM_HMAC_MD5, ak_bits);
- }
- }
-}
-
-static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id,
- unsigned ek_bits, int aalg_id, unsigned ak_bits,
- int modp_id)
-{
- struct ike_info *ike_info = alg_info->ike;
- unsigned cnt = alg_info->alg_info_cnt;
- unsigned i;
-
- /* check for overflows */
- passert(cnt < countof(alg_info->ike));
-
- /* dont add duplicates */
- for (i = 0; i < cnt; i++)
- {
- if (ike_info[i].ike_ealg == ealg_id
- && (!ek_bits || ike_info[i].ike_eklen == ek_bits)
- && ike_info[i].ike_halg == aalg_id
- && (!ak_bits || ike_info[i].ike_hklen == ak_bits)
- && ike_info[i].ike_modp==modp_id)
- return;
- }
-
- ike_info[cnt].ike_ealg = ealg_id;
- ike_info[cnt].ike_eklen = ek_bits;
- ike_info[cnt].ike_halg = aalg_id;
- ike_info[cnt].ike_hklen = ak_bits;
- ike_info[cnt].ike_modp = modp_id;
- alg_info->alg_info_cnt++;
-
- DBG(DBG_CRYPT,
- DBG_log("ikg alg added: %s_%d/%s/%s, cnt=%d",
- enum_show(&oakley_enc_names, ealg_id), ek_bits,
- enum_show(&oakley_hash_names, aalg_id),
- enum_show(&oakley_group_names, modp_id),
- alg_info->alg_info_cnt)
- )
-}
-
-/*
- * Proposals will be built by looping over default_ike_groups array and
- * merging alg_info (ike_info) contents
- */
-
-static int default_ike_groups[] = {
- MODP_1536_BIT,
- MODP_1024_BIT
-};
-
-/*
- * Add IKE alg info _with_ logic (policy):
- */
-static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id,
- int ek_bits, int aalg_id, int ak_bits, int modp_id)
-{
- int i = 0;
- int n_groups = countof(default_ike_groups);
-
- /* if specified modp_id avoid loop over default_ike_groups */
- if (modp_id)
- {
- n_groups=0;
- goto in_loop;
- }
-
- for (; n_groups--; i++)
- {
- modp_id = default_ike_groups[i];
-in_loop:
- /* Policy: default to 3DES */
- if (ealg_id == 0)
- {
- ealg_id = OAKLEY_3DES_CBC;
- }
- if (ealg_id > 0)
- {
- if (aalg_id > 0)
- {
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- aalg_id, ak_bits,
- modp_id);
- }
- else
- {
- /* Policy: default to MD5 and SHA */
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- OAKLEY_MD5, ak_bits,
- modp_id);
- __alg_info_ike_add((struct alg_info_ike *)alg_info,
- ealg_id, ek_bits,
- OAKLEY_SHA, ak_bits,
- modp_id);
- }
- }
- }
-}
-
-static status_t alg_info_add(chunk_t alg, unsigned protoid,
- int *ealg, size_t *ealg_keysize,
- int *aalg, size_t *aalg_keysize, int *dh_group)
-{
- const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
-
- if (token == NULL)
- {
- return FAILED;
- }
- switch (token->type)
- {
- case ENCRYPTION_ALGORITHM:
- if (*ealg != 0)
- {
- return FAILED;
- }
- *ealg = (protoid == PROTO_ISAKMP) ?
- oakley_from_encryption_algorithm(token->algorithm) :
- esp_from_encryption_algorithm(token->algorithm);
- if (*ealg == 0)
- {
- return FAILED;
- }
- *ealg_keysize = token->keysize;
- break;
- case INTEGRITY_ALGORITHM:
- if (*aalg != 0)
- {
- return FAILED;
- }
- *aalg = (protoid == PROTO_ISAKMP) ?
- oakley_from_integrity_algorithm(token->algorithm) :
- esp_from_integrity_algorithm(token->algorithm);
- if (*aalg == 0)
- {
- return FAILED;
- }
- *aalg_keysize = token->keysize;
- break;
- case DIFFIE_HELLMAN_GROUP:
- if (protoid == PROTO_ISAKMP)
- {
- if (*dh_group != 0)
- {
- return FAILED;
- }
- *dh_group = token->algorithm;
- }
- break;
- default:
- return FAILED;
- }
- return SUCCESS;
-}
-
-
-static status_t alg_info_parse_str(struct alg_info *alg_info, char *alg_str)
-{
- char *strict, *single;
- status_t status = SUCCESS;
-
- strict = alg_str + strlen(alg_str) - 1;
- if (*strict == '!')
- {
- alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
- *strict = '\0';
- }
- while ((single = strsep(&alg_str, ",")))
- {
- chunk_t string = { (u_char *)single, strlen(single) };
- int ealg = 0;
- int aalg = 0;
- int dh_group = 0;
- size_t ealg_keysize = 0;
- size_t aalg_keysize = 0;
-
- eat_whitespace(&string);
-
- if (string.len > 0)
- {
- chunk_t alg;
-
- /* get all token, separated by '-' */
- while (extract_token(&alg, '-', &string))
- {
- status |= alg_info_add(alg, alg_info->alg_info_protoid,
- &ealg, &ealg_keysize,
- &aalg, &aalg_keysize, &dh_group);
- }
- if (string.len)
- {
- status |= alg_info_add(string, alg_info->alg_info_protoid,
- &ealg, &ealg_keysize,
- &aalg, &aalg_keysize, &dh_group);
- }
- }
- if (status == SUCCESS)
-
- {
- switch (alg_info->alg_info_protoid)
- {
- case PROTO_IPSEC_ESP:
- alg_info_esp_add(alg_info, ealg, ealg_keysize,
- aalg, aalg_keysize);
- break;
- case PROTO_ISAKMP:
- alg_info_ike_add(alg_info, ealg, ealg_keysize,
- aalg, aalg_keysize,
- dh_group);
- break;
- default:
- break;
- }
- }
- }
- return status;
-}
-
-struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
-{
- struct alg_info_esp *alg_info_esp;
- char esp_buf[BUF_LEN];
- char *pfs_name;
- status_t status = SUCCESS;
- /*
- * alg_info storage should be sized dynamically
- * but this may require 2passes to know
- * transform count in advance.
- */
- alg_info_esp = malloc_thing (struct alg_info_esp);
- zero(alg_info_esp);
-
- pfs_name=strchr(alg_str, ';');
- if (pfs_name)
- {
- memcpy(esp_buf, alg_str, pfs_name-alg_str);
- esp_buf[pfs_name-alg_str] = 0;
- alg_str = esp_buf;
- pfs_name++;
-
- /* if pfs strings AND first char is not '0' */
- if (*pfs_name && pfs_name[0] != '0')
- {
- const proposal_token_t *token;
-
- token = proposal_get_token(pfs_name, strlen(pfs_name));
- if (token == NULL || token->type != DIFFIE_HELLMAN_GROUP)
- {
- /* Bomb if pfsgroup not found */
- DBG(DBG_CRYPT,
- DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found"
- , pfs_name)
- )
- status = FAILED;
- goto out;
- }
- alg_info_esp->esp_pfsgroup = token->algorithm;
- }
- }
- else
- {
- alg_info_esp->esp_pfsgroup = 0;
- }
- alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP;
- status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
-
-out:
- if (status == SUCCESS)
- {
- alg_info_esp->ref_cnt = 1;
- return alg_info_esp;
- }
- else
- {
- free(alg_info_esp);
- return NULL;
- }
-}
-
-struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
-{
- struct alg_info_ike *alg_info_ike;
- /*
- * alg_info storage should be sized dynamically
- * but this may require 2passes to know
- * transform count in advance.
- */
- alg_info_ike = malloc_thing (struct alg_info_ike);
- zero(alg_info_ike);
- alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
-
- if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
- {
- alg_info_ike->ref_cnt = 1;
- return alg_info_ike;
- }
- else
- {
- free(alg_info_ike);
- return NULL;
- }
-}
-
-/*
- * alg_info struct can be shared by
- * several connections instances,
- * handle free() with ref_cnts
- */
-void
-alg_info_addref(struct alg_info *alg_info)
-{
- if (alg_info != NULL)
- {
- alg_info->ref_cnt++;
- }
-}
-
-void
-alg_info_delref(struct alg_info **alg_info_p)
-{
- struct alg_info *alg_info = *alg_info_p;
-
- if (alg_info != NULL)
- {
- passert(alg_info->ref_cnt != 0);
- alg_info->ref_cnt--;
- if (alg_info->ref_cnt == 0)
- {
- alg_info_free(alg_info);
- }
- *alg_info_p = NULL;
- }
-}
-
-/* snprint already parsed transform list (alg_info) */
-int
-alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info)
-{
- char *ptr = buf;
- int np = 0;
- struct esp_info *esp_info;
- struct ike_info *ike_info;
- int cnt;
-
- switch (alg_info->alg_info_protoid) {
- case PROTO_IPSEC_ESP:
- {
- struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info;
-
- ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt)
- {
- np = snprintf(ptr, buflen, "%s",
- enum_show(&esp_transform_names, esp_info->esp_ealg_id));
- ptr += np;
- buflen -= np;
- if (esp_info->esp_ealg_keylen)
- {
- np = snprintf(ptr, buflen, "_%zu", esp_info->esp_ealg_keylen);
- ptr += np;
- buflen -= np;
- }
- np = snprintf(ptr, buflen, "/%s, ",
- enum_show(&auth_alg_names, esp_info->esp_aalg_id));
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- if (alg_info_esp->esp_pfsgroup)
- {
- np = snprintf(ptr, buflen, "; pfsgroup=%s; ",
- enum_show(&oakley_group_names, alg_info_esp->esp_pfsgroup));
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- break;
- }
-
- case PROTO_ISAKMP:
- ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt)
- {
- np = snprintf(ptr, buflen, "%s",
- enum_show(&oakley_enc_names, ike_info->ike_ealg));
- ptr += np;
- buflen -= np;
- if (ike_info->ike_eklen)
- {
- np = snprintf(ptr, buflen, "_%zu", ike_info->ike_eklen);
- ptr += np;
- buflen -= np;
- }
- np = snprintf(ptr, buflen, "/%s/%s, ",
- enum_show(&oakley_hash_names, ike_info->ike_halg),
- enum_show(&oakley_group_names, ike_info->ike_modp));
- ptr += np;
- buflen -= np;
- if (buflen < 0)
- goto out;
- }
- break;
- default:
- np = snprintf(buf, buflen, "INVALID protoid=%d\n"
- , alg_info->alg_info_protoid);
- ptr += np;
- buflen -= np;
- goto out;
- }
-
- np = snprintf(ptr, buflen, "%s"
- , alg_info->alg_info_flags & ALG_INFO_F_STRICT?
- "strict":"");
- ptr += np;
- buflen -= np;
-out:
- if (buflen < 0)
- {
- loglog(RC_LOG_SERIOUS
- , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d"
- , buflen);
- }
-
- return ptr - buf;
-}
-
-int alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info)
-{
- char *ptr = buf;
-
- int cnt = alg_info->alg_info_cnt;
- struct esp_info *esp_info = alg_info->esp;
-
- while (cnt--)
- {
- if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL)
- && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL))
- {
- u_int eklen = (esp_info->esp_ealg_keylen)
- ? esp_info->esp_ealg_keylen
- : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id)
- * BITS_PER_BYTE;
-
- u_int aklen = esp_info->esp_aalg_keylen
- ? esp_info->esp_aalg_keylen
- : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id)
- * BITS_PER_BYTE;
-
- int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ",
- esp_info->esp_ealg_id, eklen,
- esp_info->esp_aalg_id, aklen);
- ptr += ret;
- buflen -= ret;
- if (buflen < 0)
- break;
- }
- esp_info++;
- }
- return ptr - buf;
-}
-
-int alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info)
-{
- char *ptr = buf;
-
- int cnt = alg_info->alg_info_cnt;
- struct ike_info *ike_info = alg_info->ike;
-
- while (cnt--)
- {
- struct encrypt_desc *enc_desc = ike_alg_get_crypter(ike_info->ike_ealg);
- struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg);
- struct dh_desc *dh_desc = ike_alg_get_dh_group(ike_info->ike_modp);
-
- if (enc_desc && hash_desc && dh_desc)
- {
-
- u_int eklen = (ike_info->ike_eklen)
- ? ike_info->ike_eklen
- : enc_desc->keydeflen;
-
- u_int aklen = (ike_info->ike_hklen)
- ? ike_info->ike_hklen
- : hash_desc->hash_digest_size * BITS_PER_BYTE;
-
- int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ",
- ike_info->ike_ealg, eklen,
- ike_info->ike_halg, aklen,
- ike_info->ike_modp);
- ptr += ret;
- buflen -= ret;
- if (buflen < 0)
- break;
- }
- ike_info++;
- }
- return ptr - buf;
-}
-