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_DESCRIPTION("In-software asymmetric public-key subtype");
26 MODULE_AUTHOR("Red Hat, Inc.");
27 MODULE_LICENSE("GPL");
30 * Provide a part of a description of the key for /proc/keys.
32 static void public_key_describe(const struct key
*asymmetric_key
,
35 struct public_key
*key
= asymmetric_key
->payload
.data
[asym_crypto
];
38 seq_printf(m
, "%s.%s", key
->id_type
, key
->pkey_algo
);
42 * Destroy a public key algorithm key.
44 void public_key_free(struct public_key
*key
)
51 EXPORT_SYMBOL_GPL(public_key_free
);
54 * Destroy a public key algorithm key.
56 static void public_key_destroy(void *payload0
, void *payload3
)
58 public_key_free(payload0
);
59 public_key_signature_free(payload3
);
63 * Determine the crypto algorithm name.
66 int software_key_determine_akcipher(const char *encoding
,
67 const char *hash_algo
,
68 const struct public_key
*pkey
,
69 char alg_name
[CRYPTO_MAX_ALG_NAME
])
73 if (strcmp(encoding
, "pkcs1") == 0) {
74 /* The data wangled by the RSA algorithm is typically padded
75 * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
79 n
= snprintf(alg_name
, CRYPTO_MAX_ALG_NAME
,
83 n
= snprintf(alg_name
, CRYPTO_MAX_ALG_NAME
,
85 pkey
->pkey_algo
, hash_algo
);
86 return n
>= CRYPTO_MAX_ALG_NAME
? -EINVAL
: 0;
89 if (strcmp(encoding
, "raw") == 0) {
90 strcpy(alg_name
, pkey
->pkey_algo
);
98 * Query information about a key.
100 static int software_key_query(const struct kernel_pkey_params
*params
,
101 struct kernel_pkey_query
*info
)
103 struct crypto_akcipher
*tfm
;
104 struct public_key
*pkey
= params
->key
->payload
.data
[asym_crypto
];
105 char alg_name
[CRYPTO_MAX_ALG_NAME
];
108 ret
= software_key_determine_akcipher(params
->encoding
,
114 tfm
= crypto_alloc_akcipher(alg_name
, 0, 0);
118 if (pkey
->key_is_private
)
119 ret
= crypto_akcipher_set_priv_key(tfm
,
120 pkey
->key
, pkey
->keylen
);
122 ret
= crypto_akcipher_set_pub_key(tfm
,
123 pkey
->key
, pkey
->keylen
);
127 len
= crypto_akcipher_maxsize(tfm
);
128 info
->key_size
= len
* 8;
129 info
->max_data_size
= len
;
130 info
->max_sig_size
= len
;
131 info
->max_enc_size
= len
;
132 info
->max_dec_size
= len
;
133 info
->supported_ops
= (KEYCTL_SUPPORTS_ENCRYPT
|
134 KEYCTL_SUPPORTS_VERIFY
);
135 if (pkey
->key_is_private
)
136 info
->supported_ops
|= (KEYCTL_SUPPORTS_DECRYPT
|
137 KEYCTL_SUPPORTS_SIGN
);
141 crypto_free_akcipher(tfm
);
142 pr_devel("<==%s() = %d\n", __func__
, ret
);
147 * Do encryption, decryption and signing ops.
149 static int software_key_eds_op(struct kernel_pkey_params
*params
,
150 const void *in
, void *out
)
152 const struct public_key
*pkey
= params
->key
->payload
.data
[asym_crypto
];
153 struct akcipher_request
*req
;
154 struct crypto_akcipher
*tfm
;
155 struct crypto_wait cwait
;
156 struct scatterlist in_sg
, out_sg
;
157 char alg_name
[CRYPTO_MAX_ALG_NAME
];
160 pr_devel("==>%s()\n", __func__
);
162 ret
= software_key_determine_akcipher(params
->encoding
,
168 tfm
= crypto_alloc_akcipher(alg_name
, 0, 0);
172 req
= akcipher_request_alloc(tfm
, GFP_KERNEL
);
176 if (pkey
->key_is_private
)
177 ret
= crypto_akcipher_set_priv_key(tfm
,
178 pkey
->key
, pkey
->keylen
);
180 ret
= crypto_akcipher_set_pub_key(tfm
,
181 pkey
->key
, pkey
->keylen
);
185 sg_init_one(&in_sg
, in
, params
->in_len
);
186 sg_init_one(&out_sg
, out
, params
->out_len
);
187 akcipher_request_set_crypt(req
, &in_sg
, &out_sg
, params
->in_len
,
189 crypto_init_wait(&cwait
);
190 akcipher_request_set_callback(req
, CRYPTO_TFM_REQ_MAY_BACKLOG
|
191 CRYPTO_TFM_REQ_MAY_SLEEP
,
192 crypto_req_done
, &cwait
);
194 /* Perform the encryption calculation. */
195 switch (params
->op
) {
196 case kernel_pkey_encrypt
:
197 ret
= crypto_akcipher_encrypt(req
);
199 case kernel_pkey_decrypt
:
200 ret
= crypto_akcipher_decrypt(req
);
202 case kernel_pkey_sign
:
203 ret
= crypto_akcipher_sign(req
);
209 ret
= crypto_wait_req(ret
, &cwait
);
214 akcipher_request_free(req
);
216 crypto_free_akcipher(tfm
);
217 pr_devel("<==%s() = %d\n", __func__
, ret
);
222 * Verify a signature using a public key.
224 int public_key_verify_signature(const struct public_key
*pkey
,
225 const struct public_key_signature
*sig
)
227 struct crypto_wait cwait
;
228 struct crypto_akcipher
*tfm
;
229 struct akcipher_request
*req
;
230 struct scatterlist sig_sg
, digest_sg
;
231 char alg_name
[CRYPTO_MAX_ALG_NAME
];
236 pr_devel("==>%s()\n", __func__
);
242 ret
= software_key_determine_akcipher(sig
->encoding
,
248 tfm
= crypto_alloc_akcipher(alg_name
, 0, 0);
253 req
= akcipher_request_alloc(tfm
, GFP_KERNEL
);
257 if (pkey
->key_is_private
)
258 ret
= crypto_akcipher_set_priv_key(tfm
,
259 pkey
->key
, pkey
->keylen
);
261 ret
= crypto_akcipher_set_pub_key(tfm
,
262 pkey
->key
, pkey
->keylen
);
267 outlen
= crypto_akcipher_maxsize(tfm
);
268 output
= kmalloc(outlen
, GFP_KERNEL
);
272 sg_init_one(&sig_sg
, sig
->s
, sig
->s_size
);
273 sg_init_one(&digest_sg
, output
, outlen
);
274 akcipher_request_set_crypt(req
, &sig_sg
, &digest_sg
, sig
->s_size
,
276 crypto_init_wait(&cwait
);
277 akcipher_request_set_callback(req
, CRYPTO_TFM_REQ_MAY_BACKLOG
|
278 CRYPTO_TFM_REQ_MAY_SLEEP
,
279 crypto_req_done
, &cwait
);
281 /* Perform the verification calculation. This doesn't actually do the
282 * verification, but rather calculates the hash expected by the
283 * signature and returns that to us.
285 ret
= crypto_wait_req(crypto_akcipher_verify(req
), &cwait
);
287 goto out_free_output
;
289 /* Do the actual verification step. */
290 if (req
->dst_len
!= sig
->digest_size
||
291 memcmp(sig
->digest
, output
, sig
->digest_size
) != 0)
297 akcipher_request_free(req
);
299 crypto_free_akcipher(tfm
);
300 pr_devel("<==%s() = %d\n", __func__
, ret
);
301 if (WARN_ON_ONCE(ret
> 0))
305 EXPORT_SYMBOL_GPL(public_key_verify_signature
);
307 static int public_key_verify_signature_2(const struct key
*key
,
308 const struct public_key_signature
*sig
)
310 const struct public_key
*pk
= key
->payload
.data
[asym_crypto
];
311 return public_key_verify_signature(pk
, sig
);
315 * Public key algorithm asymmetric key subtype
317 struct asymmetric_key_subtype public_key_subtype
= {
318 .owner
= THIS_MODULE
,
319 .name
= "public_key",
320 .name_len
= sizeof("public_key") - 1,
321 .describe
= public_key_describe
,
322 .destroy
= public_key_destroy
,
323 .query
= software_key_query
,
324 .eds_op
= software_key_eds_op
,
325 .verify_signature
= public_key_verify_signature_2
,
327 EXPORT_SYMBOL_GPL(public_key_subtype
);