// given a string, generate a 32-bit key int generate_key(char *pwd, u8 *pkey) { int len_pwd = strlen(pwd); struct scatterlist sg; struct crypto_hash *tfm; struct hash_desc desc; int i; unsigned char output[SHA1_LENGTH]; // key generated char *buf = kmalloc(MAX_PWD, GFP_KERNEL); // password buffer memset(buf, 0, MAX_PWD); strncpy(buf, pwd, len_pwd); tfm = crypto_alloc_hash("sha1", 1, CRYPTO_ALG_ASYNC); desc.tfm = tfm; desc.flags = 0; sg_init_one(&sg, buf, len_pwd); crypto_hash_init(&desc); crypto_hash_update(&desc, &sg, len_pwd); crypto_hash_final(&desc, output); for(i=0; i<16; i++) pkey[i] = output[i]; for(i=0; i<16; i++) pkey[i+16] = output[i]; crypto_free_hash(tfm); kfree(buf); return 0; }
static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc) { struct pohmelfs_crypto_engine *e = &tc->eng; struct hash_desc *desc = e->data; unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd); int err; desc->tfm = e->hash; desc->flags = 0; err = crypto_hash_init(desc); if (err) return err; err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator); if (err) return err; err = crypto_hash_final(desc, dst); if (err) return err; { unsigned int i; dprintk("%s: ", __func__); for (i = 0; i < tc->psb->crypto_attached_size; ++i) dprintka("%02x ", dst[i]); dprintka("\n"); } return 0; }
TEE_Result tee_hash_createdigest(uint32_t algo, const uint8_t *data, size_t datalen, uint8_t *digest, size_t digestlen) { TEE_Result res; void *ctx = NULL; res = crypto_hash_alloc_ctx(&ctx, algo); if (res) return res; res = crypto_hash_init(ctx, algo); if (res) goto out; if (datalen != 0) { res = crypto_hash_update(ctx, algo, data, datalen); if (res) goto out; } res = crypto_hash_final(ctx, algo, digest, digestlen); out: crypto_hash_free_ctx(ctx, algo); return res; }
static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, const struct in6_addr *daddr, struct in6_addr *saddr, const struct tcphdr *th) { struct tcp_md5sig_pool *hp; struct hash_desc *desc; hp = tcp_get_md5sig_pool(); if (!hp) goto clear_hash_noput; desc = &hp->md5_desc; if (crypto_hash_init(desc)) goto clear_hash; if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2)) goto clear_hash; if (tcp_md5_hash_header(hp, th)) goto clear_hash; if (tcp_md5_hash_key(hp, key)) goto clear_hash; if (crypto_hash_final(desc, md5_hash)) goto clear_hash; tcp_put_md5sig_pool(); return 0; clear_hash: tcp_put_md5sig_pool(); clear_hash_noput: memset(md5_hash, 0, 16); return 1; }
static int finalize_hash (struct hash_desc *desc, unsigned char * out, unsigned int out_size) { int ret = -1; if (!desc || !desc->tfm || !out || !out_size) { printk(KERN_ERR "FIPS(%s): Invalid args", __FUNCTION__); return ret; } if (crypto_hash_digestsize(desc->tfm) > out_size) { printk(KERN_ERR "FIPS(%s): Not enough space for digest", __FUNCTION__); return ret; } ret = crypto_hash_final (desc, out); if (ret) { printk(KERN_ERR "FIPS(%s): crypto_hash_final failed", __FUNCTION__); return -1; } return 0; }
int hash_lbr(uint8_t hash[DIGEST_LENGTH],struct lbr_t *lbr) { struct scatterlist sg; int i, j; /* No error checking here. If anything fails, we better go straight home anyway. */ crypto_hash_init(&armor_desc); armor_desc.flags = 0; /* Loop over all LBR entries. */ for (i = 0; i < LBR_ENTRIES; i++) { sg_set_buf(&sg, &lbr->from[(lbr->tos - i) % LBR_ENTRIES], sizeof(uint64_t)); crypto_hash_update(&armor_desc, &sg, sizeof(uint64_t)); sg_set_buf(&sg, &lbr->to [(lbr->tos - i) % LBR_ENTRIES], sizeof(uint64_t)); crypto_hash_update(&armor_desc, &sg, sizeof(uint64_t)); printdj(false, "lbr[%2d], <from: 0x%012llx, to: 0x%012llx>\n", i, lbr->from[(lbr->tos+LBR_ENTRIES-i) % LBR_ENTRIES], lbr-> to[(lbr->tos+LBR_ENTRIES-i) % LBR_ENTRIES]); } ARMOR_STAT_INC(digests); crypto_hash_final(&armor_desc, hash); printdj(false, "hash: "); for (j = 0; j < DIGEST_LENGTH; j++) printdj(false,"%02x", hash[j]); printdj(false,"\n"); return 0; }
void sha1_final(void *c, void *out) { struct hash_desc *d = c; if (crypto_hash_final(d, out)) printk(KERN_INFO "crypto_hash_final()\n"); }
/* checksum the plaintext data and hdrlen bytes of the token header */ s32 make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body, int body_offset, struct xdr_netobj *cksum) { struct hash_desc desc; /* XXX add to ctx? */ struct scatterlist sg[1]; int err; desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(desc.tfm)) return GSS_S_FAILURE; cksum->len = crypto_hash_digestsize(desc.tfm); desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_hash_init(&desc); if (err) goto out; sg_set_buf(sg, header, hdrlen); err = crypto_hash_update(&desc, sg, hdrlen); if (err) goto out; err = xdr_process_buf(body, body_offset, body->len - body_offset, checksummer, &desc); if (err) goto out; err = crypto_hash_final(&desc, cksum->data); out: crypto_free_hash(desc.tfm); return err ? GSS_S_FAILURE : 0; }
/* If hash_len pointer is NULL - destroy descriptor. */ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, unsigned char *hash, unsigned int *hash_len) { int err; int size = crypto_hash_digestsize(((struct hash_desc *)hdesc)->tfm); if (hash_len == NULL) { crypto_free_hash(((struct hash_desc *)hdesc)->tfm); kfree(hdesc); return 0; } if (hash == NULL || *hash_len < size) { *hash_len = size; return -ENOSPC; } err = crypto_hash_final((struct hash_desc *) hdesc, hash); if (err < 0) { /* May be caller can fix error */ return err; } crypto_free_hash(((struct hash_desc *)hdesc)->tfm); kfree(hdesc); return err; }
static int __init sha1_init(void) { struct scatterlist sg; struct crypto_hash *tfm; struct hash_desc desc; unsigned char output[SHA1_LENGTH]; unsigned char buf[10]; int i; printk(KERN_INFO "sha1: %s\n", __FUNCTION__); memset(buf, 'A', 10); memset(output, 0x00, SHA1_LENGTH); tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); desc.tfm = tfm; desc.flags = 0; sg_init_one(&sg, buf, 10); crypto_hash_init(&desc); crypto_hash_update(&desc, &sg, 10); crypto_hash_final(&desc, output); for (i = 0; i < 20; i++) { printk(KERN_ERR "%d-%d\n", output[i], i); } crypto_free_hash(tfm); return 0; }
unsigned char * key_to_hash(unsigned char *key) { struct scatterlist sg; struct crypto_hash *tfm; struct hash_desc desc; unsigned char *digest= NULL; digest=kmalloc(16,GFP_KERNEL); if(IS_ERR(digest)){ printk("Error in allocating memory to Hash Key\n "); return NULL; } tfm = crypto_alloc_hash("md5", 0, 0); desc.tfm = tfm; desc.flags = 0; sg_init_one(&sg, key, 16); crypto_hash_init(&desc); crypto_hash_update(&desc, &sg, 16); crypto_hash_final(&desc, digest); crypto_free_hash(tfm); if(!digest){ printk("Error in hashing userland key\n"); return NULL; } return digest; }
TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *other_info, size_t other_info_len, uint8_t *derived_key, size_t derived_key_len) { TEE_Result res; size_t hash_len, i, n, sz; void *ctx = NULL; uint8_t tmp[TEE_MAX_HASH_SIZE]; uint32_t be_count; uint8_t *out = derived_key; uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); res = crypto_hash_alloc_ctx(&ctx, hash_algo); if (res != TEE_SUCCESS) return res; res = tee_hash_get_digest_size(hash_algo, &hash_len); if (res != TEE_SUCCESS) goto out; n = derived_key_len / hash_len; sz = hash_len; for (i = 1; i <= n + 1; i++) { be_count = TEE_U32_TO_BIG_ENDIAN(i); res = crypto_hash_init(ctx, hash_algo); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, hash_algo, (uint8_t *)&be_count, sizeof(be_count)); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, hash_algo, shared_secret, shared_secret_len); if (res != TEE_SUCCESS) goto out; if (other_info && other_info_len) { res = crypto_hash_update(ctx, hash_algo, other_info, other_info_len); if (res != TEE_SUCCESS) goto out; } res = crypto_hash_final(ctx, hash_algo, tmp, sizeof(tmp)); if (res != TEE_SUCCESS) goto out; if (i == n + 1) sz = derived_key_len % hash_len; memcpy(out, tmp, sz); out += sz; } res = TEE_SUCCESS; out: crypto_hash_free_ctx(ctx, hash_algo); return res; }
static void padlock_sha_final(struct crypto_tfm *tfm, uint8_t *out) { if (unlikely(ctx(tfm)->bypass)) { crypto_hash_final(&ctx(tfm)->fallback, out); ctx(tfm)->bypass = 0; return; } /* Pass the input buffer to PadLock microcode... */ ctx(tfm)->f_sha_padlock(ctx(tfm)->data, out, ctx(tfm)->used); ctx(tfm)->used = 0; }
static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, const struct sock *sk, const struct request_sock *req, const struct sk_buff *skb) { const struct in6_addr *saddr, *daddr; struct tcp_md5sig_pool *hp; struct hash_desc *desc; const struct tcphdr *th = tcp_hdr(skb); if (sk) { saddr = &inet6_sk(sk)->saddr; daddr = &inet6_sk(sk)->daddr; } else if (req) { saddr = &inet6_rsk(req)->loc_addr; daddr = &inet6_rsk(req)->rmt_addr; } else { const struct ipv6hdr *ip6h = ipv6_hdr(skb); saddr = &ip6h->saddr; daddr = &ip6h->daddr; } hp = tcp_get_md5sig_pool(); if (!hp) goto clear_hash_noput; desc = &hp->md5_desc; if (crypto_hash_init(desc)) goto clear_hash; if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len)) goto clear_hash; if (tcp_md5_hash_header(hp, th)) goto clear_hash; if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2)) goto clear_hash; if (tcp_md5_hash_key(hp, key)) goto clear_hash; if (crypto_hash_final(desc, md5_hash)) goto clear_hash; tcp_put_md5sig_pool(); return 0; clear_hash: tcp_put_md5sig_pool(); clear_hash_noput: memset(md5_hash, 0, 16); return 1; }
int wrapfs_compute_checksum(struct file* filp, char* buffer, char *checksum_algorithm) { struct scatterlist sg[1]; struct hash_desc desc; mm_segment_t oldfs; int bytes, rc =0; // int diglength = 16; int length = PAGE_SIZE; unsigned char buf[DIGESTLEN+1]; char *read_in_buffer = NULL; memset(buf,0,DIGESTLEN+1); read_in_buffer = kmalloc(length, GFP_KERNEL); if(read_in_buffer == NULL) { kfree(read_in_buffer); printk("Error in allocating memonry in checksum block.\n"); return -ENOMEM; } filp->f_pos = 0; oldfs = get_fs(); set_fs(KERNEL_DS); rc = crypt_init_desc(&desc,checksum_algorithm); do { bytes = filp->f_op->read(filp, read_in_buffer, length, &filp->f_pos); sg_init_one(sg,read_in_buffer,bytes); rc = crypto_hash_update(&desc,sg,bytes); } while(bytes); if(!rc) { rc = crypto_hash_final(&desc, buf);//calculate final digest and populate value in buf #if 0 printk("\n printing checksum in compute checksum \n"); for(i =0;i<16;i++){ printk("%02x",buf[i]& 0XFF); // buffer[i] = buf[i]; } #endif } rc = str_to_hex_str(buf, buffer, DIGESTLEN*2 +1, DIGESTLEN); crypto_free_hash(desc.tfm); set_fs(oldfs); kfree(read_in_buffer); return rc; }
int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum) { char *p; struct crypto_hash *tfm; struct hash_desc desc; struct scatterlist sg; unsigned char temp_sum[GR_SHA_LEN]; volatile int retval = 0; volatile int dummy = 0; unsigned int i; sg_init_table(&sg, 1); tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { /* should never happen, since sha256 should be built in */ return 1; } desc.tfm = tfm; desc.flags = 0; crypto_hash_init(&desc); p = salt; sg_set_buf(&sg, p, GR_SALT_LEN); crypto_hash_update(&desc, &sg, sg.length); p = entry->pw; sg_set_buf(&sg, p, strlen(p)); crypto_hash_update(&desc, &sg, sg.length); crypto_hash_final(&desc, temp_sum); memset(entry->pw, 0, GR_PW_LEN); for (i = 0; i < GR_SHA_LEN; i++) if (sum[i] != temp_sum[i]) retval = 1; else dummy = 1; // waste a cycle crypto_free_hash(tfm); return retval; }
/* * Calculates block's hash value, to avoid all block compare. * hash_out must be allocated outside. */ int calc_hash(char* data, size_t size, u8* hash_out) { struct hash_desc sha256_desc; struct scatterlist sg; sha256_desc.tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); sg_init_one(&sg, data, size); crypto_hash_init(&sha256_desc); crypto_hash_update(&sha256_desc, &sg, size); crypto_hash_final(&sha256_desc, hash_out); crypto_free_hash(sha256_desc.tfm); return 0; }
static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu, u8 *crc) { struct scatterlist sg[2]; unsigned int nbytes = sizeof(struct iscsi_hdr); sg_init_table(sg, pdu->ahssize ? 2 : 1); sg_set_buf(&sg[0], &pdu->bhs, nbytes); if (pdu->ahssize) { sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize); nbytes += pdu->ahssize; } crypto_hash_init(hash); crypto_hash_update(hash, sg, nbytes); crypto_hash_final(hash, crc); }
/* get_key_hash * * @enc_key: key of which the md5 hash has to be generated * * Returns the md5 hash of the key. Responsibility of freeing the hashed key lies with the caller who requested the hashed key. */ unsigned char *get_key_hash(unsigned char *enc_key) { /* imp, plaintext should be array else getting sefault so copy key in array here */ struct scatterlist sg; struct hash_desc desc; int i, err; unsigned char *hashed_key; unsigned char plaintext[AES_KEY_SIZE]; for (i = 0; i < AES_KEY_SIZE; i++) plaintext[i] = enc_key[i]; hashed_key = kmalloc(sizeof(char)*AES_KEY_SIZE, GFP_KERNEL); desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(desc.tfm)) { err = PTR_ERR(desc.tfm); printk(KERN_ALERT"error in allocating hash"); goto ERR; } desc.flags = 0; sg_init_one(&sg, plaintext, AES_KEY_SIZE); err = crypto_hash_init(&desc); if (err) { printk(KERN_ALERT"error in initializing crypto hash\n"); goto ERR; } err = crypto_hash_update(&desc, &sg, AES_KEY_SIZE); if (err) { printk(KERN_ALERT"error in updating crypto hash\n"); goto ERR; } printk(KERN_ALERT"cry[to hash updated\n"); err = crypto_hash_final(&desc, hashed_key); if (err) { printk(KERN_ALERT"error in finalizing crypto hash\n"); goto ERR; } crypto_free_hash(desc.tfm); return hashed_key; ERR: if (desc.tfm) crypto_free_hash(desc.tfm); return ERR_PTR(err); }
/* * Calculate the MD5/SHA1 file digest */ int ima_calc_hash(struct file *file, char *digest) { struct hash_desc desc; struct scatterlist sg[1]; loff_t i_size, offset = 0; char *rbuf; int rc; rc = init_desc(&desc); if (rc != 0) return rc; rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!rbuf) { rc = -ENOMEM; goto out; } i_size = i_size_read(file->f_dentry->d_inode); while (offset < i_size) { int rbuf_len; rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); if (rbuf_len < 0) { rc = rbuf_len; break; } if (rbuf_len == 0) break; offset += rbuf_len; sg_init_one(sg, rbuf, rbuf_len); rc = crypto_hash_update(&desc, sg, rbuf_len); if (rc) break; } kfree(rbuf); if (!rc) rc = crypto_hash_final(&desc, digest); out: crypto_free_hash(desc.tfm); return rc; }
static TEE_Result check_digest(struct ree_fs_ta_handle *h) { void *digest = NULL; TEE_Result res; digest = malloc(h->shdr->hash_size); if (!digest) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_hash_final(h->hash_ctx, h->hash_algo, digest, h->shdr->hash_size); if (res != TEE_SUCCESS) { res = TEE_ERROR_SECURITY; goto out; } if (memcmp(digest, SHDR_GET_HASH(h->shdr), h->shdr->hash_size)) res = TEE_ERROR_SECURITY; out: free(digest); return res; }
int calculate_key(char *key,char *chksum,int len) { int rc =0; struct scatterlist sg; struct hash_desc desc; desc.flags = 0; desc.tfm = crypto_alloc_hash("md5",0,CRYPTO_ALG_ASYNC); if(IS_ERR(desc.tfm)) { rc = PTR_ERR(desc.tfm); goto out; } if(crypto_hash_init(&desc)) goto out; sg_init_one(&sg,(u8*)key,len); crypto_hash_update(&desc,&sg,len); crypto_hash_final(&desc,chksum); out: return rc; }
static void digest_data(struct hash_desc *hash, struct iscsi_cmnd *cmnd, struct tio *tio, u32 offset, u8 *crc) { struct scatterlist *sg = cmnd->conn->hash_sg; u32 size, length; int i, idx, count; unsigned int nbytes; size = cmnd->pdu.datasize; nbytes = size = (size + 3) & ~3; offset += tio->offset; idx = offset >> PAGE_CACHE_SHIFT; offset &= ~PAGE_CACHE_MASK; count = get_pgcnt(size, offset); assert(idx + count <= tio->pg_cnt); assert(count <= ISCSI_CONN_IOV_MAX); sg_init_table(sg, ARRAY_SIZE(cmnd->conn->hash_sg)); crypto_hash_init(hash); for (i = 0; size; i++) { if (offset + size > PAGE_CACHE_SIZE) length = PAGE_CACHE_SIZE - offset; else length = size; sg_set_page(&sg[i], tio->pvec[idx + i], length, offset); size -= length; offset = 0; } sg_mark_end(&sg[i - 1]); crypto_hash_update(hash, sg, nbytes); crypto_hash_final(hash, crc); }
static void calc_checksums(char *buf) { struct crypto_hash *tfm; struct hash_desc desc; struct scatterlist sg; char sha1[40]; int i; int ret; tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { return; } desc.tfm = tfm; desc.flags = 0; ret = crypto_hash_init(&desc); if (ret < 0) goto out; sg_init_one(&sg, inbuf, inbuf_size); ret = crypto_hash_update(&desc, &sg, inbuf_size); if (ret < 0) goto out; ret = crypto_hash_final(&desc, sha1); if (ret < 0) goto out; for (i = 0; i < 20; i++) { sprintf(&buf[i * 2], "%02x", sha1[i] & 0xff); } out: crypto_free_hash(tfm); }
void mars_digest(unsigned char *digest, void *data, int len) { struct hash_desc desc = { .tfm = mars_tfm, .flags = 0, }; struct scatterlist sg; memset(digest, 0, mars_digest_size); // TODO: use per-thread instance, omit locking down(&tfm_sem); crypto_hash_init(&desc); sg_init_table(&sg, 1); sg_set_buf(&sg, data, len); crypto_hash_update(&desc, &sg, sg.length); crypto_hash_final(&desc, digest); up(&tfm_sem); } EXPORT_SYMBOL_GPL(mars_digest); void mref_checksum(struct mref_object *mref) { unsigned char checksum[mars_digest_size]; int len; if (mref->ref_cs_mode <= 0 || !mref->ref_data) return; mars_digest(checksum, mref->ref_data, mref->ref_len); len = sizeof(mref->ref_checksum); if (len > mars_digest_size) len = mars_digest_size; memcpy(&mref->ref_checksum, checksum, len); }
/** * Finish hash calculation, copy hash digest to buffer, clean up hash descriptor * * \param[in] hdesc hash descriptor * \param[out] hash pointer to hash buffer to store hash digest * \param[in,out] hash_len pointer to hash buffer size, if \a hash == NULL * or hash_len == NULL only free \a hdesc instead * of computing the hash * * \retval 0 for success * \retval -EOVERFLOW if hash_len is too small for the hash digest * \retval negative errno for other errors from lower layers */ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, unsigned char *hash, unsigned int *hash_len) { int size = crypto_hash_digestsize(((struct hash_desc *)hdesc)->tfm); int err; if (hash == NULL || hash_len == NULL) { err = 0; goto free; } if (*hash_len < size) { err = -EOVERFLOW; goto free; } err = crypto_hash_final((struct hash_desc *)hdesc, hash); if (err == 0) *hash_len = size; free: crypto_free_hash(((struct hash_desc *)hdesc)->tfm); kfree(hdesc); return err; }
int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv, void *data, struct page *page, unsigned int size) { int err; struct scatterlist sg; if (!e->cipher && !e->hash) return 0; dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n", __func__, e, cmd_iv, data, page, (page) ? page->index : 0, size); if (data) { sg_init_one(&sg, data, size); } else { sg_init_table(&sg, 1); sg_set_page(&sg, page, size, 0); } if (e->cipher) { struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash); u8 iv[32]; memset(iv, 0, sizeof(iv)); memcpy(iv, &cmd_iv, sizeof(cmd_iv)); ablkcipher_request_set_tfm(req, e->cipher); err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout); if (err) goto err_out_exit; } if (e->hash) { struct hash_desc desc; void *dst = e->data + e->size/2; desc.tfm = e->hash; desc.flags = 0; err = crypto_hash_init(&desc); if (err) goto err_out_exit; err = crypto_hash_update(&desc, &sg, size); if (err) goto err_out_exit; err = crypto_hash_final(&desc, dst); if (err) goto err_out_exit; err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash)); if (err) { #ifdef CONFIG_POHMELFS_DEBUG unsigned int i; unsigned char *recv = e->data, *calc = dst; dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ", __func__, e, e->hash, e->cipher, cmd_iv); for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) { #if 0 dprintka("%02x ", recv[i]); if (recv[i] != calc[i]) { dprintka("| calc byte: %02x.\n", calc[i]); break; } #else dprintka("%02x/%02x ", recv[i], calc[i]); #endif } dprintk("\n"); #endif goto err_out_exit; } else { dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n", __func__, e, e->hash, e->cipher); } } dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n", __func__, e, e->size, e->hash, e->cipher); return 0; err_out_exit: dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n", __func__, e, e->hash, e->cipher, err); return err; }
static int tf_self_test_digest(const char *alg_name, const struct digest_test_vector *tv) { unsigned char digest[64]; unsigned char input[256]; struct scatterlist sg; struct hash_desc desc = {NULL, 0}; int error; size_t digest_length; desc.tfm = crypto_alloc_hash(alg_name, 0, 0); if (IS_ERR_OR_NULL(desc.tfm)) { ERROR("crypto_alloc_hash(%s) failed", alg_name); error = (desc.tfm == NULL ? -ENOMEM : (int)desc.tfm); goto abort; } digest_length = crypto_hash_digestsize(desc.tfm); INFO("alg_name=%s driver_name=%s digest_length=%u", alg_name, crypto_tfm_alg_driver_name(crypto_hash_tfm(desc.tfm)), digest_length); if (digest_length > sizeof(digest)) { ERROR("digest length too large (%zu > %zu)", digest_length, sizeof(digest)); error = -ENOMEM; goto abort; } if (tv->key != NULL) { error = crypto_hash_setkey(desc.tfm, tv->key, tv->key_length); if (error) { ERROR("crypto_hash_setkey(%s) failed: %d", alg_name, error); goto abort; } TF_TRACE_ARRAY(tv->key, tv->key_length); } error = crypto_hash_init(&desc); if (error) { ERROR("crypto_hash_init(%s) failed: %d", alg_name, error); goto abort; } /* The test vector data is in vmalloc'ed memory since it's a module global. Copy it to the stack, since the crypto API doesn't support vmalloc'ed memory. */ if (tv->length > sizeof(input)) { ERROR("data too large (%zu > %zu)", tv->length, sizeof(input)); error = -ENOMEM; goto abort; } memcpy(input, tv->text, tv->length); INFO("sg_init_one(%p, %p, %u)", &sg, input, tv->length); sg_init_one(&sg, input, tv->length); TF_TRACE_ARRAY(input, tv->length); error = crypto_hash_update(&desc, &sg, tv->length); if (error) { ERROR("crypto_hash_update(%s) failed: %d", alg_name, error); goto abort; } error = crypto_hash_final(&desc, digest); if (error) { ERROR("crypto_hash_final(%s) failed: %d", alg_name, error); goto abort; } crypto_free_hash(desc.tfm); desc.tfm = NULL; if (memcmp(digest, tv->digest, digest_length)) { TF_TRACE_ARRAY(digest, digest_length); ERROR("wrong %s digest value", alg_name); pr_err("[SMC Driver] error: SMC Driver POST FAILURE (%s)\n", alg_name); error = -EINVAL; } else { INFO("%s: digest successful", alg_name); error = 0; } return error; abort: if (!IS_ERR_OR_NULL(desc.tfm)) crypto_free_hash(desc.tfm); pr_err("[SMC Driver] error: SMC Driver POST FAILURE (%s)\n", alg_name); return error; }
/** * iscsi_tcp_segment_done - check whether the segment is complete * @tcp_conn: iscsi tcp connection * @segment: iscsi segment to check * @recv: set to one of this is called from the recv path * @copied: number of bytes copied * * Check if we're done receiving this segment. If the receive * buffer is full but we expect more data, move on to the * next entry in the scatterlist. * * If the amount of data we received isn't a multiple of 4, * we will transparently receive the pad bytes, too. * * This function must be re-entrant. */ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, struct iscsi_segment *segment, int recv, unsigned copied) { struct scatterlist sg; unsigned int pad; ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copied %u %u size %u %s\n", segment->copied, copied, segment->size, recv ? "recv" : "xmit"); if (segment->hash && copied) { /* * If a segment is kmapd we must unmap it before sending * to the crypto layer since that will try to kmap it again. */ iscsi_tcp_segment_unmap(segment); if (!segment->data) { sg_init_table(&sg, 1); sg_set_page(&sg, sg_page(segment->sg), copied, segment->copied + segment->sg_offset + segment->sg->offset); } else sg_init_one(&sg, segment->data + segment->copied, copied); crypto_hash_update(segment->hash, &sg, copied); } segment->copied += copied; if (segment->copied < segment->size) { iscsi_tcp_segment_map(segment, recv); return 0; } segment->total_copied += segment->copied; segment->copied = 0; segment->size = 0; /* Unmap the current scatterlist page, if there is one. */ iscsi_tcp_segment_unmap(segment); /* Do we have more scatterlist entries? */ ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "total copied %u total size %u\n", segment->total_copied, segment->total_size); if (segment->total_copied < segment->total_size) { /* Proceed to the next entry in the scatterlist. */ iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg), 0); iscsi_tcp_segment_map(segment, recv); BUG_ON(segment->size == 0); return 0; } /* Do we need to handle padding? */ if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) { pad = iscsi_padding(segment->total_copied); if (pad != 0) { ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "consume %d pad bytes\n", pad); segment->total_size += pad; segment->size = pad; segment->data = segment->padbuf; return 0; } } /* * Set us up for transferring the data digest. hdr digest * is completely handled in hdr done function. */ if (segment->hash) { crypto_hash_final(segment->hash, segment->digest); iscsi_tcp_segment_splice_digest(segment, recv ? segment->recv_digest : segment->digest); return 0; } return 1; }
static int chap_server_compute_md5( struct iscsi_conn *conn, struct iscsi_node_auth *auth, char *nr_in_ptr, char *nr_out_ptr, unsigned int *nr_out_len) { unsigned long id; unsigned char id_as_uchar; unsigned char digest[MD5_SIGNATURE_SIZE]; unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2]; unsigned char identifier[10], *challenge = NULL; unsigned char *challenge_binhex = NULL; unsigned char client_digest[MD5_SIGNATURE_SIZE]; unsigned char server_digest[MD5_SIGNATURE_SIZE]; unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; size_t compare_len; struct iscsi_chap *chap = conn->auth_protocol; struct crypto_hash *tfm; struct hash_desc desc; struct scatterlist sg; int auth_ret = -1, ret, challenge_len; memset(identifier, 0, 10); memset(chap_n, 0, MAX_CHAP_N_SIZE); memset(chap_r, 0, MAX_RESPONSE_LENGTH); memset(digest, 0, MD5_SIGNATURE_SIZE); memset(response, 0, MD5_SIGNATURE_SIZE * 2 + 2); memset(client_digest, 0, MD5_SIGNATURE_SIZE); memset(server_digest, 0, MD5_SIGNATURE_SIZE); challenge = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL); if (!challenge) { pr_err("Unable to allocate challenge buffer\n"); goto out; } challenge_binhex = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL); if (!challenge_binhex) { pr_err("Unable to allocate challenge_binhex buffer\n"); goto out; } /* * Extract CHAP_N. */ if (extract_param(nr_in_ptr, "CHAP_N", MAX_CHAP_N_SIZE, chap_n, &type) < 0) { pr_err("Could not find CHAP_N.\n"); goto out; } if (type == HEX) { pr_err("Could not find CHAP_N.\n"); goto out; } /* Include the terminating NULL in the compare */ compare_len = strlen(auth->userid) + 1; if (strncmp(chap_n, auth->userid, compare_len) != 0) { pr_err("CHAP_N values do not match!\n"); goto out; } pr_debug("[server] Got CHAP_N=%s\n", chap_n); /* * Extract CHAP_R. */ if (extract_param(nr_in_ptr, "CHAP_R", MAX_RESPONSE_LENGTH, chap_r, &type) < 0) { pr_err("Could not find CHAP_R.\n"); goto out; } if (type != HEX) { pr_err("Could not find CHAP_R.\n"); goto out; } pr_debug("[server] Got CHAP_R=%s\n", chap_r); chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { pr_err("Unable to allocate struct crypto_hash\n"); goto out; } desc.tfm = tfm; desc.flags = 0; ret = crypto_hash_init(&desc); if (ret < 0) { pr_err("crypto_hash_init() failed\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, &chap->id, 1); ret = crypto_hash_update(&desc, &sg, 1); if (ret < 0) { pr_err("crypto_hash_update() failed for id\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, &auth->password, strlen(auth->password)); ret = crypto_hash_update(&desc, &sg, strlen(auth->password)); if (ret < 0) { pr_err("crypto_hash_update() failed for password\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, chap->challenge, CHAP_CHALLENGE_LENGTH); ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH); if (ret < 0) { pr_err("crypto_hash_update() failed for challenge\n"); crypto_free_hash(tfm); goto out; } ret = crypto_hash_final(&desc, server_digest); if (ret < 0) { pr_err("crypto_hash_final() failed for server digest\n"); crypto_free_hash(tfm); goto out; } crypto_free_hash(tfm); chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); pr_debug("[server] MD5 Server Digest: %s\n", response); if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) { pr_debug("[server] MD5 Digests do not match!\n\n"); goto out; } else pr_debug("[server] MD5 Digests match, CHAP connetication" " successful.\n\n"); /* * One way authentication has succeeded, return now if mutual * authentication is not enabled. */ if (!auth->authenticate_target) { kfree(challenge); kfree(challenge_binhex); return 0; } /* * Get CHAP_I. */ if (extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type) < 0) { pr_err("Could not find CHAP_I.\n"); goto out; } if (type == HEX) ret = kstrtoul(&identifier[2], 0, &id); else ret = kstrtoul(identifier, 0, &id); if (ret < 0) { pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret); goto out; } if (id > 255) { pr_err("chap identifier: %lu greater than 255\n", id); goto out; } /* * RFC 1994 says Identifier is no more than octet (8 bits). */ pr_debug("[server] Got CHAP_I=%lu\n", id); /* * Get CHAP_C. */ if (extract_param(nr_in_ptr, "CHAP_C", CHAP_CHALLENGE_STR_LEN, challenge, &type) < 0) { pr_err("Could not find CHAP_C.\n"); goto out; } if (type != HEX) { pr_err("Could not find CHAP_C.\n"); goto out; } pr_debug("[server] Got CHAP_C=%s\n", challenge); challenge_len = chap_string_to_hex(challenge_binhex, challenge, strlen(challenge)); if (!challenge_len) { pr_err("Unable to convert incoming challenge\n"); goto out; } if (challenge_len > 1024) { pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); goto out; } /* * During mutual authentication, the CHAP_C generated by the * initiator must not match the original CHAP_C generated by * the target. */ if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) { pr_err("initiator CHAP_C matches target CHAP_C, failing" " login attempt\n"); goto out; } /* * During mutual authentication, the CHAP_C generated by the * initiator must not match the original CHAP_C generated by * the target. */ if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) { pr_err("initiator CHAP_C matches target CHAP_C, failing" " login attempt\n"); goto out; } /* * Generate CHAP_N and CHAP_R for mutual authentication. */ tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { pr_err("Unable to allocate struct crypto_hash\n"); goto out; } desc.tfm = tfm; desc.flags = 0; ret = crypto_hash_init(&desc); if (ret < 0) { pr_err("crypto_hash_init() failed\n"); crypto_free_hash(tfm); goto out; } /* To handle both endiannesses */ id_as_uchar = id; sg_init_one(&sg, &id_as_uchar, 1); ret = crypto_hash_update(&desc, &sg, 1); if (ret < 0) { pr_err("crypto_hash_update() failed for id\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, auth->password_mutual, strlen(auth->password_mutual)); ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual)); if (ret < 0) { pr_err("crypto_hash_update() failed for" " password_mutual\n"); crypto_free_hash(tfm); goto out; } /* * Convert received challenge to binary hex. */ sg_init_one(&sg, challenge_binhex, challenge_len); ret = crypto_hash_update(&desc, &sg, challenge_len); if (ret < 0) { pr_err("crypto_hash_update() failed for ma challenge\n"); crypto_free_hash(tfm); goto out; } ret = crypto_hash_final(&desc, digest); if (ret < 0) { pr_err("crypto_hash_final() failed for ma digest\n"); crypto_free_hash(tfm); goto out; } crypto_free_hash(tfm); /* * Generate CHAP_N and CHAP_R. */ *nr_out_len = sprintf(nr_out_ptr, "CHAP_N=%s", auth->userid_mutual); *nr_out_len += 1; pr_debug("[server] Sending CHAP_N=%s\n", auth->userid_mutual); /* * Convert response from binary hex to ascii hext. */ chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE); *nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s", response); *nr_out_len += 1; pr_debug("[server] Sending CHAP_R=0x%s\n", response); auth_ret = 0; out: kfree(challenge); kfree(challenge_binhex); return auth_ret; }