Message ID | 20160415202317.29343.93424.stgit@tstruk-mobl1 (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Herbert Xu |
Headers | show |
On 04/15/2016 02:32 PM, kbuild test robot wrote: > Hi Tadeusz, > > [auto build test ERROR on cryptodev/master] > [also build test ERROR on v4.6-rc3 next-20160415] > [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] > > url: https://github.com/0day-ci/linux/commits/Tadeusz-Struk/crypto-algif-add-akcipher/20160416-043207 > base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master > config: i386-allmodconfig (attached as .config) > reproduce: > # save the attached .config to linux build tree > make ARCH=i386 Hi, It's is for https://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-next plus this: https://patchwork.kernel.org/patch/8843381/ Thanks,
Hi Tadeusz, [auto build test ERROR on cryptodev/master] [also build test ERROR on v4.6-rc3 next-20160415] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] url: https://github.com/0day-ci/linux/commits/Tadeusz-Struk/crypto-algif-add-akcipher/20160416-043207 base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master config: i386-allmodconfig (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=i386 All error/warnings (new ones prefixed by >>): crypto/algif_akcipher.c: In function 'asym_key_encrypt': >> crypto/algif_akcipher.c:331:9: error: variable 'params' has initializer but incomplete type struct kernel_pkey_params params = {0}; ^ >> crypto/algif_akcipher.c:331:38: warning: excess elements in struct initializer struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c:331:38: note: (near initialization for 'params') >> crypto/algif_akcipher.c:331:28: error: storage size of 'params' isn't known struct kernel_pkey_params params = {0}; ^ >> crypto/algif_akcipher.c:357:8: error: implicit declaration of function 'encrypt_blob' [-Werror=implicit-function-declaration] ret = encrypt_blob(¶ms, in, out); ^ >> crypto/algif_akcipher.c:331:28: warning: unused variable 'params' [-Wunused-variable] struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c: In function 'asym_key_decrypt': crypto/algif_akcipher.c:371:9: error: variable 'params' has initializer but incomplete type struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c:371:38: warning: excess elements in struct initializer struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c:371:38: note: (near initialization for 'params') crypto/algif_akcipher.c:371:28: error: storage size of 'params' isn't known struct kernel_pkey_params params = {0}; ^ >> crypto/algif_akcipher.c:397:8: error: implicit declaration of function 'decrypt_blob' [-Werror=implicit-function-declaration] ret = decrypt_blob(¶ms, in, out); ^ crypto/algif_akcipher.c:371:28: warning: unused variable 'params' [-Wunused-variable] struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c: In function 'asym_key_sign': crypto/algif_akcipher.c:411:9: error: variable 'params' has initializer but incomplete type struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c:411:38: warning: excess elements in struct initializer struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c:411:38: note: (near initialization for 'params') crypto/algif_akcipher.c:411:28: error: storage size of 'params' isn't known struct kernel_pkey_params params = {0}; ^ >> crypto/algif_akcipher.c:437:8: error: implicit declaration of function 'create_signature' [-Werror=implicit-function-declaration] ret = create_signature(¶ms, in, out); ^ crypto/algif_akcipher.c:411:28: warning: unused variable 'params' [-Wunused-variable] struct kernel_pkey_params params = {0}; ^ crypto/algif_akcipher.c: In function 'asym_key_verify': >> crypto/algif_akcipher.c:465:5: error: 'struct public_key_signature' has no member named 'encoding' sig.encoding = "pkcs1"; ^ cc1: some warnings being treated as errors vim +/params +331 crypto/algif_akcipher.c 325 326 return err ? err : size; 327 } 328 329 static int asym_key_encrypt(const struct key *key, struct akcipher_request *req) 330 { > 331 struct kernel_pkey_params params = {0}; 332 char *src = NULL, *dst = NULL, *in, *out; 333 int ret; 334 335 if (!sg_is_last(req->src)) { 336 src = kmalloc(req->src_len, GFP_KERNEL); 337 if (!src) 338 return -ENOMEM; 339 scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); 340 in = src; 341 } else { 342 in = sg_virt(req->src); 343 } 344 if (!sg_is_last(req->dst)) { 345 dst = kmalloc(req->dst_len, GFP_KERNEL); 346 if (!dst) { 347 kfree(src); 348 return -ENOMEM; 349 } 350 out = dst; 351 } else { 352 out = sg_virt(req->dst); 353 } 354 params.key = (struct key *)key; 355 params.data_len = req->src_len; 356 params.enc_len = req->dst_len; > 357 ret = encrypt_blob(¶ms, in, out); 358 if (ret) 359 goto free; 360 361 if (dst) 362 scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1); 363 free: 364 kfree(src); 365 kfree(dst); 366 return ret; 367 } 368 369 static int asym_key_decrypt(const struct key *key, struct akcipher_request *req) 370 { > 371 struct kernel_pkey_params params = {0}; 372 char *src = NULL, *dst = NULL, *in, *out; 373 int ret; 374 375 if (!sg_is_last(req->src)) { 376 src = kmalloc(req->src_len, GFP_KERNEL); 377 if (!src) 378 return -ENOMEM; 379 scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); 380 in = src; 381 } else { 382 in = sg_virt(req->src); 383 } 384 if (!sg_is_last(req->dst)) { 385 dst = kmalloc(req->dst_len, GFP_KERNEL); 386 if (!dst) { 387 kfree(src); 388 return -ENOMEM; 389 } 390 out = dst; 391 } else { 392 out = sg_virt(req->dst); 393 } 394 params.key = (struct key *)key; 395 params.data_len = req->src_len; 396 params.enc_len = req->dst_len; > 397 ret = decrypt_blob(¶ms, in, out); 398 if (ret) 399 goto free; 400 401 if (dst) 402 scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1); 403 free: 404 kfree(src); 405 kfree(dst); 406 return ret; 407 } 408 409 static int asym_key_sign(const struct key *key, struct akcipher_request *req) 410 { > 411 struct kernel_pkey_params params = {0}; 412 char *src = NULL, *dst = NULL, *in, *out; 413 int ret; 414 415 if (!sg_is_last(req->src)) { 416 src = kmalloc(req->src_len, GFP_KERNEL); 417 if (!src) 418 return -ENOMEM; 419 scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); 420 in = src; 421 } else { 422 in = sg_virt(req->src); 423 } 424 if (!sg_is_last(req->dst)) { 425 dst = kmalloc(req->dst_len, GFP_KERNEL); 426 if (!dst) { 427 kfree(src); 428 return -ENOMEM; 429 } 430 out = dst; 431 } else { 432 out = sg_virt(req->dst); 433 } 434 params.key = (struct key *)key; 435 params.data_len = req->src_len; 436 params.enc_len = req->dst_len; > 437 ret = create_signature(¶ms, in, out); 438 if (ret) 439 goto free; 440 441 if (dst) 442 scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1); 443 free: 444 kfree(src); 445 kfree(dst); 446 return ret; 447 } 448 449 static int asym_key_verify(const struct key *key, struct akcipher_request *req) 450 { 451 struct public_key_signature sig; 452 char *src = NULL, *in; 453 int ret; 454 455 if (!sg_is_last(req->src)) { 456 src = kmalloc(req->src_len, GFP_KERNEL); 457 if (!src) 458 return -ENOMEM; 459 scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); 460 in = src; 461 } else { 462 in = sg_virt(req->src); 463 } 464 sig.pkey_algo = "rsa"; > 465 sig.encoding = "pkcs1"; 466 /* Need to find a way to pass the hash param */ 467 sig.hash_algo = "sha1"; 468 sig.digest_size = 20; --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Fri, Apr 15, 2016 at 02:32:47PM -0700, Tadeusz Struk wrote: > On 04/15/2016 02:32 PM, kbuild test robot wrote: > > Hi Tadeusz, > > > > [auto build test ERROR on cryptodev/master] > > [also build test ERROR on v4.6-rc3 next-20160415] > > [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] > > > > url: https://github.com/0day-ci/linux/commits/Tadeusz-Struk/crypto-algif-add-akcipher/20160416-043207 > > base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master > > config: i386-allmodconfig (attached as .config) > > reproduce: > > # save the attached .config to linux build tree > > make ARCH=i386 > > Hi, > It's is for https://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-next > plus this: > https://patchwork.kernel.org/patch/8843381/ Thanks Tadeusz for the feedback. hi Xiaolong, anything we can do in 0day side to detect the base for this case? > Thanks, > -- > TS > -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 24dc082..59c8244 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -260,6 +260,16 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, err = alg_setkey(sk, optval, optlen, type->setpubkey); break; + + case ALG_SET_KEY_ID: + case ALG_SET_PUBKEY_ID: + /* ALG_SET_KEY_ID is only for akcipher */ + if (!strcmp(type->name, "akcipher") || + sock->state == SS_CONNECTED) + goto unlock; + + err = alg_setkey(sk, optval, optlen, type->setkeyid); + break; case ALG_SET_AEAD_AUTHSIZE: if (sock->state == SS_CONNECTED) goto unlock; diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c index e00793d..863866d 100644 --- a/crypto/algif_akcipher.c +++ b/crypto/algif_akcipher.c @@ -14,6 +14,8 @@ #include <crypto/akcipher.h> #include <crypto/scatterwalk.h> #include <crypto/if_alg.h> +#include <crypto/public_key.h> +#include <keys/asymmetric-type.h> #include <linux/init.h> #include <linux/list.h> #include <linux/kernel.h> @@ -29,6 +31,7 @@ struct akcipher_sg_list { struct akcipher_tfm { struct crypto_akcipher *akcipher; + char keyid[12]; bool has_key; }; @@ -37,6 +40,7 @@ struct akcipher_ctx { struct af_alg_sgl rsgl[ALG_MAX_PAGES]; struct af_alg_completion completion; + struct key *key; unsigned long used; @@ -322,6 +326,153 @@ unlock: return err ? err : size; } +static int asym_key_encrypt(const struct key *key, struct akcipher_request *req) +{ + struct kernel_pkey_params params = {0}; + char *src = NULL, *dst = NULL, *in, *out; + int ret; + + if (!sg_is_last(req->src)) { + src = kmalloc(req->src_len, GFP_KERNEL); + if (!src) + return -ENOMEM; + scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); + in = src; + } else { + in = sg_virt(req->src); + } + if (!sg_is_last(req->dst)) { + dst = kmalloc(req->dst_len, GFP_KERNEL); + if (!dst) { + kfree(src); + return -ENOMEM; + } + out = dst; + } else { + out = sg_virt(req->dst); + } + params.key = (struct key *)key; + params.data_len = req->src_len; + params.enc_len = req->dst_len; + ret = encrypt_blob(¶ms, in, out); + if (ret) + goto free; + + if (dst) + scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1); +free: + kfree(src); + kfree(dst); + return ret; +} + +static int asym_key_decrypt(const struct key *key, struct akcipher_request *req) +{ + struct kernel_pkey_params params = {0}; + char *src = NULL, *dst = NULL, *in, *out; + int ret; + + if (!sg_is_last(req->src)) { + src = kmalloc(req->src_len, GFP_KERNEL); + if (!src) + return -ENOMEM; + scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); + in = src; + } else { + in = sg_virt(req->src); + } + if (!sg_is_last(req->dst)) { + dst = kmalloc(req->dst_len, GFP_KERNEL); + if (!dst) { + kfree(src); + return -ENOMEM; + } + out = dst; + } else { + out = sg_virt(req->dst); + } + params.key = (struct key *)key; + params.data_len = req->src_len; + params.enc_len = req->dst_len; + ret = decrypt_blob(¶ms, in, out); + if (ret) + goto free; + + if (dst) + scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1); +free: + kfree(src); + kfree(dst); + return ret; +} + +static int asym_key_sign(const struct key *key, struct akcipher_request *req) +{ + struct kernel_pkey_params params = {0}; + char *src = NULL, *dst = NULL, *in, *out; + int ret; + + if (!sg_is_last(req->src)) { + src = kmalloc(req->src_len, GFP_KERNEL); + if (!src) + return -ENOMEM; + scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); + in = src; + } else { + in = sg_virt(req->src); + } + if (!sg_is_last(req->dst)) { + dst = kmalloc(req->dst_len, GFP_KERNEL); + if (!dst) { + kfree(src); + return -ENOMEM; + } + out = dst; + } else { + out = sg_virt(req->dst); + } + params.key = (struct key *)key; + params.data_len = req->src_len; + params.enc_len = req->dst_len; + ret = create_signature(¶ms, in, out); + if (ret) + goto free; + + if (dst) + scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1); +free: + kfree(src); + kfree(dst); + return ret; +} + +static int asym_key_verify(const struct key *key, struct akcipher_request *req) +{ + struct public_key_signature sig; + char *src = NULL, *in; + int ret; + + if (!sg_is_last(req->src)) { + src = kmalloc(req->src_len, GFP_KERNEL); + if (!src) + return -ENOMEM; + scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0); + in = src; + } else { + in = sg_virt(req->src); + } + sig.pkey_algo = "rsa"; + sig.encoding = "pkcs1"; + /* Need to find a way to pass the hash param */ + sig.hash_algo = "sha1"; + sig.digest_size = 20; + sig.s_size = req->src_len; + sig.s = src; + ret = verify_signature(key, &sig); + kfree(src); + return ret; +} + static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -377,16 +528,28 @@ static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg, usedpages); switch (ctx->op) { case ALG_OP_VERIFY: - err = crypto_akcipher_verify(&ctx->req); + if (ctx->key) + err = asym_key_verify(ctx->key, &ctx->req); + else + err = crypto_akcipher_verify(&ctx->req); break; case ALG_OP_SIGN: - err = crypto_akcipher_sign(&ctx->req); + if (ctx->key) + err = asym_key_sign(ctx->key, &ctx->req); + else + err = crypto_akcipher_sign(&ctx->req); break; case ALG_OP_ENCRYPT: - err = crypto_akcipher_encrypt(&ctx->req); + if (ctx->key) + err = asym_key_encrypt(ctx->key, &ctx->req); + else + err = crypto_akcipher_encrypt(&ctx->req); break; case ALG_OP_DECRYPT: - err = crypto_akcipher_decrypt(&ctx->req); + if (ctx->key) + err = asym_key_decrypt(ctx->key, &ctx->req); + else + err = crypto_akcipher_decrypt(&ctx->req); break; default: err = -EFAULT; @@ -579,6 +742,27 @@ static void akcipher_release(void *private) kfree(tfm); } +static int akcipher_setkeyid(void *private, const u8 *key, unsigned int keylen) +{ + struct akcipher_tfm *tfm = private; + struct key *akey; + u32 keyid = *((u32 *)key); + int err = -ENOKEY; + + /* Store the key id and verify that a key with the given id is present. + * The actual key will be acquired in the accept_parent function + */ + sprintf(tfm->keyid, "id:%08x", keyid); + akey = request_key(&key_type_asymmetric, tfm->keyid, NULL); + if (IS_ERR(key)) + goto out; + + tfm->has_key = true; + key_put(akey); +out: + return err; +} + static int akcipher_setprivkey(void *private, const u8 *key, unsigned int keylen) { @@ -610,6 +794,8 @@ static void akcipher_sock_destruct(struct sock *sk) akcipher_put_sgl(sk); sock_kfree_s(sk, ctx, ctx->len); af_alg_release_parent(sk); + if (ctx->key) + key_put(ctx->key); } static int akcipher_accept_parent_nokey(void *private, struct sock *sk) @@ -618,6 +804,7 @@ static int akcipher_accept_parent_nokey(void *private, struct sock *sk) struct alg_sock *ask = alg_sk(sk); struct akcipher_tfm *tfm = private; struct crypto_akcipher *akcipher = tfm->akcipher; + struct key *key; unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(akcipher); ctx = sock_kmalloc(sk, len, GFP_KERNEL); @@ -634,11 +821,20 @@ static int akcipher_accept_parent_nokey(void *private, struct sock *sk) af_alg_init_completion(&ctx->completion); sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES); - ask->private = ctx; + if (strlen(tfm->keyid)) { + key = request_key(&key_type_asymmetric, tfm->keyid, NULL); + if (IS_ERR(key)) { + sock_kfree_s(sk, ctx, len); + return -ENOKEY; + } + ctx->key = key; + memset(tfm->keyid, '\0', sizeof(tfm->keyid)); + } akcipher_request_set_tfm(&ctx->req, akcipher); akcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, af_alg_complete, &ctx->completion); + ask->private = ctx; sk->sk_destruct = akcipher_sock_destruct; @@ -660,6 +856,7 @@ static const struct af_alg_type algif_type_akcipher = { .release = akcipher_release, .setkey = akcipher_setprivkey, .setpubkey = akcipher_setpubkey, + .setkeyid = akcipher_setkeyid, .accept = akcipher_accept_parent, .accept_nokey = akcipher_accept_parent_nokey, .ops = &algif_akcipher_ops, diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 6c3e6e7..09c99ab 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -53,6 +53,7 @@ struct af_alg_type { void (*release)(void *private); int (*setkey)(void *private, const u8 *key, unsigned int keylen); int (*setpubkey)(void *private, const u8 *key, unsigned int keylen); + int (*setkeyid)(void *private, const u8 *key, unsigned int keylen); int (*accept)(void *private, struct sock *sk); int (*accept_nokey)(void *private, struct sock *sk); int (*setauthsize)(void *private, unsigned int authsize); diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h index 02e6162..0379766 100644 --- a/include/uapi/linux/if_alg.h +++ b/include/uapi/linux/if_alg.h @@ -35,6 +35,8 @@ struct af_alg_iv { #define ALG_SET_AEAD_ASSOCLEN 4 #define ALG_SET_AEAD_AUTHSIZE 5 #define ALG_SET_PUBKEY 6 +#define ALG_SET_PUBKEY_ID 7 +#define ALG_SET_KEY_ID 8 /* Operations */ #define ALG_OP_DECRYPT 0
This patch adds support for asymmetric key type to AF_ALG. It will work as follows: A new PF_ALG socket options are added on top of existing ALG_SET_KEY and ALG_SET_PUBKEY, namely ALG_SET_KEY_ID and ALG_SET_PUBKEY_ID for setting public and private keys respectively. When these new options will be used the user, instead of providing the key material, will provide a key id and the key itself will be obtained from kernel keyring subsystem. The user will use the standard tools (keyctl tool or the keyctl syscall) for key instantiation and to obtain the key id. The key id can also be obtained by reading the /proc/keys file. When a key corresponding to the given keyid is found, it is stored in the socket context and subsequent crypto operation invoked by the user will use the new asymmetric accessor functions instead of akcipher api. The asymmetric subtype can internally use akcipher api or invoke operations defined by a given subtype, depending on the key type. Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> --- crypto/af_alg.c | 10 ++ crypto/algif_akcipher.c | 207 ++++++++++++++++++++++++++++++++++++++++++- include/crypto/if_alg.h | 1 include/uapi/linux/if_alg.h | 2 4 files changed, 215 insertions(+), 5 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html