/* * 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; }
static void * prism2_wep_init(int keyidx) { struct prism2_wep_data *priv; priv = kmalloc(sizeof(*priv), GFP_ATOMIC); if (priv == NULL) goto fail; memset(priv, 0, sizeof(*priv)); priv->key_idx = keyidx; priv->tfm = crypto_alloc_tfm("arc4", 0); if (priv->tfm == NULL) { printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " "crypto API arc4\n"); goto fail; } /* start WEP IV from a random value */ get_random_bytes(&priv->iv, 4); return priv; fail: if (priv) { if (priv->tfm) crypto_free_tfm(priv->tfm); kfree(priv); } return NULL; }
static void * prism2_wep_init(int keyidx) { struct prism2_wep_data *priv; priv = kmalloc(sizeof(*priv), GFP_ATOMIC); if (priv == NULL) goto fail; memset(priv, 0, sizeof(*priv)); priv->key_idx = keyidx; #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) priv->tfm = crypto_alloc_tfm("arc4", 0); if (priv->tfm == NULL) { printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " "crypto API arc4\n"); goto fail; } #else priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) { printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " "crypto API arc4\n"); priv->tx_tfm = NULL; goto fail; } priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) { printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " "crypto API arc4\n"); priv->rx_tfm = NULL; goto fail; } #endif /* start WEP IV from a random value */ get_random_bytes(&priv->iv, 4); return priv; fail: #if((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) if (priv) { if (priv->tfm) crypto_free_tfm(priv->tfm); kfree(priv); } #else if (priv) { if (priv->tx_tfm) crypto_free_blkcipher(priv->tx_tfm); if (priv->rx_tfm) crypto_free_blkcipher(priv->rx_tfm); kfree(priv); } #endif return NULL; }
static int cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) { int err = -EINVAL; char cms[LO_NAME_SIZE]; /* cipher-mode string */ char *cipher; char *mode; char *cmsp = cms; /* c-m string pointer */ struct crypto_tfm *tfm = NULL; /* encryption breaks for non sector aligned offsets */ if (info->lo_offset % LOOP_IV_SECTOR_SIZE) goto out; strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE); cms[LO_NAME_SIZE - 1] = 0; cipher = strsep(&cmsp, "-"); mode = strsep(&cmsp, "-"); if (mode == NULL || strcmp(mode, "cbc") == 0) tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC | CRYPTO_TFM_REQ_MAY_SLEEP); else if (strcmp(mode, "ecb") == 0) tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB | CRYPTO_TFM_REQ_MAY_SLEEP); if (tfm == NULL) return -EINVAL; err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key, info->lo_encrypt_key_size); if (err != 0) goto out_free_tfm; lo->key_data = tfm; return 0; out_free_tfm: crypto_free_tfm(tfm); out: return err; }
static int ipcomp6_init_state(struct xfrm_state *x, void *args) { int err; struct ipcomp_data *ipcd; struct xfrm_algo_desc *calg_desc; err = -EINVAL; if (!x->calg) goto out; err = -ENOMEM; ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL); if (!ipcd) goto error; memset(ipcd, 0, sizeof(*ipcd)); x->props.header_len = 0; if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); ipcd->scratch = kmalloc(IPCOMP_SCRATCH_SIZE, GFP_KERNEL); if (!ipcd->scratch) goto error; ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0); if (!ipcd->tfm) goto error; if (x->props.mode) { err = ipcomp6_tunnel_attach(x); if (err) goto error; } calg_desc = xfrm_calg_get_byname(x->calg->alg_name); BUG_ON(!calg_desc); ipcd->threshold = calg_desc->uinfo.comp.threshold; x->data = ipcd; err = 0; out: return err; error: if (ipcd) { ipcomp6_free_data(ipcd); kfree(ipcd); } goto out; }
int do_digest(char *code, char **result) { char *ret; int len = strlen(code); tfm = crypto_alloc_tfm("sha1", 0); if (IS_ERR(tfm)) return -1; sg_init_one(&sg, code, len); ret = (char *)kmalloc(50, GFP_KERNEL); if (!result) { crypto_free_tfm(tfm); return -1; } memset(ret, 0, 50); crypto_digest_final(tfm, result); crypto_free_tfm(tfm); *result = ret; return 0; }
static int digsig_sha1_init(SIGCTX * ctx) { if (ctx == NULL) return -1; if (sha1_tfm == NULL) sha1_tfm = crypto_alloc_tfm("sha1", 0); ctx->tfm = sha1_tfm; if (IS_ERR(ctx->tfm)) { DSM_ERROR("tfm allocation failed\n"); return -1; } crypto_digest_init(ctx->tfm); return 0; }
static inline const void * get_key(const void *p, const void *end, struct crypto_tfm **res) { struct xdr_netobj key; int alg, alg_mode; char *alg_name; p = simple_get_bytes(p, end, &alg, sizeof(alg)); if (IS_ERR(p)) goto out_err; p = simple_get_netobj(p, end, &key); if (IS_ERR(p)) goto out_err; switch (alg) { case ENCTYPE_DES_CBC_RAW: alg_name = "des"; alg_mode = CRYPTO_TFM_MODE_CBC; break; default: printk("gss_kerberos_mech: unsupported algorithm %d\n", alg); goto out_err_free_key; } if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) { printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name); goto out_err_free_key; } if (crypto_cipher_setkey(*res, key.data, key.len)) { printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name); goto out_err_free_tfm; } kfree(key.data); return p; out_err_free_tfm: crypto_free_tfm(*res); out_err_free_key: kfree(key.data); p = ERR_PTR(-EINVAL); out_err: return p; }
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; }
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; }
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 skcipher_crypt_blkcipher(struct skcipher_request *req, int (*crypt)(struct blkcipher_desc *, struct scatterlist *, struct scatterlist *, unsigned int)) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_blkcipher **ctx = crypto_skcipher_ctx(tfm); struct blkcipher_desc desc = { .tfm = *ctx, .info = req->iv, .flags = req->base.flags, }; return crypt(&desc, req->dst, req->src, req->cryptlen); } static int skcipher_encrypt_blkcipher(struct skcipher_request *req) { struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; return skcipher_crypt_blkcipher(req, alg->encrypt); } static int skcipher_decrypt_blkcipher(struct skcipher_request *req) { struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; return skcipher_crypt_blkcipher(req, alg->decrypt); } static void crypto_exit_skcipher_ops_blkcipher(struct crypto_tfm *tfm) { struct crypto_blkcipher **ctx = crypto_tfm_ctx(tfm); crypto_free_blkcipher(*ctx); } static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm) { struct crypto_alg *calg = tfm->__crt_alg; struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); struct crypto_blkcipher **ctx = crypto_tfm_ctx(tfm); struct crypto_blkcipher *blkcipher; struct crypto_tfm *btfm; if (!crypto_mod_get(calg)) return -EAGAIN; btfm = __crypto_alloc_tfm(calg, CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK); if (IS_ERR(btfm)) { crypto_mod_put(calg); return PTR_ERR(btfm); } blkcipher = __crypto_blkcipher_cast(btfm); *ctx = blkcipher; tfm->exit = crypto_exit_skcipher_ops_blkcipher; skcipher->setkey = skcipher_setkey_blkcipher; skcipher->encrypt = skcipher_encrypt_blkcipher; skcipher->decrypt = skcipher_decrypt_blkcipher; skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher); skcipher->keysize = calg->cra_blkcipher.max_keysize; return 0; } static int skcipher_setkey_ablkcipher(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen) { struct crypto_ablkcipher **ctx = crypto_skcipher_ctx(tfm); struct crypto_ablkcipher *ablkcipher = *ctx; int err; crypto_ablkcipher_clear_flags(ablkcipher, ~0); crypto_ablkcipher_set_flags(ablkcipher, crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); err = crypto_ablkcipher_setkey(ablkcipher, key, keylen); crypto_skcipher_set_flags(tfm, crypto_ablkcipher_get_flags(ablkcipher) & CRYPTO_TFM_RES_MASK); return err; } static int skcipher_crypt_ablkcipher(struct skcipher_request *req, int (*crypt)(struct ablkcipher_request *)) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_ablkcipher **ctx = crypto_skcipher_ctx(tfm); struct ablkcipher_request *subreq = skcipher_request_ctx(req); ablkcipher_request_set_tfm(subreq, *ctx); ablkcipher_request_set_callback(subreq, skcipher_request_flags(req), req->base.complete, req->base.data); ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, req->iv); return crypt(subreq); } static int skcipher_encrypt_ablkcipher(struct skcipher_request *req) { struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher; return skcipher_crypt_ablkcipher(req, alg->encrypt); } static int skcipher_decrypt_ablkcipher(struct skcipher_request *req) { struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher); struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher; return skcipher_crypt_ablkcipher(req, alg->decrypt); } static void crypto_exit_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) { struct crypto_ablkcipher **ctx = crypto_tfm_ctx(tfm); crypto_free_ablkcipher(*ctx); } static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) { struct crypto_alg *calg = tfm->__crt_alg; struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); struct crypto_ablkcipher **ctx = crypto_tfm_ctx(tfm); struct crypto_ablkcipher *ablkcipher; struct crypto_tfm *abtfm; if (!crypto_mod_get(calg)) return -EAGAIN; abtfm = __crypto_alloc_tfm(calg, 0, 0); if (IS_ERR(abtfm)) { crypto_mod_put(calg); return PTR_ERR(abtfm); } ablkcipher = __crypto_ablkcipher_cast(abtfm); *ctx = ablkcipher; tfm->exit = crypto_exit_skcipher_ops_ablkcipher; skcipher->setkey = skcipher_setkey_ablkcipher; skcipher->encrypt = skcipher_encrypt_ablkcipher; skcipher->decrypt = skcipher_decrypt_ablkcipher; skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher); skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) + sizeof(struct ablkcipher_request); skcipher->keysize = calg->cra_ablkcipher.max_keysize; return 0; } static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) { if (tfm->__crt_alg->cra_type == &crypto_blkcipher_type) return crypto_init_skcipher_ops_blkcipher(tfm); BUG_ON(tfm->__crt_alg->cra_type != &crypto_ablkcipher_type && tfm->__crt_alg->cra_type != &crypto_givcipher_type); return crypto_init_skcipher_ops_ablkcipher(tfm); } static const struct crypto_type crypto_skcipher_type2 = { .extsize = crypto_skcipher_extsize, .init_tfm = crypto_skcipher_init_tfm, .maskclear = ~CRYPTO_ALG_TYPE_MASK, .maskset = CRYPTO_ALG_TYPE_BLKCIPHER_MASK, .type = CRYPTO_ALG_TYPE_BLKCIPHER, .tfmsize = offsetof(struct crypto_skcipher, base), }; struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, u32 type, u32 mask) { return crypto_alloc_tfm(alg_name, &crypto_skcipher_type2, type, mask); } EXPORT_SYMBOL_GPL(crypto_alloc_skcipher); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Symmetric key cipher type");
struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type, u32 mask) { return crypto_alloc_tfm(alg_name, &crypto_akcipher_type, type, mask); }
struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask) { return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask); }
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 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; }
struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type, u32 mask) { return crypto_alloc_tfm(alg_name, &crypto_pcomp_type, type, mask); }
int plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len) { struct page *page = NULL; char *data = NULL; int offset = 0; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) struct crypto_hash *tfm = NULL; struct scatterlist sg = {0}; struct hash_desc desc = {0}; page = alloc_page(GFP_KERNEL); if (!page) { return -ENOMEM; } data = (char *)page_address(page); tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { __free_page(page); return -EINVAL; } desc.tfm = tfm; desc.flags = 0; crypto_hash_init(&desc); sg_init_one(&sg, (void *)data, PAGE_SIZE); for (offset = 0; offset < len; offset += PAGE_SIZE) { memset(data, 0x00, PAGE_SIZE); /* Check if the data is page size or part of page */ if ((len - offset) >= PAGE_SIZE) { memcpy(data, plaintext + offset, PAGE_SIZE); crypto_hash_update(&desc, &sg, PAGE_SIZE); } else { memcpy(data, plaintext + offset, (len - offset)); sg_init_one(&sg, (void *)data, (len - offset)); crypto_hash_update(&desc, &sg, (len - offset)); } } crypto_hash_final(&desc, hash); crypto_free_hash(tfm); #else struct crypto_tfm *tfm; struct scatterlist sg; page = alloc_page(GFP_KERNEL); if (!page) { return -ENOMEM; } data = (char *)page_address(page); tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP); if (tfm == NULL) { __free_page(page); return -EINVAL; } crypto_digest_init(tfm); sg_init_one(&sg, (u8 *)data, PAGE_SIZE); for (offset = 0; offset < len; offset += PAGE_SIZE) { memset(data, 0x00, PAGE_SIZE); if ((len - offset) >= PAGE_SIZE) { memcpy(data, plaintext + offset, PAGE_SIZE); crypto_digest_update(tfm, &sg, 1); } else { memcpy(data, plaintext + offset, (len - offset)); sg_init_one(&sg, (u8 *)data, (len - offset)); crypto_digest_update(tfm, &sg, 1); } } crypto_digest_final(tfm, hash); crypto_free_tfm(tfm); #endif __free_page(page); return 0; }