/* * 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: %s() :" "entering for encalg=%d, authalg=%d\n", __FUNCTION__, 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: %s() :" "found ipsec_alg (ixt_e=%p) for encalg=%d\n", __FUNCTION__, 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: %s() :" "found ipsec_alg (ixt_a=%p) for auth=%d\n", __FUNCTION__, ixt_a, sa_p->ips_authalg); sa_p->ips_alg_auth=ixt_a; } return 0; }
/* * 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; 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: %s: " "encalg=%d object not found\n", __FUNCTION__, 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: %s : " "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n", __FUNCTION__, 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); ixt_a->ixt_a_hmac_set_key(test_key_a, test_key, keysize); get_random_bytes(test_auth, BUFSZ); ret=ixt_a->ixt_a_hmac_hash(test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN); printk(KERN_INFO "klips_info: %s: " "ret=%d\n", __FUNCTION__, 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(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: %s: " "%s hash speed=%d KB/s\n", __FUNCTION__, ixt_a->ixt_name, speed); } kfree(buf); ipsec_alg_put((struct ipsec_alg *)ixt_a); out: return ret; #undef test_auth #undef test_key_a #undef test_key #undef test_hash #undef test_size }
/* * 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 = 0; int keyminbits, keymaxbits; caddr_t akp = NULL; struct ipsec_alg_auth *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_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; } /* will hold: 2 ctx and a blocksize buffer: kb */ if ((akp = (caddr_t)kmalloc(ixt_a->ixt_a_ctx_size, GFP_ATOMIC)) == NULL) { ret = -ENOMEM; goto ixt_out; } KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: about to call:" "hmac_set_key(key_ctx=%p, key=%p, key_size=%d)\n", akp, (caddr_t)sa_p->ips_key_a, sa_p->ips_key_bits_a/8); if (ixt_a->ixt_a_hmac_set_key) { ret = ixt_a->ixt_a_hmac_set_key(ixt_a, akp, sa_p->ips_key_a, sa_p->ips_key_bits_a/8); /* XXX XXX */ if (ret < 0) { kfree(akp); goto ixt_out; } } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_auth_key_create: " "no hmac_set_key function available!\n"); ret = -EPROTO; goto ixt_out; } if (sa_p->ips_key_a) { memset(sa_p->ips_key_a, 0, sa_p->ips_key_bits_a/8); kfree(sa_p->ips_key_a); } sa_p->ips_key_a = akp; sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size; sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */ sa_p->ips_alg_auth = ixt_a; ixt_a = NULL; ixt_out: if (ixt_a) { ipsec_alg_put((struct ipsec_alg *)ixt_a); } 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; int iv_size, keysize, key_e_size; struct ipsec_alg_enc *ixt_e; #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: %s: " "encalg=%d object not found\n", __FUNCTION__, enc_alg); ret=-EINVAL; goto out; } iv_size=ixt_e->ixt_blocksize; key_e_size=ixt_e->ixt_e_ctx_size; keysize=ixt_e->ixt_e_keylen; KLIPS_PRINT(1, "klips_debug: %s: " "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n", __FUNCTION__, 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); ixt_e->ixt_e_set_key(test_key_e, test_key, keysize); get_random_bytes(test_enc, BUFSZ); memcpy(test_tmp, test_enc, BUFSZ); ret=ixt_e->ixt_e_cbc_encrypt(test_key_e, test_enc, test_enc, BUFSZ, test_iv, 1); printk(KERN_INFO "klips_info: %s: " "cbc_encrypt=1 ret=%d\n", __FUNCTION__, ret); ret=memcmp(test_enc, test_tmp, BUFSZ); printk(KERN_INFO "klips_info: %s: " "memcmp(enc, tmp) ret=%d: %s\n", ret, __FUNCTION__, ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" ); memcpy(test_dec, test_enc, BUFSZ); ret=ixt_e->ixt_e_cbc_encrypt(test_key_e, test_dec, test_dec, BUFSZ, test_iv, 0); printk(KERN_INFO "klips_info: %s : " "cbc_encrypt=0 ret=%d\n", __FUNCTION__, ret); ret=memcmp(test_dec, test_tmp, BUFSZ); printk(KERN_INFO "klips_info: %s : " "memcmp(dec,tmp) ret=%d: %s\n", __FUNCTION__, 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(test_key_e, test_tmp, test_tmp, BUFSZ, test_iv, encrypt); mb(); count++; mb(); } if (count > max) max = count; } speed = max * (HZ * BUFSZ / 1024); printk(KERN_INFO "klips_info: %s: " "%s %s speed=%d KB/s\n", __FUNCTION__, ixt_e->ixt_name, encrypt? "encrypt": "decrypt", speed); } } kfree(buf); ipsec_alg_put((struct ipsec_alg *)ixt_e); out: return ret; #undef test_enc #undef test_dec #undef test_tmp #undef test_key_e #undef test_iv #undef test_key #undef test_size }
/* * encryption key context creation function * called from pfkey_v2_parser.c:pfkey_ips_init() */ int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) { int ret = 0; int keyminbits, keymaxbits; caddr_t ekp = NULL; struct ipsec_alg_enc *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_enc_key_create: " "entering with encalg=%d ixt_e=%p\n", sa_p->ips_encalg, ixt_e); if (!ixt_e) { KLIPS_ERROR(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "NULL ipsec_alg_enc object\n"); return -EPROTO; } /* * grRRR... DES 7bits jurassic stuff ... f*ckk --jjo */ switch(ixt_e->ixt_common.ixt_support.ias_id) { case ESP_3DES: keyminbits=keymaxbits=192;break; case ESP_DES: keyminbits=keymaxbits=64;break; default: keyminbits=ixt_e->ixt_common.ixt_support.ias_keyminbits; keymaxbits=ixt_e->ixt_common.ixt_support.ias_keymaxbits; } if (sa_p->ips_key_bits_e<keyminbits || sa_p->ips_key_bits_e>keymaxbits) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "incorrect encryption key size for id=%d: %d bits -- " "must be between %d,%d bits\n" /*octets (bytes)\n"*/, ixt_e->ixt_common.ixt_support.ias_id, sa_p->ips_key_bits_e, keyminbits, keymaxbits); ret=-EINVAL; goto ixt_out; } if (ixt_e->ixt_e_new_key) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "using ixt_e_new_key to generate key\n"); if ((ekp = ixt_e->ixt_e_new_key(ixt_e, sa_p->ips_key_e, sa_p->ips_key_bits_e/8)) == NULL) { ret = -EINVAL; goto ixt_out; } } else if (ixt_e->ixt_e_set_key) { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "using ixt_e_set_key to generate key context\n"); if ((ekp = (caddr_t)kmalloc(ixt_e->ixt_e_ctx_size, GFP_ATOMIC)) == NULL) { ret = -ENOMEM; goto ixt_out; } /* zero-out key_e */ memset(ekp, 0, ixt_e->ixt_e_ctx_size); /* I cast here to allow more decoupling in alg module */ KLIPS_PRINT(debug_pfkey, "set_key(key_ctx=%p, key=%p, key_size=%d)\n", ekp, (caddr_t)sa_p->ips_key_e, sa_p->ips_key_bits_e/8); ret = ixt_e->ixt_e_set_key(ixt_e, ekp, (caddr_t)sa_p->ips_key_e, sa_p->ips_key_bits_e/8); if (ret < 0) { kfree(ekp); goto ixt_out; } } else { KLIPS_PRINT(debug_pfkey, "klips_debug:ipsec_alg_enc_key_create: " "no function available to generate a key!\n"); ret = -EPROTO; goto ixt_out; } if (sa_p->ips_key_e) { memset(sa_p->ips_key_e, 0, sa_p->ips_key_bits_e/8); kfree(sa_p->ips_key_e); } sa_p->ips_key_e = ekp; sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size; sa_p->ips_alg_enc = ixt_e; ixt_e = NULL; ixt_out: if (ixt_e) ipsec_alg_put((struct ipsec_alg *)ixt_e); return ret; }