14ae71c1dSDavid Howells /* Signature verification with an asymmetric key 24ae71c1dSDavid Howells * 35fb94e9cSMauro Carvalho Chehab * See Documentation/crypto/asymmetric-keys.txt 44ae71c1dSDavid Howells * 54ae71c1dSDavid Howells * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 64ae71c1dSDavid Howells * Written by David Howells (dhowells@redhat.com) 74ae71c1dSDavid Howells * 84ae71c1dSDavid Howells * This program is free software; you can redistribute it and/or 94ae71c1dSDavid Howells * modify it under the terms of the GNU General Public Licence 104ae71c1dSDavid Howells * as published by the Free Software Foundation; either version 114ae71c1dSDavid Howells * 2 of the Licence, or (at your option) any later version. 124ae71c1dSDavid Howells */ 134ae71c1dSDavid Howells 14c3ce6dfaSDavid Howells #define pr_fmt(fmt) "SIG: "fmt 154ae71c1dSDavid Howells #include <keys/asymmetric-subtype.h> 161f6a9ab0SPaul Gortmaker #include <linux/export.h> 174ae71c1dSDavid Howells #include <linux/err.h> 183b764563SDavid Howells #include <linux/slab.h> 195a307718SDavid Howells #include <linux/keyctl.h> 204ae71c1dSDavid Howells #include <crypto/public_key.h> 215a307718SDavid Howells #include <keys/user-type.h> 224ae71c1dSDavid Howells #include "asymmetric_keys.h" 234ae71c1dSDavid Howells 243b764563SDavid Howells /* 253b764563SDavid Howells * Destroy a public key signature. 263b764563SDavid Howells */ 273b764563SDavid Howells void public_key_signature_free(struct public_key_signature *sig) 283b764563SDavid Howells { 29a022ec02SDavid Howells int i; 30a022ec02SDavid Howells 313b764563SDavid Howells if (sig) { 32a022ec02SDavid Howells for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++) 33a022ec02SDavid Howells kfree(sig->auth_ids[i]); 343b764563SDavid Howells kfree(sig->s); 353b764563SDavid Howells kfree(sig->digest); 363b764563SDavid Howells kfree(sig); 373b764563SDavid Howells } 383b764563SDavid Howells } 393b764563SDavid Howells EXPORT_SYMBOL_GPL(public_key_signature_free); 403b764563SDavid Howells 414ae71c1dSDavid Howells /** 425a307718SDavid Howells * query_asymmetric_key - Get information about an aymmetric key. 435a307718SDavid Howells * @params: Various parameters. 445a307718SDavid Howells * @info: Where to put the information. 455a307718SDavid Howells */ 465a307718SDavid Howells int query_asymmetric_key(const struct kernel_pkey_params *params, 475a307718SDavid Howells struct kernel_pkey_query *info) 485a307718SDavid Howells { 495a307718SDavid Howells const struct asymmetric_key_subtype *subtype; 505a307718SDavid Howells struct key *key = params->key; 515a307718SDavid Howells int ret; 525a307718SDavid Howells 535a307718SDavid Howells pr_devel("==>%s()\n", __func__); 545a307718SDavid Howells 555a307718SDavid Howells if (key->type != &key_type_asymmetric) 565a307718SDavid Howells return -EINVAL; 575a307718SDavid Howells subtype = asymmetric_key_subtype(key); 585a307718SDavid Howells if (!subtype || 595a307718SDavid Howells !key->payload.data[0]) 605a307718SDavid Howells return -EINVAL; 615a307718SDavid Howells if (!subtype->query) 625a307718SDavid Howells return -ENOTSUPP; 635a307718SDavid Howells 645a307718SDavid Howells ret = subtype->query(params, info); 655a307718SDavid Howells 665a307718SDavid Howells pr_devel("<==%s() = %d\n", __func__, ret); 675a307718SDavid Howells return ret; 685a307718SDavid Howells } 695a307718SDavid Howells EXPORT_SYMBOL_GPL(query_asymmetric_key); 705a307718SDavid Howells 715a307718SDavid Howells /** 725a307718SDavid Howells * encrypt_blob - Encrypt data using an asymmetric key 735a307718SDavid Howells * @params: Various parameters 745a307718SDavid Howells * @data: Data blob to be encrypted, length params->data_len 755a307718SDavid Howells * @enc: Encrypted data buffer, length params->enc_len 765a307718SDavid Howells * 775a307718SDavid Howells * Encrypt the specified data blob using the private key specified by 785a307718SDavid Howells * params->key. The encrypted data is wrapped in an encoding if 795a307718SDavid Howells * params->encoding is specified (eg. "pkcs1"). 805a307718SDavid Howells * 815a307718SDavid Howells * Returns the length of the data placed in the encrypted data buffer or an 825a307718SDavid Howells * error. 835a307718SDavid Howells */ 845a307718SDavid Howells int encrypt_blob(struct kernel_pkey_params *params, 855a307718SDavid Howells const void *data, void *enc) 865a307718SDavid Howells { 875a307718SDavid Howells params->op = kernel_pkey_encrypt; 885a307718SDavid Howells return asymmetric_key_eds_op(params, data, enc); 895a307718SDavid Howells } 905a307718SDavid Howells EXPORT_SYMBOL_GPL(encrypt_blob); 915a307718SDavid Howells 925a307718SDavid Howells /** 935a307718SDavid Howells * decrypt_blob - Decrypt data using an asymmetric key 945a307718SDavid Howells * @params: Various parameters 955a307718SDavid Howells * @enc: Encrypted data to be decrypted, length params->enc_len 965a307718SDavid Howells * @data: Decrypted data buffer, length params->data_len 975a307718SDavid Howells * 985a307718SDavid Howells * Decrypt the specified data blob using the private key specified by 995a307718SDavid Howells * params->key. The decrypted data is wrapped in an encoding if 1005a307718SDavid Howells * params->encoding is specified (eg. "pkcs1"). 1015a307718SDavid Howells * 1025a307718SDavid Howells * Returns the length of the data placed in the decrypted data buffer or an 1035a307718SDavid Howells * error. 1045a307718SDavid Howells */ 1055a307718SDavid Howells int decrypt_blob(struct kernel_pkey_params *params, 1065a307718SDavid Howells const void *enc, void *data) 1075a307718SDavid Howells { 1085a307718SDavid Howells params->op = kernel_pkey_decrypt; 1095a307718SDavid Howells return asymmetric_key_eds_op(params, enc, data); 1105a307718SDavid Howells } 1115a307718SDavid Howells EXPORT_SYMBOL_GPL(decrypt_blob); 1125a307718SDavid Howells 1135a307718SDavid Howells /** 1145a307718SDavid Howells * create_signature - Sign some data using an asymmetric key 1155a307718SDavid Howells * @params: Various parameters 1165a307718SDavid Howells * @data: Data blob to be signed, length params->data_len 1175a307718SDavid Howells * @enc: Signature buffer, length params->enc_len 1185a307718SDavid Howells * 1195a307718SDavid Howells * Sign the specified data blob using the private key specified by params->key. 1205a307718SDavid Howells * The signature is wrapped in an encoding if params->encoding is specified 1215a307718SDavid Howells * (eg. "pkcs1"). If the encoding needs to know the digest type, this can be 1225a307718SDavid Howells * passed through params->hash_algo (eg. "sha1"). 1235a307718SDavid Howells * 1245a307718SDavid Howells * Returns the length of the data placed in the signature buffer or an error. 1255a307718SDavid Howells */ 1265a307718SDavid Howells int create_signature(struct kernel_pkey_params *params, 1275a307718SDavid Howells const void *data, void *enc) 1285a307718SDavid Howells { 1295a307718SDavid Howells params->op = kernel_pkey_sign; 1305a307718SDavid Howells return asymmetric_key_eds_op(params, data, enc); 1315a307718SDavid Howells } 1325a307718SDavid Howells EXPORT_SYMBOL_GPL(create_signature); 1335a307718SDavid Howells 1345a307718SDavid Howells /** 1354ae71c1dSDavid Howells * verify_signature - Initiate the use of an asymmetric key to verify a signature 1364ae71c1dSDavid Howells * @key: The asymmetric key to verify against 1374ae71c1dSDavid Howells * @sig: The signature to check 1384ae71c1dSDavid Howells * 1394ae71c1dSDavid Howells * Returns 0 if successful or else an error. 1404ae71c1dSDavid Howells */ 1414ae71c1dSDavid Howells int verify_signature(const struct key *key, 1424ae71c1dSDavid Howells const struct public_key_signature *sig) 1434ae71c1dSDavid Howells { 1444ae71c1dSDavid Howells const struct asymmetric_key_subtype *subtype; 1454ae71c1dSDavid Howells int ret; 1464ae71c1dSDavid Howells 1474ae71c1dSDavid Howells pr_devel("==>%s()\n", __func__); 1484ae71c1dSDavid Howells 1494ae71c1dSDavid Howells if (key->type != &key_type_asymmetric) 1504ae71c1dSDavid Howells return -EINVAL; 1514ae71c1dSDavid Howells subtype = asymmetric_key_subtype(key); 1524ae71c1dSDavid Howells if (!subtype || 153146aa8b1SDavid Howells !key->payload.data[0]) 1544ae71c1dSDavid Howells return -EINVAL; 1554ae71c1dSDavid Howells if (!subtype->verify_signature) 1564ae71c1dSDavid Howells return -ENOTSUPP; 1574ae71c1dSDavid Howells 1584ae71c1dSDavid Howells ret = subtype->verify_signature(key, sig); 1594ae71c1dSDavid Howells 1604ae71c1dSDavid Howells pr_devel("<==%s() = %d\n", __func__, ret); 1614ae71c1dSDavid Howells return ret; 1624ae71c1dSDavid Howells } 1634ae71c1dSDavid Howells EXPORT_SYMBOL_GPL(verify_signature); 164