/* * The verify operation is here for completeness similar to the verification * defined in RFC2313 section 10.2 except that block type 0 is not accepted, * as in RFC2437. RFC2437 section 9.2 doesn't define any operation to * retrieve the DigestInfo from a signature, instead the user is expected * to call the sign operation to generate the expected signature and compare * signatures instead of the message-digests. */ static int pkcs1pad_verify(struct akcipher_request *req) { struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); int err; if (!ctx->key_size || req->src_len < ctx->key_size) return -EINVAL; req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL); if (!req_ctx->out_buf) return -ENOMEM; pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf, ctx->key_size, NULL); akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, pkcs1pad_verify_complete_cb, req); /* Reuse input buffer, output to a new buffer */ akcipher_request_set_crypt(&req_ctx->child_req, req->src, req_ctx->out_sg, req->src_len, ctx->key_size); err = crypto_akcipher_verify(&req_ctx->child_req); if (err != -EINPROGRESS && err != -EBUSY) return pkcs1pad_verify_complete(req, err); return err; }
/* * The verify operation is here for completeness similar to the verification * defined in RFC2313 section 10.2 except that block type 0 is not accepted, * as in RFC2437. RFC2437 section 9.2 doesn't define any operation to * retrieve the DigestInfo from a signature, instead the user is expected * to call the sign operation to generate the expected signature and compare * signatures instead of the message-digests. */ static int pkcs1pad_verify(struct akcipher_request *req) { struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); int err; if (!ctx->key_size || req->src_len < ctx->key_size) return -EINVAL; if (ctx->key_size > PAGE_SIZE) return -ENOTSUPP; /* Reuse input buffer, output to a new buffer */ req_ctx->child_req.src = req->src; req_ctx->child_req.src_len = req->src_len; req_ctx->child_req.dst = req_ctx->out_sg; req_ctx->child_req.dst_len = ctx->key_size - 1; req_ctx->out_buf = kmalloc(ctx->key_size - 1, (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC); if (!req_ctx->out_buf) return -ENOMEM; pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf, ctx->key_size - 1, NULL); akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, pkcs1pad_verify_complete_cb, req); err = crypto_akcipher_verify(&req_ctx->child_req); if (err != -EINPROGRESS && (err != -EBUSY || !(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) return pkcs1pad_verify_complete(req, err); return err; }
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; }
/* * 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; }