📄 ipsec_alg.c
字号:
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_ivlen == 0 && ixt->ixt_blocksize > 1) ixt->ixt_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_alg_id, ret); ret = pfkey_list_insert_supported((struct 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 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_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) { mb(); ixt_e->ixt_e_cbc_encrypt(ixt_e, tmp_key_e, test_tmp, BUFSZ, test_iv, encrypt); mb(); count++; mb(); } if (count > max) max = count; } speed = max * (HZ * BUFSZ / 1024); printk(KERN_INFO "klips_info: ipsec_alg_test_encrypt: " "%s %s speed=%d KB/s\n", ixt_e->ixt_name, encrypt? "encrypt": "decrypt", speed); } }out: if (tmp_key_e && ixt_e->ixt_e_destroy_key) ixt_e->ixt_e_destroy_key(ixt_e, tmp_key_e); if (buf) kfree(buf); if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); return ret; #undef test_enc #undef test_dec #undef test_tmp #undef test_key_e #undef test_iv #undef test_key #undef test_size }/* * Must be called from user context * used at module load type for testing algo implementation */static int ipsec_alg_test_auth(int auth_alg, int test) { int ret; caddr_t buf = NULL; int blocksize, keysize, key_a_size; struct ipsec_alg_auth *ixt_a; #define BUFSZ 1024 #define MARGIN 0 #define test_auth (buf+MARGIN) #define test_key_a (test_auth+BUFSZ+MARGIN) #define test_key (test_key_a+key_a_size+MARGIN) #define test_hash (test_key+keysize+MARGIN) #define test_size (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4) ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg); if (ixt_a==NULL) { KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_auth: " "encalg=%d object not found\n", auth_alg); ret=-EINVAL; goto out; } blocksize=ixt_a->ixt_blocksize; key_a_size=ixt_a->ixt_a_ctx_size; keysize=ixt_a->ixt_a_keylen; KLIPS_PRINT(1, "klips_debug: ipsec_alg_test_auth: " "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n", auth_alg, blocksize, key_a_size, keysize); if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) { ret= -ENOMEM; goto out; } get_random_bytes(test_key, keysize); ret = ixt_a->ixt_a_hmac_set_key(ixt_a, test_key_a, test_key, keysize); if (ret < 0 ) goto out; get_random_bytes(test_auth, BUFSZ); ret=ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); printk(KERN_INFO "klips_info: ipsec_alg_test_auth: " "ret=%d\n", ret); { /* Shamelessly taken from drivers/md sources O:) */ unsigned long now; int i, count, max=0; int speed; for (i = 0; i < 5; i++) { now = jiffies; count = 0; while (jiffies == now) { mb(); ixt_a->ixt_a_hmac_hash(ixt_a, test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); mb(); count++; mb(); } if (count > max) max = count; } speed = max * (HZ * BUFSZ / 1024); printk(KERN_INFO "klips_info: ipsec_alg_test_auth: " "%s hash speed=%d KB/s\n", ixt_a->ixt_name, speed); }out: if (buf) kfree(buf); if (ixt_a) ipsec_alg_put((struct ipsec_alg *)ixt_a); return ret; #undef test_auth #undef test_key_a #undef test_key #undef test_hash #undef test_size }int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) { switch(alg_type) { case IPSEC_ALG_TYPE_ENCRYPT: return ipsec_alg_test_encrypt(alg_id, test); break; case IPSEC_ALG_TYPE_AUTH: return ipsec_alg_test_auth(alg_id, test); break; } printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: " "alg_type=%d alg_id=%d\n", alg_type, alg_id); return -EINVAL;}int ipsec_alg_init(void) { KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n", IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION), SADB_EALG_MAX, SADB_AALG_MAX); /* Initialize tables */ write_lock_bh(&ipsec_alg_lock); ipsec_alg_hash_init(); write_unlock_bh(&ipsec_alg_lock); /* Initialize static algos */ KLIPS_PRINT(1, "klips_info:ipsec_alg_init: " "calling ipsec_alg_static_init()\n"); /* If we are suppose to use our AES, and don't have CryptoAPI enabled... */#if defined(CONFIG_KLIPS_ENC_AES) && CONFIG_KLIPS_ENC_AES && !defined(CONFIG_KLIPS_ENC_AES_MODULE) && !CONFIG_KLIPS_ENC_CRYPTOAPI && !defined(CONFIG_KLIPS_ENC_CRYPTOAPI_MODULE) { extern int ipsec_aes_init(void); ipsec_aes_init(); }#endif /* If we are doing CryptoAPI, then init */#if defined(CONFIG_KLIPS_ENC_CRYPTOAPI) && CONFIG_KLIPS_ENC_CRYPTOAPI && !defined(CONFIG_KLIPS_ENC_CRYPTOAPI_MODULE) { extern int ipsec_cryptoapi_init(void); ipsec_cryptoapi_init(); }#endif return 0;}/********************************************** * * INTERFACE for ipsec_sa init and wipe * **********************************************//* * Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init() */int ipsec_alg_sa_init(struct ipsec_sa *sa_p) { struct ipsec_alg_enc *ixt_e; struct ipsec_alg_auth *ixt_a; /* Only ESP for now ... */ if (sa_p->ips_said.proto != IPPROTO_ESP) return -EPROTONOSUPPORT; KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :" "entering for encalg=%d, authalg=%d\n", sa_p->ips_encalg, sa_p->ips_authalg); if ((ixt_e=(struct ipsec_alg_enc *) ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) { KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :" "found ipsec_alg (ixt_e=%p) for encalg=%d\n", ixt_e, sa_p->ips_encalg); sa_p->ips_alg_enc=ixt_e; } if ((ixt_a=(struct ipsec_alg_auth *) ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) { KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_init() :" "found ipsec_alg (ixt_a=%p) for auth=%d\n", ixt_a, sa_p->ips_authalg); sa_p->ips_alg_auth=ixt_a; } return 0;}/* * Called from pluto -> ipsec_sa.c:ipsec_sa_delchain() */int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) { struct ipsec_alg *ixt; if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) { KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" "unlinking for encalg=%d\n", ixt->ixt_alg_id); ipsec_alg_put(ixt); } if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) { KLIPS_PRINT(debug_pfkey, "klips_debug: ipsec_alg_sa_wipe() :" "unlinking for authalg=%d\n", ixt->ixt_alg_id); ipsec_alg_put(ixt); } return 0;}IPSEC_PROCFS_DEBUG_NO_STATICintipsec_xform_get_info(char *buffer, char **start, off_t offset, int length IPSEC_PROC_LAST_ARG){ int len = 0; off_t begin = 0; int i; struct list_head *head; struct ipsec_alg *ixt; KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS, "klips_debug:ipsec_tncfg_get_info: " "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n", buffer, *start, (int)offset, length); for(i = 0, head = ipsec_alg_hash_table; i< IPSEC_ALG_HASHSZ; i++, head++) { struct list_head *p; for (p=head->next; p!=head; p=p->next) { ixt = list_entry(p, struct ipsec_alg, ixt_list); len += ipsec_snprintf(buffer+len, length-len, "VERSION=%d TYPE=%d ID=%d NAME=%s REFCNT=%d ", ixt->ixt_version, ixt->ixt_alg_type, ixt->ixt_alg_id, ixt->ixt_name, ixt->ixt_refcnt); len += ipsec_snprintf(buffer+len, length-len, "STATE=%08x BLOCKSIZE=%d IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", ixt->ixt_state, ixt->ixt_blocksize, ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); len += ipsec_snprintf(buffer+len, length-len, "IVLEN=%d KEYMINBITS=%d KEYMAXBITS=%d ", ixt->ixt_ivlen, ixt->ixt_keyminbits, ixt->ixt_keymaxbits); switch(ixt->ixt_alg_type) { case IPSEC_ALG_TYPE_AUTH: { struct ipsec_alg_auth *auth = (struct ipsec_alg_auth *)ixt; len += ipsec_snprintf(buffer+len, length-len, "KEYLEN=%d CTXSIZE=%d AUTHLEN=%d ", auth->ixt_a_keylen, auth->ixt_a_ctx_size, auth->ixt_a_authlen); break; } case IPSEC_ALG_TYPE_ENCRYPT: { struct ipsec_alg_enc *enc = (struct ipsec_alg_enc *)ixt; len += ipsec_snprintf(buffer+len, length-len, "KEYLEN=%d CTXSIZE=%d ", enc->ixt_e_keylen, enc->ixt_e_ctx_size); break; } } len += ipsec_snprintf(buffer+len, length-len, "\n"); } } *start = buffer + (offset - begin); /* Start of wanted data */ len -= (offset - begin); /* Start slop */ if (len > length) len = length; return len;}/* * As the author of this module, I ONLY ALLOW using it from * GPL (or same LICENSE TERMS as kernel source) modules. * * In respect to hardware crypto engines this means: * * Closed-source device drivers ARE NOT ALLOWED to use * this interface. * * Closed-source VHDL/Verilog firmware running on * the crypto hardware device IS ALLOWED to use this interface * via a GPL (or same LICENSE TERMS as kernel source) device driver. * --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording) *//* * These symbols can only be used from GPL modules * for now, I'm disabling this because it creates false * symbol problems for old modutils. */#ifndef NET_26#if 0#ifndef EXPORT_SYMBOL_GPL #undef EXPORT_SYMBOL_GPL#define EXPORT_SYMBOL_GPL EXPORT_SYMBOL#endif #endifEXPORT_SYMBOL(register_ipsec_alg);EXPORT_SYMBOL(unregister_ipsec_alg);EXPORT_SYMBOL(ipsec_alg_test);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -