1 /* In-software asymmetric public-key crypto subtype
3 * See Documentation/crypto/asymmetric-keys.txt
5 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public Licence
10 * as published by the Free Software Foundation; either version
11 * 2 of the Licence, or (at your option) any later version.
14 #define pr_fmt(fmt) "PKEY: "fmt
15 #include <linux/module.h>
16 #include <linux/export.h>
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19 #include <linux/seq_file.h>
20 #include <linux/scatterlist.h>
21 #include <keys/asymmetric-subtype.h>
22 #include <crypto/public_key.h>
23 #include <crypto/akcipher.h>
25 MODULE_LICENSE("GPL");
28 * Provide a part of a description of the key for /proc/keys.
30 static void public_key_describe(const struct key
*asymmetric_key
,
33 struct public_key
*key
= asymmetric_key
->payload
.data
[asym_crypto
];
36 seq_printf(m
, "%s.%s", key
->id_type
, key
->pkey_algo
);
40 * Destroy a public key algorithm key.
42 void public_key_free(struct public_key
*key
)
49 EXPORT_SYMBOL_GPL(public_key_free
);
52 * Destroy a public key algorithm key.
54 static void public_key_destroy(void *payload0
, void *payload3
)
56 public_key_free(payload0
);
57 public_key_signature_free(payload3
);
60 struct public_key_completion
{
61 struct completion completion
;
65 static void public_key_verify_done(struct crypto_async_request
*req
, int err
)
67 struct public_key_completion
*compl = req
->data
;
69 if (err
== -EINPROGRESS
)
73 complete(&compl->completion
);
77 * Verify a signature using a public key.
79 int public_key_verify_signature(const struct public_key
*pkey
,
80 const struct public_key_signature
*sig
)
82 struct public_key_completion
compl;
83 struct crypto_akcipher
*tfm
;
84 struct akcipher_request
*req
;
85 struct scatterlist sig_sg
, digest_sg
;
87 char alg_name_buf
[CRYPTO_MAX_ALG_NAME
];
92 pr_devel("==>%s()\n", __func__
);
99 alg_name
= sig
->pkey_algo
;
100 if (strcmp(sig
->pkey_algo
, "rsa") == 0) {
101 /* The data wangled by the RSA algorithm is typically padded
102 * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
105 if (snprintf(alg_name_buf
, CRYPTO_MAX_ALG_NAME
,
106 "pkcs1pad(rsa,%s)", sig
->hash_algo
107 ) >= CRYPTO_MAX_ALG_NAME
)
109 alg_name
= alg_name_buf
;
112 tfm
= crypto_alloc_akcipher(alg_name
, 0, 0);
116 req
= akcipher_request_alloc(tfm
, GFP_KERNEL
);
120 ret
= crypto_akcipher_set_pub_key(tfm
, pkey
->key
, pkey
->keylen
);
125 outlen
= crypto_akcipher_maxsize(tfm
);
126 output
= kmalloc(outlen
, GFP_KERNEL
);
130 sg_init_one(&sig_sg
, sig
->s
, sig
->s_size
);
131 sg_init_one(&digest_sg
, output
, outlen
);
132 akcipher_request_set_crypt(req
, &sig_sg
, &digest_sg
, sig
->s_size
,
134 init_completion(&compl.completion
);
135 akcipher_request_set_callback(req
, CRYPTO_TFM_REQ_MAY_BACKLOG
|
136 CRYPTO_TFM_REQ_MAY_SLEEP
,
137 public_key_verify_done
, &compl);
139 /* Perform the verification calculation. This doesn't actually do the
140 * verification, but rather calculates the hash expected by the
141 * signature and returns that to us.
143 ret
= crypto_akcipher_verify(req
);
144 if (ret
== -EINPROGRESS
) {
145 wait_for_completion(&compl.completion
);
149 goto out_free_output
;
151 /* Do the actual verification step. */
152 if (req
->dst_len
!= sig
->digest_size
||
153 memcmp(sig
->digest
, output
, sig
->digest_size
) != 0)
159 akcipher_request_free(req
);
161 crypto_free_akcipher(tfm
);
162 pr_devel("<==%s() = %d\n", __func__
, ret
);
165 EXPORT_SYMBOL_GPL(public_key_verify_signature
);
167 static int public_key_verify_signature_2(const struct key
*key
,
168 const struct public_key_signature
*sig
)
170 const struct public_key
*pk
= key
->payload
.data
[asym_crypto
];
171 return public_key_verify_signature(pk
, sig
);
175 * Public key algorithm asymmetric key subtype
177 struct asymmetric_key_subtype public_key_subtype
= {
178 .owner
= THIS_MODULE
,
179 .name
= "public_key",
180 .name_len
= sizeof("public_key") - 1,
181 .describe
= public_key_describe
,
182 .destroy
= public_key_destroy
,
183 .verify_signature
= public_key_verify_signature_2
,
185 EXPORT_SYMBOL_GPL(public_key_subtype
);