📄 ipsec_alg.c
字号:
GFP_ATOMIC)) == NULL) { ret=-ENOMEM; goto ixt_out; } /* zero-out key_e */ memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size); /* I cast here to allow more decoupling in alg module */ KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: about to call:" "set_key(key_e=%p, ekp=%p, key_size=%d)\n", (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); ret = ixt_e->ixt_e_set_key(ixt_e, (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8); } /* paranoid */ memset(ekp, 0, sa_p->ips_key_bits_e/8); kfree(ekp);ixt_out: return ret;}/*************************************************************** * * INTERFACE for AUTH services: key creation, hash functions * ***************************************************************//* * auth key context creation function * called from pfkey_v2_parser.c:pfkey_ips_init() */int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) { int ret=-EINVAL; struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; int keyminbits, keymaxbits; unsigned char *akp; unsigned int aks; KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "entering with authalg=%d ixt_a=%p\n", sa_p->ips_authalg, ixt_a); if (!ixt_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "NULL ipsec_alg_auth object\n"); return -EPROTO; } keyminbits=ixt_a->ixt_common.ixt_support.ias_keyminbits; keymaxbits=ixt_a->ixt_common.ixt_support.ias_keymaxbits; if(sa_p->ips_key_bits_a<keyminbits || sa_p->ips_key_bits_a>keymaxbits) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: incorrect auth" "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/, sa_p->ips_key_bits_a, keyminbits, keymaxbits); ret=-EINVAL; goto ixt_out; } /* save auth key pointer */ sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */ akp = sa_p->ips_key_a; aks = sa_p->ips_key_a_size; /* will hold: 2 ctx and a blocksize buffer: kb */ sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size; if((sa_p->ips_key_a = (caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) { ret=-ENOMEM; goto ixt_out; } ixt_a->ixt_a_hmac_set_key(ixt_a, sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */ ret=0; memset(akp, 0, aks); kfree(akp); ixt_out: return ret;}int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen){ struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth; if (!ixt_a) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_sa_esp_hash: " "NULL ipsec_alg_auth object\n"); return -EPROTO; } KLIPS_PRINT(debug_tunnel|debug_rcv, "klips_debug:ipsec_sa_esp_hash: " "hashing %p (%d bytes) to %p (%d bytes)\n", espp, len, hash, hashlen); ixt_a->ixt_a_hmac_hash(ixt_a, sa_p->ips_key_a, espp, len, hash, hashlen); return 0;}/*************************************************************** * * INTERFACE for module loading,testing, and unloading * ***************************************************************//* validation for registering (enc) module */static int check_enc(struct ipsec_alg_enc *ixt){ int ret=-EINVAL; if (ixt->ixt_common.ixt_blocksize==0) /* || ixt->ixt_common.ixt_blocksize%2) need for ESP_NULL */ barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize); if (ixt->ixt_common.ixt_support.ias_keyminbits==0 && ixt->ixt_common.ixt_support.ias_keymaxbits==0 && ixt->ixt_e_keylen==0) goto zero_key_ok; if (ixt->ixt_common.ixt_support.ias_keyminbits==0) barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); if (ixt->ixt_common.ixt_support.ias_keymaxbits==0) barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits); if (ixt->ixt_e_keylen==0) barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen); zero_key_ok: if (ixt->ixt_e_ctx_size==0 && ixt->ixt_e_new_key == NULL) barf_out(KERN_ERR "invalid key_e_size=%d and ixt_e_new_key=NULL\n", ixt->ixt_e_ctx_size); if (ixt->ixt_e_cbc_encrypt==NULL) barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n"); ret=0;out: return ret;}/* validation for registering (auth) module */static int check_auth(struct ipsec_alg_auth *ixt){ int ret=-EINVAL; if (ixt->ixt_common.ixt_support.ias_id==0 || ixt->ixt_common.ixt_support.ias_id > SADB_AALG_MAX) barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n", ixt->ixt_common.ixt_support.ias_id, SADB_AALG_MAX); if (ixt->ixt_common.ixt_blocksize==0 || ixt->ixt_common.ixt_blocksize%2) barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_common.ixt_blocksize); if (ixt->ixt_common.ixt_blocksize>AH_BLKLEN_MAX) barf_out(KERN_ERR "sorry blocksize=%d > %d. " "Please increase AH_BLKLEN_MAX and recompile\n", ixt->ixt_common.ixt_blocksize, AH_BLKLEN_MAX); if (ixt->ixt_common.ixt_support.ias_keyminbits==0 && ixt->ixt_common.ixt_support.ias_keymaxbits==0 && ixt->ixt_a_keylen==0) goto zero_key_ok; if (ixt->ixt_common.ixt_support.ias_keyminbits==0) barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_common.ixt_support.ias_keyminbits); if (ixt->ixt_common.ixt_support.ias_keymaxbits==0) barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_common.ixt_support.ias_keymaxbits); if (ixt->ixt_common.ixt_support.ias_keymaxbits!=ixt->ixt_common.ixt_support.ias_keyminbits) barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n"); if (ixt->ixt_a_keylen==0) barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen);zero_key_ok: if (ixt->ixt_a_ctx_size==0) barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size); if (ixt->ixt_a_hmac_set_key==NULL) barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n"); if (ixt->ixt_a_hmac_hash==NULL) barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n"); ret=0;out: return ret;}/* * Generic (enc, auth) registration entry point */int register_ipsec_alg(struct ipsec_alg *ixt){ int ret=-EINVAL; /* Validation */ if (ixt==NULL) barf_out("NULL ipsec_alg object passed\n"); if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00)) barf_out("incorrect version: %d.%d.%d-%d, " "must be %d.%d.%d[-%d]\n", IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION)); switch(ixt->ixt_alg_type) { case IPSEC_ALG_TYPE_AUTH: if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0)) goto out; break; case IPSEC_ALG_TYPE_ENCRYPT: if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0)) goto out; /* * Adapted two lines below: * ivlen == 0 is possible (NULL enc has blocksize==1) * * fixed NULL support by David De Reu <DeReu@tComLabs.com> */ if (ixt->ixt_support.ias_ivlen == 0 && ixt->ixt_blocksize > 1) { ixt->ixt_support.ias_ivlen = ixt->ixt_blocksize*8; } break; default: barf_out("alg_type=%d not supported\n", ixt->ixt_alg_type); } INIT_LIST_HEAD(&ixt->ixt_list); ret = ipsec_alg_insert(ixt); if (ret<0) barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed." "Not loaded (ret=%d).\n", ixt->ixt_support.ias_id, ret); ret = pfkey_list_insert_supported((struct ipsec_alg_supported *)&ixt->ixt_support , &(pfkey_supported_list[SADB_SATYPE_ESP])); if (ret==0) { ixt->ixt_state |= IPSEC_ALG_ST_SUPP; /* send register event to userspace */ pfkey_register_reply(SADB_SATYPE_ESP, NULL); } else printk(KERN_ERR "pfkey_list_insert_supported returned %d. " "Loading anyway.\n", ret); ret=0;out: return ret;}/* * unregister ipsec_alg object from own tables, if * success => calls pfkey_list_remove_supported() */int unregister_ipsec_alg(struct ipsec_alg *ixt) { int ret= -EINVAL; switch(ixt->ixt_alg_type) { case IPSEC_ALG_TYPE_AUTH: case IPSEC_ALG_TYPE_ENCRYPT: break; default: /* this is not a typo :) */ barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", ixt->ixt_name); } ret=ipsec_alg_delete(ixt); if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) { ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP; pfkey_list_remove_supported((struct ipsec_alg_supported *)&ixt->ixt_support , &(pfkey_supported_list[SADB_SATYPE_ESP])); /* send register event to userspace */ pfkey_register_reply(SADB_SATYPE_ESP, NULL); }out: return ret;}/* * Must be called from user context * used at module load type for testing algo implementation */static int ipsec_alg_test_encrypt(int enc_alg, int test) { int ret; caddr_t buf = NULL; int iv_size, keysize, key_e_size; struct ipsec_alg_enc *ixt_e; void *tmp_key_e = NULL; #define BUFSZ 1024 #define MARGIN 0 #define test_enc (buf+MARGIN) #define test_dec (test_enc+BUFSZ+MARGIN) #define test_tmp (test_dec+BUFSZ+MARGIN) #define test_key_e (test_tmp+BUFSZ+MARGIN) #define test_iv (test_key_e+key_e_size+MARGIN) #define test_key (test_iv+iv_size+MARGIN) #define test_size (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7) ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg); if (ixt_e==NULL) { KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_encrypt: " "encalg=%d object not found\n", enc_alg); ret=-EINVAL; goto out; } iv_size=ixt_e->ixt_common.ixt_support.ias_ivlen / 8; key_e_size=ixt_e->ixt_e_ctx_size; keysize=ixt_e->ixt_e_keylen; KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_encrypt: " "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n", enc_alg, iv_size, key_e_size, keysize); if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { ret= -ENOMEM; goto out; } get_random_bytes(test_key, keysize); get_random_bytes(test_iv, iv_size); if (ixt_e->ixt_e_new_key) { tmp_key_e = ixt_e->ixt_e_new_key(ixt_e, test_key, keysize); ret = tmp_key_e ? 0 : -EINVAL; } else { tmp_key_e = test_key_e; ret = ixt_e->ixt_e_set_key(ixt_e, test_key_e, test_key, keysize); } if (ret < 0) goto out; get_random_bytes(test_enc, BUFSZ); memcpy(test_tmp, test_enc, BUFSZ); ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_enc, BUFSZ, test_iv, 1); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "cbc_encrypt=1 ret=%d\n", ret); ret=memcmp(test_enc, test_tmp, BUFSZ); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "memcmp(enc, tmp) ret=%d: %s\n", ret, ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" ); memcpy(test_dec, test_enc, BUFSZ); ret=ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_dec, BUFSZ, test_iv, 0); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "cbc_encrypt=0 ret=%d\n", ret); ret=memcmp(test_dec, test_tmp, BUFSZ); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "memcmp(dec,tmp) ret=%d: %s\n", ret, ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" ); { /* Shamelessly taken from drivers/md sources O:) */ unsigned long now; int i, count, max=0; int encrypt, speed; for (encrypt=0; encrypt <2;encrypt ++) { for (i = 0; i < 5; i++) { now = jiffies; count = 0; while (jiffies == now) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -