void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, u8 *out) { unsigned int i; struct scatterlist tmp; char *opad = tfm->crt_digest.dit_hmac_block; if (*keylen > crypto_tfm_alg_blocksize(tfm)) { hash_key(tfm, key, *keylen); *keylen = crypto_tfm_alg_digestsize(tfm); } crypto_digest_final(tfm, out); memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); memcpy(opad, key, *keylen); for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) opad[i] ^= 0x5c; tmp.page = virt_to_page(opad); tmp.offset = offset_in_page(opad); tmp.length = crypto_tfm_alg_blocksize(tfm); crypto_digest_init(tfm); crypto_digest_update(tfm, &tmp, 1); tmp.page = virt_to_page(out); tmp.offset = offset_in_page(out); tmp.length = crypto_tfm_alg_digestsize(tfm); crypto_digest_update(tfm, &tmp, 1); crypto_digest_final(tfm, out); }
/* * Allocate space for a (de)compressor. */ static void *mppe_alloc(unsigned char *options, int optlen) { struct ppp_mppe_state *state; unsigned int digestsize; if (optlen != CILEN_MPPE + sizeof(state->master_key) || options[0] != CI_MPPE || options[1] != CILEN_MPPE) goto out; state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); if (state == NULL) goto out; memset(state, 0, sizeof(*state)); state->arc4 = crypto_alloc_tfm("arc4", 0); if (!state->arc4) goto out_free; state->sha1 = crypto_alloc_tfm("sha1", 0); if (!state->sha1) goto out_free; digestsize = crypto_tfm_alg_digestsize(state->sha1); if (digestsize < MPPE_MAX_KEY_LEN) goto out_free; state->sha1_digest = kmalloc(digestsize, GFP_KERNEL); if (!state->sha1_digest) goto out_free; /* Save keys. */ memcpy(state->master_key, &options[CILEN_MPPE], sizeof(state->master_key)); memcpy(state->session_key, state->master_key, sizeof(state->master_key)); /* * We defer initial key generation until mppe_init(), as mppe_alloc() * is called frequently during negotiation. */ return (void *)state; out_free: if (state->sha1_digest) kfree(state->sha1_digest); if (state->sha1) crypto_free_tfm(state->sha1); if (state->arc4) crypto_free_tfm(state->arc4); kfree(state); out: return NULL; }
void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) { unsigned int i; struct scatterlist tmp; char *ipad = tfm->crt_digest.dit_hmac_block; if (*keylen > crypto_tfm_alg_blocksize(tfm)) { hash_key(tfm, key, *keylen); *keylen = crypto_tfm_alg_digestsize(tfm); } memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); memcpy(ipad, key, *keylen); for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) ipad[i] ^= 0x36; sg_set_buf(&tmp, ipad, crypto_tfm_alg_blocksize(tfm)); crypto_digest_init(tfm); crypto_digest_update(tfm, &tmp, 1); }
static int ah6_init_state(struct xfrm_state *x, void *args) { struct ah_data *ahp = NULL; struct xfrm_algo_desc *aalg_desc; if (!x->aalg) goto error; /* null auth can use a zero length key */ if (x->aalg->alg_key_len > 512) goto error; if (x->encap) goto error; ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); if (ahp == NULL) return -ENOMEM; memset(ahp, 0, sizeof(*ahp)); ahp->key = x->aalg->alg_key; ahp->key_len = (x->aalg->alg_key_len+7)/8; ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); if (!ahp->tfm) goto error; ahp->icv = ah_hmac_digest; /* * Lookup the algorithm description maintained by xfrm_algo, * verify crypto transform properties, and store information * we need for AH processing. This lookup cannot fail here * after a successful crypto_alloc_tfm(). */ aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != crypto_tfm_alg_digestsize(ahp->tfm)) { printk(KERN_INFO "AH: %s digestsize %u != %hu\n", x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN); ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL); if (!ahp->work_icv) goto error; x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len); if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); x->data = ahp; return 0; error: if (ahp) { if (ahp->work_icv) kfree(ahp->work_icv); if (ahp->tfm) crypto_free_tfm(ahp->tfm); kfree(ahp); } return -EINVAL; }
int esp_init_state(struct xfrm_state *x, void *args) { struct esp_data *esp = NULL; /* null auth and encryption can have zero length keys */ if (x->aalg) { if (x->aalg->alg_key_len > 512) goto error; } if (x->ealg == NULL) goto error; esp = kmalloc(sizeof(*esp), GFP_KERNEL); if (esp == NULL) return -ENOMEM; memset(esp, 0, sizeof(*esp)); if (x->aalg) { struct xfrm_algo_desc *aalg_desc; esp->auth.key = x->aalg->alg_key; esp->auth.key_len = (x->aalg->alg_key_len+7)/8; esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); if (esp->auth.tfm == NULL) goto error; esp->auth.icv = esp_hmac_digest; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != crypto_tfm_alg_digestsize(esp->auth.tfm)) { printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, crypto_tfm_alg_digestsize(esp->auth.tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); if (!esp->auth.work_icv) goto error; } esp->conf.key = x->ealg->alg_key; esp->conf.key_len = (x->ealg->alg_key_len+7)/8; if (x->props.ealgo == SADB_EALG_NULL) esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); else esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); if (esp->conf.tfm == NULL) goto error; esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); esp->conf.padlen = 0; if (esp->conf.ivlen) { esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); get_random_bytes(esp->conf.ivec, esp->conf.ivlen); } crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len); x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; if (x->props.mode) x->props.header_len += sizeof(struct iphdr); if (x->encap) { struct xfrm_encap_tmpl *encap = x->encap; if (encap->encap_type) { switch (encap->encap_type) { case UDP_ENCAP_ESPINUDP: x->props.header_len += sizeof(struct udphdr); break; default: printk (KERN_INFO "esp_init_state(): Unhandled encap type: %u\n", encap->encap_type); break; } } } x->data = esp; x->props.trailer_len = esp4_get_max_size(x, 0) - x->props.header_len; return 0; error: if (esp) { if (esp->auth.tfm) crypto_free_tfm(esp->auth.tfm); if (esp->auth.work_icv) kfree(esp->auth.work_icv); if (esp->conf.tfm) crypto_free_tfm(esp->conf.tfm); kfree(esp); } return -EINVAL; }
static int esp6_init_state(struct xfrm_state *x) { struct esp_data *esp = NULL; /* null auth and encryption can have zero length keys */ if (x->aalg) { if (x->aalg->alg_key_len > 512) goto error; } if (x->ealg == NULL || (x->ealg->alg_key_len == 0 && x->props.ealgo != SADB_EALG_NULL)) goto error; if (x->encap) goto error; esp = kmalloc(sizeof(*esp), GFP_KERNEL); if (esp == NULL) return -ENOMEM; memset(esp, 0, sizeof(*esp)); if (x->aalg) { struct xfrm_algo_desc *aalg_desc; unsigned int digestsize; u32 mode = 0; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); #ifdef CONFIG_CRYPTO_XCBC mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ? CRYPTO_TFM_MODE_CBC : 0; #endif esp->auth.key = x->aalg->alg_key; esp->auth.key_len = (x->aalg->alg_key_len+7)/8; esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, mode); if (esp->auth.tfm == NULL) goto error; #ifdef CONFIG_CRYPTO_XCBC esp->auth.icv = !mode ? esp_hmac_digest : esp_xcbc_digest; #else esp->auth.icv = esp_hmac_digest; #endif digestsize = !mode ? crypto_tfm_alg_digestsize(esp->auth.tfm) : crypto_tfm_alg_blocksize(esp->auth.tfm); if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) { printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, digestsize, aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); if (!esp->auth.work_icv) goto error; } esp->conf.key = x->ealg->alg_key; if (x->props.ealgo == SADB_EALG_NULL) { esp->conf.key_len = 0; esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); } else { esp->conf.key_len = (x->ealg->alg_key_len+7)/8; esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); } if (esp->conf.tfm == NULL) goto error; esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); esp->conf.padlen = 0; if (esp->conf.ivlen) { esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); if (unlikely(esp->conf.ivec == NULL)) goto error; get_random_bytes(esp->conf.ivec, esp->conf.ivlen); } if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) goto error; x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); x->data = esp; return 0; error: x->data = esp; esp6_destroy(x); x->data = NULL; return -EINVAL; }
static int ah_init_state(struct xfrm_state *x) { struct ah_data *ahp = NULL; struct xfrm_algo_desc *aalg_desc; unsigned int digestsize; u32 mode = 0; if (!x->aalg) goto error; /* null auth can use a zero length key */ if (x->aalg->alg_key_len > 512) goto error; if (x->encap) goto error; ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); if (ahp == NULL) return -ENOMEM; memset(ahp, 0, sizeof(*ahp)); aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); #ifdef CONFIG_CRYPTO_XCBC mode = aalg_desc->desc.sadb_alg_id == SADB_X_AALG_AES_XCBC_MAC ? CRYPTO_TFM_MODE_CBC : 0; #endif ahp->key = x->aalg->alg_key; ahp->key_len = (x->aalg->alg_key_len+7)/8; ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, mode); if (!ahp->tfm) goto error; #ifdef CONFIG_CRYPTO_XCBC ahp->icv = !mode ? ah_hmac_digest : ah_xcbc_digest; #else ahp->icv = ah_hmac_digest; #endif digestsize = !mode ? crypto_tfm_alg_digestsize(ahp->tfm) : crypto_tfm_alg_blocksize(ahp->tfm); /* * Lookup the algorithm description maintained by xfrm_algo, * verify crypto transform properties, and store information * we need for AH processing. This lookup cannot fail here * after a successful crypto_alloc_tfm(). */ if (aalg_desc->uinfo.auth.icv_fullbits/8 != digestsize) { printk(KERN_INFO "AH: %s digestsize %u != %hu\n", x->aalg->alg_name, digestsize, aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN); ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL); if (!ahp->work_icv) goto error; x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len); if (x->props.mode) x->props.header_len += sizeof(struct iphdr); x->data = ahp; return 0; error: if (ahp) { kfree(ahp->work_icv); crypto_free_tfm(ahp->tfm); kfree(ahp); } return -EINVAL; }
static int esp6_init_state(struct xfrm_state *x) { struct esp_data *esp = NULL; /* null auth and encryption can have zero length keys */ if (x->aalg) { if (x->aalg->alg_key_len > 512) goto error; } if (x->ealg == NULL) goto error; if (x->encap) goto error; esp = kmalloc(sizeof(*esp), GFP_KERNEL); if (esp == NULL) return -ENOMEM; memset(esp, 0, sizeof(*esp)); if (x->aalg) { struct xfrm_algo_desc *aalg_desc; esp->auth.key = x->aalg->alg_key; esp->auth.key_len = (x->aalg->alg_key_len+7)/8; esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); if (esp->auth.tfm == NULL) goto error; esp->auth.icv = esp_hmac_digest; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != crypto_tfm_alg_digestsize(esp->auth.tfm)) { printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, crypto_tfm_alg_digestsize(esp->auth.tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); if (!esp->auth.work_icv) goto error; } esp->conf.key = x->ealg->alg_key; esp->conf.key_len = (x->ealg->alg_key_len+7)/8; if (x->props.ealgo == SADB_EALG_NULL) esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); else esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); if (esp->conf.tfm == NULL) goto error; esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); esp->conf.padlen = 0; if (esp->conf.ivlen) { esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); if (unlikely(esp->conf.ivec == NULL)) goto error; get_random_bytes(esp->conf.ivec, esp->conf.ivlen); } if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) goto error; x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); x->data = esp; #if defined (CONFIG_OCTEON_NATIVE_IPSEC) esp->oct_data = cavium_alloc_n_fill(x); #endif return 0; error: x->data = esp; esp6_destroy(x); x->data = NULL; return -EINVAL; }
int esp6_init_state(struct xfrm_state *x, void *args) { struct esp_data *esp = NULL; if (x->aalg) { if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512) goto error; } if (x->ealg == NULL) goto error; esp = kmalloc(sizeof(*esp), GFP_KERNEL); if (esp == NULL) return -ENOMEM; memset(esp, 0, sizeof(*esp)); if (x->aalg) { struct xfrm_algo_desc *aalg_desc; esp->auth.key = x->aalg->alg_key; esp->auth.key_len = (x->aalg->alg_key_len+7)/8; esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); if (esp->auth.tfm == NULL) goto error; esp->auth.icv = esp_hmac_digest; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != crypto_tfm_alg_digestsize(esp->auth.tfm)) { printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, crypto_tfm_alg_digestsize(esp->auth.tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); if (!esp->auth.work_icv) goto error; } esp->conf.key = x->ealg->alg_key; esp->conf.key_len = (x->ealg->alg_key_len+7)/8; if (x->props.ealgo == SADB_EALG_NULL) esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); else esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); if (esp->conf.tfm == NULL) goto error; esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); esp->conf.padlen = 0; if (esp->conf.ivlen) { esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); get_random_bytes(esp->conf.ivec, esp->conf.ivlen); } crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len); x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); x->data = esp; return 0; error: if (esp) { if (esp->auth.tfm) crypto_free_tfm(esp->auth.tfm); if (esp->auth.work_icv) kfree(esp->auth.work_icv); if (esp->conf.tfm) crypto_free_tfm(esp->conf.tfm); kfree(esp); } return -EINVAL; }