1051dbb91SDmitry Kasatkin /* 2051dbb91SDmitry Kasatkin * Copyright (C) 2011 Nokia Corporation 3051dbb91SDmitry Kasatkin * Copyright (C) 2011 Intel Corporation 4051dbb91SDmitry Kasatkin * 5051dbb91SDmitry Kasatkin * Author: 6051dbb91SDmitry Kasatkin * Dmitry Kasatkin <dmitry.kasatkin@nokia.com> 7051dbb91SDmitry Kasatkin * <dmitry.kasatkin@intel.com> 8051dbb91SDmitry Kasatkin * 9051dbb91SDmitry Kasatkin * This program is free software; you can redistribute it and/or modify 10051dbb91SDmitry Kasatkin * it under the terms of the GNU General Public License as published by 11051dbb91SDmitry Kasatkin * the Free Software Foundation, version 2 of the License. 12051dbb91SDmitry Kasatkin * 13051dbb91SDmitry Kasatkin * File: sign.c 14051dbb91SDmitry Kasatkin * implements signature (RSA) verification 15051dbb91SDmitry Kasatkin * pkcs decoding is based on LibTomCrypt code 16051dbb91SDmitry Kasatkin */ 17051dbb91SDmitry Kasatkin 18051dbb91SDmitry Kasatkin #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19051dbb91SDmitry Kasatkin 20051dbb91SDmitry Kasatkin #include <linux/err.h> 21051dbb91SDmitry Kasatkin #include <linux/module.h> 22051dbb91SDmitry Kasatkin #include <linux/slab.h> 23051dbb91SDmitry Kasatkin #include <linux/key.h> 24051dbb91SDmitry Kasatkin #include <linux/crypto.h> 25051dbb91SDmitry Kasatkin #include <crypto/hash.h> 26051dbb91SDmitry Kasatkin #include <crypto/sha.h> 27051dbb91SDmitry Kasatkin #include <keys/user-type.h> 28051dbb91SDmitry Kasatkin #include <linux/mpi.h> 29051dbb91SDmitry Kasatkin #include <linux/digsig.h> 30051dbb91SDmitry Kasatkin 31051dbb91SDmitry Kasatkin static struct crypto_shash *shash; 32051dbb91SDmitry Kasatkin 3326d43845SDmitry Kasatkin static const char *pkcs_1_v1_5_decode_emsa(const unsigned char *msg, 34051dbb91SDmitry Kasatkin unsigned long msglen, 35051dbb91SDmitry Kasatkin unsigned long modulus_bitlen, 36b35e286aSDmitry Kasatkin unsigned long *outlen) 37051dbb91SDmitry Kasatkin { 38051dbb91SDmitry Kasatkin unsigned long modulus_len, ps_len, i; 39051dbb91SDmitry Kasatkin 40051dbb91SDmitry Kasatkin modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); 41051dbb91SDmitry Kasatkin 42051dbb91SDmitry Kasatkin /* test message size */ 43051dbb91SDmitry Kasatkin if ((msglen > modulus_len) || (modulus_len < 11)) 4426d43845SDmitry Kasatkin return NULL; 45051dbb91SDmitry Kasatkin 46051dbb91SDmitry Kasatkin /* separate encoded message */ 4726d43845SDmitry Kasatkin if (msg[0] != 0x00 || msg[1] != 0x01) 4826d43845SDmitry Kasatkin return NULL; 49051dbb91SDmitry Kasatkin 50051dbb91SDmitry Kasatkin for (i = 2; i < modulus_len - 1; i++) 51051dbb91SDmitry Kasatkin if (msg[i] != 0xFF) 52051dbb91SDmitry Kasatkin break; 53051dbb91SDmitry Kasatkin 54051dbb91SDmitry Kasatkin /* separator check */ 55b35e286aSDmitry Kasatkin if (msg[i] != 0) 56051dbb91SDmitry Kasatkin /* There was no octet with hexadecimal value 0x00 57051dbb91SDmitry Kasatkin to separate ps from m. */ 5826d43845SDmitry Kasatkin return NULL; 59051dbb91SDmitry Kasatkin 60051dbb91SDmitry Kasatkin ps_len = i - 2; 61051dbb91SDmitry Kasatkin 62051dbb91SDmitry Kasatkin *outlen = (msglen - (2 + ps_len + 1)); 63051dbb91SDmitry Kasatkin 6426d43845SDmitry Kasatkin return msg + 2 + ps_len + 1; 65051dbb91SDmitry Kasatkin } 66051dbb91SDmitry Kasatkin 67051dbb91SDmitry Kasatkin /* 68051dbb91SDmitry Kasatkin * RSA Signature verification with public key 69051dbb91SDmitry Kasatkin */ 70051dbb91SDmitry Kasatkin static int digsig_verify_rsa(struct key *key, 71051dbb91SDmitry Kasatkin const char *sig, int siglen, 72051dbb91SDmitry Kasatkin const char *h, int hlen) 73051dbb91SDmitry Kasatkin { 74051dbb91SDmitry Kasatkin int err = -EINVAL; 75051dbb91SDmitry Kasatkin unsigned long len; 76051dbb91SDmitry Kasatkin unsigned long mlen, mblen; 77051dbb91SDmitry Kasatkin unsigned nret, l; 78b35e286aSDmitry Kasatkin int head, i; 7926d43845SDmitry Kasatkin unsigned char *out1 = NULL; 8026d43845SDmitry Kasatkin const char *m; 81051dbb91SDmitry Kasatkin MPI in = NULL, res = NULL, pkey[2]; 82146aa8b1SDavid Howells uint8_t *p, *datap; 83146aa8b1SDavid Howells const uint8_t *endp; 84146aa8b1SDavid Howells const struct user_key_payload *ukp; 85051dbb91SDmitry Kasatkin struct pubkey_hdr *pkh; 86051dbb91SDmitry Kasatkin 87051dbb91SDmitry Kasatkin down_read(&key->sem); 880837e49aSDavid Howells ukp = user_key_payload_locked(key); 89f58a0815SDmitry Kasatkin 90*192cabd6SEric Biggers if (!ukp) { 91*192cabd6SEric Biggers /* key was revoked before we acquired its semaphore */ 92*192cabd6SEric Biggers err = -EKEYREVOKED; 93*192cabd6SEric Biggers goto err1; 94*192cabd6SEric Biggers } 95*192cabd6SEric Biggers 96f58a0815SDmitry Kasatkin if (ukp->datalen < sizeof(*pkh)) 97f58a0815SDmitry Kasatkin goto err1; 98f58a0815SDmitry Kasatkin 99051dbb91SDmitry Kasatkin pkh = (struct pubkey_hdr *)ukp->data; 100051dbb91SDmitry Kasatkin 101051dbb91SDmitry Kasatkin if (pkh->version != 1) 102051dbb91SDmitry Kasatkin goto err1; 103051dbb91SDmitry Kasatkin 104051dbb91SDmitry Kasatkin if (pkh->algo != PUBKEY_ALGO_RSA) 105051dbb91SDmitry Kasatkin goto err1; 106051dbb91SDmitry Kasatkin 107051dbb91SDmitry Kasatkin if (pkh->nmpi != 2) 108051dbb91SDmitry Kasatkin goto err1; 109051dbb91SDmitry Kasatkin 110051dbb91SDmitry Kasatkin datap = pkh->mpi; 111f58a0815SDmitry Kasatkin endp = ukp->data + ukp->datalen; 112051dbb91SDmitry Kasatkin 113051dbb91SDmitry Kasatkin for (i = 0; i < pkh->nmpi; i++) { 114051dbb91SDmitry Kasatkin unsigned int remaining = endp - datap; 115051dbb91SDmitry Kasatkin pkey[i] = mpi_read_from_buffer(datap, &remaining); 11603cdfaadSNicolai Stange if (IS_ERR(pkey[i])) { 11703cdfaadSNicolai Stange err = PTR_ERR(pkey[i]); 11886f8bedcSDmitry Kasatkin goto err; 11903cdfaadSNicolai Stange } 120051dbb91SDmitry Kasatkin datap += remaining; 121051dbb91SDmitry Kasatkin } 122051dbb91SDmitry Kasatkin 123051dbb91SDmitry Kasatkin mblen = mpi_get_nbits(pkey[0]); 12426d43845SDmitry Kasatkin mlen = DIV_ROUND_UP(mblen, 8); 125051dbb91SDmitry Kasatkin 126c5ce7c69SNicolai Stange if (mlen == 0) { 127c5ce7c69SNicolai Stange err = -EINVAL; 128f58a0815SDmitry Kasatkin goto err; 129c5ce7c69SNicolai Stange } 130c5ce7c69SNicolai Stange 131c5ce7c69SNicolai Stange err = -ENOMEM; 132051dbb91SDmitry Kasatkin 133051dbb91SDmitry Kasatkin out1 = kzalloc(mlen, GFP_KERNEL); 134051dbb91SDmitry Kasatkin if (!out1) 135051dbb91SDmitry Kasatkin goto err; 136051dbb91SDmitry Kasatkin 137051dbb91SDmitry Kasatkin nret = siglen; 138051dbb91SDmitry Kasatkin in = mpi_read_from_buffer(sig, &nret); 13903cdfaadSNicolai Stange if (IS_ERR(in)) { 14003cdfaadSNicolai Stange err = PTR_ERR(in); 141051dbb91SDmitry Kasatkin goto err; 14203cdfaadSNicolai Stange } 143051dbb91SDmitry Kasatkin 144051dbb91SDmitry Kasatkin res = mpi_alloc(mpi_get_nlimbs(in) * 2); 145051dbb91SDmitry Kasatkin if (!res) 146051dbb91SDmitry Kasatkin goto err; 147051dbb91SDmitry Kasatkin 148051dbb91SDmitry Kasatkin err = mpi_powm(res, in, pkey[1], pkey[0]); 149051dbb91SDmitry Kasatkin if (err) 150051dbb91SDmitry Kasatkin goto err; 151051dbb91SDmitry Kasatkin 152051dbb91SDmitry Kasatkin if (mpi_get_nlimbs(res) * BYTES_PER_MPI_LIMB > mlen) { 153051dbb91SDmitry Kasatkin err = -EINVAL; 154051dbb91SDmitry Kasatkin goto err; 155051dbb91SDmitry Kasatkin } 156051dbb91SDmitry Kasatkin 157051dbb91SDmitry Kasatkin p = mpi_get_buffer(res, &l, NULL); 158051dbb91SDmitry Kasatkin if (!p) { 159051dbb91SDmitry Kasatkin err = -EINVAL; 160051dbb91SDmitry Kasatkin goto err; 161051dbb91SDmitry Kasatkin } 162051dbb91SDmitry Kasatkin 163051dbb91SDmitry Kasatkin len = mlen; 164051dbb91SDmitry Kasatkin head = len - l; 165051dbb91SDmitry Kasatkin memset(out1, 0, head); 166051dbb91SDmitry Kasatkin memcpy(out1 + head, p, l); 167051dbb91SDmitry Kasatkin 1687810cc1eSYOSHIFUJI Hideaki kfree(p); 1697810cc1eSYOSHIFUJI Hideaki 17026d43845SDmitry Kasatkin m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len); 171051dbb91SDmitry Kasatkin 17226d43845SDmitry Kasatkin if (!m || len != hlen || memcmp(m, h, hlen)) 173bc01637aSDmitry Kasatkin err = -EINVAL; 174051dbb91SDmitry Kasatkin 175051dbb91SDmitry Kasatkin err: 176051dbb91SDmitry Kasatkin mpi_free(in); 177051dbb91SDmitry Kasatkin mpi_free(res); 178051dbb91SDmitry Kasatkin kfree(out1); 17986f8bedcSDmitry Kasatkin while (--i >= 0) 18086f8bedcSDmitry Kasatkin mpi_free(pkey[i]); 181051dbb91SDmitry Kasatkin err1: 182051dbb91SDmitry Kasatkin up_read(&key->sem); 183051dbb91SDmitry Kasatkin 184051dbb91SDmitry Kasatkin return err; 185051dbb91SDmitry Kasatkin } 186051dbb91SDmitry Kasatkin 187051dbb91SDmitry Kasatkin /** 188051dbb91SDmitry Kasatkin * digsig_verify() - digital signature verification with public key 189051dbb91SDmitry Kasatkin * @keyring: keyring to search key in 190051dbb91SDmitry Kasatkin * @sig: digital signature 19154b14f40SFabian Frederick * @siglen: length of the signature 192051dbb91SDmitry Kasatkin * @data: data 193051dbb91SDmitry Kasatkin * @datalen: length of the data 19454b14f40SFabian Frederick * 19554b14f40SFabian Frederick * Returns 0 on success, -EINVAL otherwise 196051dbb91SDmitry Kasatkin * 197051dbb91SDmitry Kasatkin * Verifies data integrity against digital signature. 198051dbb91SDmitry Kasatkin * Currently only RSA is supported. 199051dbb91SDmitry Kasatkin * Normally hash of the content is used as a data for this function. 200051dbb91SDmitry Kasatkin * 201051dbb91SDmitry Kasatkin */ 202051dbb91SDmitry Kasatkin int digsig_verify(struct key *keyring, const char *sig, int siglen, 203051dbb91SDmitry Kasatkin const char *data, int datalen) 204051dbb91SDmitry Kasatkin { 205051dbb91SDmitry Kasatkin int err = -ENOMEM; 206051dbb91SDmitry Kasatkin struct signature_hdr *sh = (struct signature_hdr *)sig; 207051dbb91SDmitry Kasatkin struct shash_desc *desc = NULL; 208051dbb91SDmitry Kasatkin unsigned char hash[SHA1_DIGEST_SIZE]; 209051dbb91SDmitry Kasatkin struct key *key; 210051dbb91SDmitry Kasatkin char name[20]; 211051dbb91SDmitry Kasatkin 212051dbb91SDmitry Kasatkin if (siglen < sizeof(*sh) + 2) 213051dbb91SDmitry Kasatkin return -EINVAL; 214051dbb91SDmitry Kasatkin 215051dbb91SDmitry Kasatkin if (sh->algo != PUBKEY_ALGO_RSA) 216051dbb91SDmitry Kasatkin return -ENOTSUPP; 217051dbb91SDmitry Kasatkin 218051dbb91SDmitry Kasatkin sprintf(name, "%llX", __be64_to_cpup((uint64_t *)sh->keyid)); 219051dbb91SDmitry Kasatkin 220051dbb91SDmitry Kasatkin if (keyring) { 221051dbb91SDmitry Kasatkin /* search in specific keyring */ 222051dbb91SDmitry Kasatkin key_ref_t kref; 223051dbb91SDmitry Kasatkin kref = keyring_search(make_key_ref(keyring, 1UL), 224051dbb91SDmitry Kasatkin &key_type_user, name); 225051dbb91SDmitry Kasatkin if (IS_ERR(kref)) 226ff6092a8SDuan Jiong key = ERR_CAST(kref); 227051dbb91SDmitry Kasatkin else 228051dbb91SDmitry Kasatkin key = key_ref_to_ptr(kref); 229051dbb91SDmitry Kasatkin } else { 230051dbb91SDmitry Kasatkin key = request_key(&key_type_user, name, NULL); 231051dbb91SDmitry Kasatkin } 232051dbb91SDmitry Kasatkin if (IS_ERR(key)) { 233051dbb91SDmitry Kasatkin pr_err("key not found, id: %s\n", name); 234051dbb91SDmitry Kasatkin return PTR_ERR(key); 235051dbb91SDmitry Kasatkin } 236051dbb91SDmitry Kasatkin 237051dbb91SDmitry Kasatkin desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash), 238051dbb91SDmitry Kasatkin GFP_KERNEL); 239051dbb91SDmitry Kasatkin if (!desc) 240051dbb91SDmitry Kasatkin goto err; 241051dbb91SDmitry Kasatkin 242051dbb91SDmitry Kasatkin desc->tfm = shash; 243051dbb91SDmitry Kasatkin desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 244051dbb91SDmitry Kasatkin 245051dbb91SDmitry Kasatkin crypto_shash_init(desc); 246051dbb91SDmitry Kasatkin crypto_shash_update(desc, data, datalen); 247051dbb91SDmitry Kasatkin crypto_shash_update(desc, sig, sizeof(*sh)); 248051dbb91SDmitry Kasatkin crypto_shash_final(desc, hash); 249051dbb91SDmitry Kasatkin 250051dbb91SDmitry Kasatkin kfree(desc); 251051dbb91SDmitry Kasatkin 252051dbb91SDmitry Kasatkin /* pass signature mpis address */ 253051dbb91SDmitry Kasatkin err = digsig_verify_rsa(key, sig + sizeof(*sh), siglen - sizeof(*sh), 254051dbb91SDmitry Kasatkin hash, sizeof(hash)); 255051dbb91SDmitry Kasatkin 256051dbb91SDmitry Kasatkin err: 257051dbb91SDmitry Kasatkin key_put(key); 258051dbb91SDmitry Kasatkin 259051dbb91SDmitry Kasatkin return err ? -EINVAL : 0; 260051dbb91SDmitry Kasatkin } 261051dbb91SDmitry Kasatkin EXPORT_SYMBOL_GPL(digsig_verify); 262051dbb91SDmitry Kasatkin 263051dbb91SDmitry Kasatkin static int __init digsig_init(void) 264051dbb91SDmitry Kasatkin { 265051dbb91SDmitry Kasatkin shash = crypto_alloc_shash("sha1", 0, 0); 266051dbb91SDmitry Kasatkin if (IS_ERR(shash)) { 267051dbb91SDmitry Kasatkin pr_err("shash allocation failed\n"); 268051dbb91SDmitry Kasatkin return PTR_ERR(shash); 269051dbb91SDmitry Kasatkin } 270051dbb91SDmitry Kasatkin 271051dbb91SDmitry Kasatkin return 0; 272051dbb91SDmitry Kasatkin 273051dbb91SDmitry Kasatkin } 274051dbb91SDmitry Kasatkin 275051dbb91SDmitry Kasatkin static void __exit digsig_cleanup(void) 276051dbb91SDmitry Kasatkin { 277051dbb91SDmitry Kasatkin crypto_free_shash(shash); 278051dbb91SDmitry Kasatkin } 279051dbb91SDmitry Kasatkin 280051dbb91SDmitry Kasatkin module_init(digsig_init); 281051dbb91SDmitry Kasatkin module_exit(digsig_cleanup); 282051dbb91SDmitry Kasatkin 283051dbb91SDmitry Kasatkin MODULE_LICENSE("GPL"); 284