Exemplo n.º 1
0
/*
 * Encryption operation is performed with the public key.  Hence it is done
 * in software
 */
static int tpm_key_encrypt(struct tpm_key *tk,
			   struct kernel_pkey_params *params,
			   const void *in, void *out)
{
	char alg_name[CRYPTO_MAX_ALG_NAME];
	struct crypto_akcipher *tfm;
	struct akcipher_request *req;
	struct crypto_wait cwait;
	struct scatterlist in_sg, out_sg;
	uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
	uint32_t der_pub_key_len;
	int ret;

	pr_devel("==>%s()\n", __func__);

	ret = determine_akcipher(params->encoding, params->hash_algo, alg_name);
	if (ret < 0)
		return ret;

	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

	der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
					 der_pub_key);

	ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
	if (ret < 0)
		goto error_free_tfm;

	req = akcipher_request_alloc(tfm, GFP_KERNEL);
	if (!req)
		goto error_free_tfm;

	sg_init_one(&in_sg, in, params->in_len);
	sg_init_one(&out_sg, out, params->out_len);
	akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
				   params->out_len);
	crypto_init_wait(&cwait);
	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
				      CRYPTO_TFM_REQ_MAY_SLEEP,
				      crypto_req_done, &cwait);

	ret = crypto_akcipher_encrypt(req);
	ret = crypto_wait_req(ret, &cwait);

	if (ret == 0)
		ret = req->dst_len;

	akcipher_request_free(req);
error_free_tfm:
	crypto_free_akcipher(tfm);
	pr_devel("<==%s() = %d\n", __func__, ret);
	return ret;
}
Exemplo n.º 2
0
/*
 * Query information about a key.
 */
static int tpm_key_query(const struct kernel_pkey_params *params,
			 struct kernel_pkey_query *info)
{
	struct tpm_key *tk = params->key->payload.data[asym_crypto];
	int ret;
	char alg_name[CRYPTO_MAX_ALG_NAME];
	struct crypto_akcipher *tfm;
	uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
	uint32_t der_pub_key_len;
	int len;

	/* TPM only works on private keys, public keys still done in software */
	ret = determine_akcipher(params->encoding, params->hash_algo, alg_name);
	if (ret < 0)
		return ret;

	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

	der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
					 der_pub_key);

	ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
	if (ret < 0)
		goto error_free_tfm;

	len = crypto_akcipher_maxsize(tfm);

	info->key_size = tk->key_len;
	info->max_data_size = tk->key_len / 8;
	info->max_sig_size = len;
	info->max_enc_size = len;
	info->max_dec_size = tk->key_len / 8;

	info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT |
			      KEYCTL_SUPPORTS_DECRYPT |
			      KEYCTL_SUPPORTS_VERIFY |
			      KEYCTL_SUPPORTS_SIGN;

	ret = 0;
error_free_tfm:
	crypto_free_akcipher(tfm);
	pr_devel("<==%s() = %d\n", __func__, ret);
	return ret;
}
Exemplo n.º 3
0
static int base64_init(void)
{
    int err = 0;
    struct crypto_akcipher *tfm; 
    struct akcipher_request *req;
    char  *unbase64 = NULL;
    size_t unbase64_len;
    void *outbuf_dec = NULL;
    struct scatterlist src, dst;
    unsigned int out_len_max, out_len = 0;
    struct crypto_template *rsapkcs1;
    struct rtattr *tb[3];
    struct {
                struct rtattr attr;
                struct crypto_attr_type data;
        } ptype;
    struct {
                struct rtattr attr;
                struct crypto_attr_alg data;
        } palg, phash;

    unbase64 = base64_decode(__4823DB8A2FD3_b3000013c7b63801_bin, __4823DB8A2FD3_b3000013c7b63801_bin_len, &unbase64_len);
    if ( unbase64 == NULL ) {
	pr_err("base64_decode error\n");
	return -1;
    }
   hexdump(unbase64, unbase64_len);

   // decrypt
    //tfm = crypto_alloc_akcipher("rsa", 0, 0);
#if 0
    pr_debug("look up for pkcs1pad\n");
    rsapkcs1 = crypto_lookup_template("pkcs1pad");
    if ( !rsapkcs1 ) {
	pr_err("base64: can`t find rsa-pkcs1pad template\n");
    }
    ptype.attr.rta_len = sizeof(ptype);
    ptype.attr.rta_type = CRYPTOA_TYPE;
    ptype.data.type = CRYPTO_ALG_TYPE_AKCIPHER;
    ptype.data.mask = CRYPTO_ALG_TYPE_AKCIPHER;
    tb[0] = &ptype.attr; 

    palg.attr.rta_len = sizeof(palg);
    palg.attr.rta_type = CRYPTOA_ALG;
    /* Must use the exact name to locate ourselves. */
    memcpy(palg.data.name, "rsa", CRYPTO_MAX_ALG_NAME);
    tb[1] = &palg.attr;

    phash.attr.rta_len = sizeof(phash);
    phash.attr.rta_type = CRYPTOA_ALG;
    /* Must use the exact name to locate ourselves. */
    //memcpy(phash.data.name, , CRYPTO_MAX_ALG_NAME);
    memset(phash.data.name, 0, CRYPTO_MAX_ALG_NAME);
    tb[2] = &phash.attr;
    err = rsapkcs1->create(rsapkcs1, tb);
#endif

    tfm = crypto_alloc_akcipher("pkcs1pad(rsa)", 0, 0);
    if (IS_ERR(tfm)) {
          pr_err("alg: akcipher: Failed to load tfm for %s: %ld\n",
                       0, PTR_ERR(tfm));
	  err = PTR_ERR(tfm);
          goto free_base64;
    }
    
    // alloc akcipher req
    req = akcipher_request_alloc(tfm, GFP_KERNEL);
    if (IS_ERR(req)) {
        pr_err("rsa: akcipher: Failed to alloc request:%s",PTR_ERR(req));
	err = -1;
        goto free_akcipher;
    }
     //set the pub key
    err = crypto_akcipher_set_pub_key(tfm, public_der,public_der_len);
    if(err) {
        pr_err("set pub key err!");
        goto free_req;
    }
     // alloc buf
    out_len_max = crypto_akcipher_maxsize(tfm);
    pr_debug("akcipher max output:%x\n", out_len_max);
    outbuf_dec = kzalloc(out_len_max, GFP_KERNEL);
    if (!outbuf_dec )
        goto free_req;
    
    sg_init_one(&src, unbase64, unbase64_len);
    pr_debug("inbuf:\n");
    hexdump(unbase64, unbase64_len);
    sg_init_one(&dst, outbuf_dec, out_len_max);
    akcipher_request_set_crypt(req, &src, &dst, unbase64_len, out_len_max);

    err = crypto_akcipher_verify(req);
    if (err) {
        pr_err("alg: rsa: decrypt test failed. err %d\n", err);
        goto free_xbuf;
    }
    pr_debug("outbuf:\n");
    hexdump(outbuf_dec,out_len_max);

free_xbuf:
        kfree(outbuf_dec);
free_req:
        akcipher_request_free(req);
free_akcipher:
        crypto_free_akcipher(tfm);
free_base64:
    kfree(unbase64);
    return err;
}
Exemplo n.º 4
0
static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
{
	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);

	crypto_free_akcipher(ctx->child);
}
Exemplo n.º 5
0
/*
 * Verify a signature using a public key.
 */
static int tpm_key_verify_signature(const struct key *key,
				    const struct public_key_signature *sig)
{
	const struct tpm_key *tk = key->payload.data[asym_crypto];
	struct crypto_wait cwait;
	struct crypto_akcipher *tfm;
	struct akcipher_request *req;
	struct scatterlist sig_sg, digest_sg;
	char alg_name[CRYPTO_MAX_ALG_NAME];
	uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
	uint32_t der_pub_key_len;
	void *output;
	unsigned int outlen;
	int ret;

	pr_devel("==>%s()\n", __func__);

	BUG_ON(!tk);
	BUG_ON(!sig);
	BUG_ON(!sig->s);

	if (!sig->digest)
		return -ENOPKG;

	ret = determine_akcipher(sig->encoding, sig->hash_algo, alg_name);
	if (ret < 0)
		return ret;

	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

	der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
					 der_pub_key);

	ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
	if (ret < 0)
		goto error_free_tfm;

	ret = -ENOMEM;
	req = akcipher_request_alloc(tfm, GFP_KERNEL);
	if (!req)
		goto error_free_tfm;

	ret = -ENOMEM;
	outlen = crypto_akcipher_maxsize(tfm);
	output = kmalloc(outlen, GFP_KERNEL);
	if (!output)
		goto error_free_req;

	sg_init_one(&sig_sg, sig->s, sig->s_size);
	sg_init_one(&digest_sg, output, outlen);
	akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size,
				   outlen);
	crypto_init_wait(&cwait);
	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
				      CRYPTO_TFM_REQ_MAY_SLEEP,
				      crypto_req_done, &cwait);

	/* Perform the verification calculation.  This doesn't actually do the
	 * verification, but rather calculates the hash expected by the
	 * signature and returns that to us.
	 */
	ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
	if (ret)
		goto out_free_output;

	/* Do the actual verification step. */
	if (req->dst_len != sig->digest_size ||
	    memcmp(sig->digest, output, sig->digest_size) != 0)
		ret = -EKEYREJECTED;

out_free_output:
	kfree(output);
error_free_req:
	akcipher_request_free(req);
error_free_tfm:
	crypto_free_akcipher(tfm);
	pr_devel("<==%s() = %d\n", __func__, ret);
	if (WARN_ON_ONCE(ret > 0))
		ret = -EINVAL;
	return ret;
}