|
@@ -59,6 +59,81 @@ static void public_key_destroy(void *payload0, void *payload3)
|
|
public_key_signature_free(payload3);
|
|
public_key_signature_free(payload3);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Determine the crypto algorithm name.
|
|
|
|
+ */
|
|
|
|
+static
|
|
|
|
+int software_key_determine_akcipher(const char *encoding,
|
|
|
|
+ const char *hash_algo,
|
|
|
|
+ const struct public_key *pkey,
|
|
|
|
+ char alg_name[CRYPTO_MAX_ALG_NAME])
|
|
|
|
+{
|
|
|
|
+ int n;
|
|
|
|
+
|
|
|
|
+ if (strcmp(encoding, "pkcs1") == 0) {
|
|
|
|
+ /* The data wangled by the RSA algorithm is typically padded
|
|
|
|
+ * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
|
|
|
|
+ * sec 8.2].
|
|
|
|
+ */
|
|
|
|
+ if (!hash_algo)
|
|
|
|
+ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
|
|
|
|
+ "pkcs1pad(%s)",
|
|
|
|
+ pkey->pkey_algo);
|
|
|
|
+ else
|
|
|
|
+ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
|
|
|
|
+ "pkcs1pad(%s,%s)",
|
|
|
|
+ pkey->pkey_algo, hash_algo);
|
|
|
|
+ return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (strcmp(encoding, "raw") == 0) {
|
|
|
|
+ strcpy(alg_name, pkey->pkey_algo);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return -ENOPKG;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Query information about a key.
|
|
|
|
+ */
|
|
|
|
+static int software_key_query(const struct kernel_pkey_params *params,
|
|
|
|
+ struct kernel_pkey_query *info)
|
|
|
|
+{
|
|
|
|
+ struct crypto_akcipher *tfm;
|
|
|
|
+ struct public_key *pkey = params->key->payload.data[asym_crypto];
|
|
|
|
+ char alg_name[CRYPTO_MAX_ALG_NAME];
|
|
|
|
+ int ret, len;
|
|
|
|
+
|
|
|
|
+ ret = software_key_determine_akcipher(params->encoding,
|
|
|
|
+ params->hash_algo,
|
|
|
|
+ pkey, alg_name);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ tfm = crypto_alloc_akcipher(alg_name, 0, 0);
|
|
|
|
+ if (IS_ERR(tfm))
|
|
|
|
+ return PTR_ERR(tfm);
|
|
|
|
+
|
|
|
|
+ ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ goto error_free_tfm;
|
|
|
|
+
|
|
|
|
+ len = crypto_akcipher_maxsize(tfm);
|
|
|
|
+ info->key_size = len * 8;
|
|
|
|
+ info->max_data_size = len;
|
|
|
|
+ info->max_sig_size = len;
|
|
|
|
+ info->max_enc_size = len;
|
|
|
|
+ info->max_dec_size = len;
|
|
|
|
+ info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
|
|
|
|
+ ret = 0;
|
|
|
|
+
|
|
|
|
+error_free_tfm:
|
|
|
|
+ crypto_free_akcipher(tfm);
|
|
|
|
+ pr_devel("<==%s() = %d\n", __func__, ret);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Verify a signature using a public key.
|
|
* Verify a signature using a public key.
|
|
*/
|
|
*/
|
|
@@ -69,8 +144,7 @@ int public_key_verify_signature(const struct public_key *pkey,
|
|
struct crypto_akcipher *tfm;
|
|
struct crypto_akcipher *tfm;
|
|
struct akcipher_request *req;
|
|
struct akcipher_request *req;
|
|
struct scatterlist sig_sg, digest_sg;
|
|
struct scatterlist sig_sg, digest_sg;
|
|
- const char *alg_name;
|
|
|
|
- char alg_name_buf[CRYPTO_MAX_ALG_NAME];
|
|
|
|
|
|
+ char alg_name[CRYPTO_MAX_ALG_NAME];
|
|
void *output;
|
|
void *output;
|
|
unsigned int outlen;
|
|
unsigned int outlen;
|
|
int ret;
|
|
int ret;
|
|
@@ -81,21 +155,11 @@ int public_key_verify_signature(const struct public_key *pkey,
|
|
BUG_ON(!sig);
|
|
BUG_ON(!sig);
|
|
BUG_ON(!sig->s);
|
|
BUG_ON(!sig->s);
|
|
|
|
|
|
- if (!sig->digest)
|
|
|
|
- return -ENOPKG;
|
|
|
|
-
|
|
|
|
- alg_name = sig->pkey_algo;
|
|
|
|
- if (strcmp(sig->pkey_algo, "rsa") == 0) {
|
|
|
|
- /* The data wangled by the RSA algorithm is typically padded
|
|
|
|
- * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
|
|
|
|
- * sec 8.2].
|
|
|
|
- */
|
|
|
|
- if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME,
|
|
|
|
- "pkcs1pad(rsa,%s)", sig->hash_algo
|
|
|
|
- ) >= CRYPTO_MAX_ALG_NAME)
|
|
|
|
- return -EINVAL;
|
|
|
|
- alg_name = alg_name_buf;
|
|
|
|
- }
|
|
|
|
|
|
+ ret = software_key_determine_akcipher(sig->encoding,
|
|
|
|
+ sig->hash_algo,
|
|
|
|
+ pkey, alg_name);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
|
|
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
|
|
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
|
|
if (IS_ERR(tfm))
|
|
if (IS_ERR(tfm))
|
|
@@ -167,6 +231,7 @@ struct asymmetric_key_subtype public_key_subtype = {
|
|
.name_len = sizeof("public_key") - 1,
|
|
.name_len = sizeof("public_key") - 1,
|
|
.describe = public_key_describe,
|
|
.describe = public_key_describe,
|
|
.destroy = public_key_destroy,
|
|
.destroy = public_key_destroy,
|
|
|
|
+ .query = software_key_query,
|
|
.verify_signature = public_key_verify_signature_2,
|
|
.verify_signature = public_key_verify_signature_2,
|
|
};
|
|
};
|
|
EXPORT_SYMBOL_GPL(public_key_subtype);
|
|
EXPORT_SYMBOL_GPL(public_key_subtype);
|