int ipsec_sa_init(struct ipsec_sa *ipsp) { int i; int error = 0; char sa[SATOT_BUF]; size_t sa_len; char ipaddr_txt[ADDRTOA_BUF]; char ipaddr2_txt[ADDRTOA_BUF]; #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char kb[AHMD596_BLKLEN]; #endif struct ipsec_alg_enc *ixt_e = NULL; struct ipsec_alg_auth *ixt_a = NULL; if(ipsp == NULL) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "ipsp is NULL, fatal\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &ipsp->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) called for SA:%s\n", sa_len ? sa : " (error)"); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "calling init routine of %s%s%s\n", IPS_XFORM_NAME(ipsp)); switch(ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: { ipsp->ips_xformfuncs = ipip_xform_funcs; addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_s))->sin_addr, 0, ipaddr_txt, sizeof(ipaddr_txt)); addrtoa(((struct sockaddr_in*)(ipsp->ips_addr_d))->sin_addr, 0, ipaddr2_txt, sizeof(ipaddr_txt)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", ipaddr_txt, ipaddr2_txt); } break; #endif /* !CONFIG_KLIPS_IPIP */ #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: ipsp->ips_xformfuncs = ah_xform_funcs; switch(ipsp->ips_authalg) { # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { unsigned char *akp; unsigned int aks; MD5_CTX *ictx; MD5_CTX *octx; if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { unsigned char *akp; unsigned int aks; SHA1_CTX *ictx; SHA1_CTX *octx; if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel", ipsp->ips_authalg); SENDERR(EINVAL); } break; #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: ipsp->ips_xformfuncs = esp_xform_funcs; { #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char *akp; unsigned int aks; #endif ipsec_alg_sa_init(ipsp); ixt_e=ipsp->ips_alg_enc; if (ixt_e == NULL) { if(printk_ratelimit()) { printk(KERN_ERR "ipsec_sa_init: " "encalg=%d support not available in the kernel", ipsp->ips_encalg); } SENDERR(ENOENT); } ipsp->ips_iv_size = ixt_e->ixt_common.ixt_support.ias_ivlen/8; /* Create IV */ if (ipsp->ips_iv_size) { if((ipsp->ips_iv = (caddr_t) kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) { SENDERR(ENOMEM); } prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; } if ((error=ipsec_alg_enc_key_create(ipsp)) < 0) SENDERR(-error); if ((ixt_a=ipsp->ips_alg_auth)) { if ((error=ipsec_alg_auth_key_create(ipsp)) < 0) SENDERR(-error); } else switch(ipsp->ips_authalg) { # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { MD5_CTX *ictx; MD5_CTX *octx; if(ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)(ipsp->ips_key_a))+0)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+1)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+2)), ntohl(*(((__u32 *)(ipsp->ips_key_a))+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* paranoid */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { SHA1_CTX *ictx; SHA1_CTX *octx; if(ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n"/*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a)+0)), ntohl(*(((__u32 *)ipsp->ips_key_a)+1)), ntohl(*(((__u32 *)ipsp->ips_key_a)+2)), ntohl(*(((__u32 *)ipsp->ips_key_a)+3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) { kb[i] = akp[i] ^ HMAC_IPAD; } for (; i < AHMD596_BLKLEN; i++) { kb[i] = HMAC_IPAD; } ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) { kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); } octx = &((struct sha1_ctx*)(ipsp->ips_key_a))->octx; SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel.\n", ipsp->ips_authalg); SENDERR(EINVAL); } } break; #endif /* !CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ipsp->ips_xformfuncs = ipcomp_xform_funcs; ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; break; #endif /* CONFIG_KLIPS_IPCOMP */ default: printk(KERN_ERR "KLIPS sa initialization: " "proto=%d unknown.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return(error); }
int pfkey_sa_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data* extr) { struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext; int error = 0; struct ipsec_sa* ipsp; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: .\n"); if(!extr || !extr->ips) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "extr or extr->ips is NULL, fatal\n"); SENDERR(EINVAL); } switch(pfkey_ext->sadb_ext_type) { case SADB_EXT_SA: ipsp = extr->ips; break; case SADB_X_EXT_SA2: if(extr->ips2 == NULL) { extr->ips2 = ipsec_sa_alloc(&error); /* pass error var by pointer */ } if(extr->ips2 == NULL) { SENDERR(-error); } ipsp = extr->ips2; break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "invalid exttype=%d.\n", pfkey_ext->sadb_ext_type); SENDERR(EINVAL); } ipsp->ips_said.spi = pfkey_sa->sadb_sa_spi; ipsp->ips_replaywin = pfkey_sa->sadb_sa_replay; ipsp->ips_state = pfkey_sa->sadb_sa_state; ipsp->ips_flags = pfkey_sa->sadb_sa_flags; ipsp->ips_replaywin_lastseq = ipsp->ips_replaywin_bitmap = 0; ipsp->ips_ref_rel = pfkey_sa->sadb_x_sa_ref; switch(ipsp->ips_said.proto) { case IPPROTO_AH: ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; ipsp->ips_encalg = SADB_EALG_NONE; break; case IPPROTO_ESP: ipsp->ips_authalg = pfkey_sa->sadb_sa_auth; ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; #ifdef CONFIG_KLIPS_ALG ipsec_alg_sa_init(ipsp); #endif /* CONFIG_KLIPS_ALG */ break; case IPPROTO_IPIP: ipsp->ips_authalg = AH_NONE; ipsp->ips_encalg = ESP_NONE; break; #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ipsp->ips_authalg = AH_NONE; ipsp->ips_encalg = pfkey_sa->sadb_sa_encrypt; break; #endif /* CONFIG_KLIPS_IPCOMP */ case IPPROTO_INT: ipsp->ips_authalg = AH_NONE; ipsp->ips_encalg = ESP_NONE; break; case 0: break; default: KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_sa_process: " "unknown proto=%d.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return error; }