From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Thu, 1 Oct 2020 20:23:48 +1000 Subject: [PATCH] pgp: factor out rsa_pad rsa_pad does the PKCS#1 v1.5 padding for the RSA signature scheme. We want to use it in other RSA signature verification applications. I considered and rejected putting it in lib/crypto.c. That file doesn't currently require any MPI functions, but rsa_pad does. That's not so much of a problem for the grub kernel and modules, but crypto.c also gets built into all the grub utilities. So - despite the utils not using any asymmetric ciphers - we would need to built the entire MPI infrastructure in to them. A better and simpler solution is just to spin rsa_pad out into its own PKCS#1 v1.5 module. Signed-off-by: Daniel Axtens --- grub-core/Makefile.core.def | 8 ++++++ grub-core/commands/pgp.c | 28 ++------------------- grub-core/lib/pkcs1_v15.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ include/grub/pkcs1_v15.h | 27 +++++++++++++++++++++ 4 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 grub-core/lib/pkcs1_v15.c create mode 100644 include/grub/pkcs1_v15.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 81fc27414..97347ae76 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -2510,6 +2510,14 @@ module = { cppflags = '$(CPPFLAGS_GCRY)'; }; +module = { + name = pkcs1_v15; + common = lib/pkcs1_v15.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + module = { name = all_video; common = lib/fake_module.c; diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c index 5daa1e9d0..2408db499 100644 --- a/grub-core/commands/pgp.c +++ b/grub-core/commands/pgp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -411,32 +412,7 @@ static int rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, const gcry_md_spec_t *hash, struct grub_public_subkey *sk) { - grub_size_t tlen, emlen, fflen; - grub_uint8_t *em, *emptr; - unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]); - int ret; - tlen = hash->mdlen + hash->asnlen; - emlen = (nbits + 7) / 8; - if (emlen < tlen + 11) - return 1; - - em = grub_malloc (emlen); - if (!em) - return 1; - - em[0] = 0x00; - em[1] = 0x01; - fflen = emlen - tlen - 3; - for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) - *emptr = 0xff; - *emptr++ = 0x00; - grub_memcpy (emptr, hash->asnoid, hash->asnlen); - emptr += hash->asnlen; - grub_memcpy (emptr, hval, hash->mdlen); - - ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); - grub_free (em); - return ret; + return grub_crypto_rsa_pad(hmpi, hval, hash, sk->mpis[0]); } struct grub_pubkey_context diff --git a/grub-core/lib/pkcs1_v15.c b/grub-core/lib/pkcs1_v15.c new file mode 100644 index 000000000..dbacd563d --- /dev/null +++ b/grub-core/lib/pkcs1_v15.c @@ -0,0 +1,59 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* + * Given a hash value 'hval', of hash specification 'hash', perform + * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod' + * (see RFC 8017 s 9.2) and place the result in 'hmpi'. + */ +gcry_err_code_t +grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval, + const gcry_md_spec_t * hash, gcry_mpi_t mod) +{ + grub_size_t tlen, emlen, fflen; + grub_uint8_t *em, *emptr; + unsigned nbits = gcry_mpi_get_nbits (mod); + int ret; + tlen = hash->mdlen + hash->asnlen; + emlen = (nbits + 7) / 8; + if (emlen < tlen + 11) + return GPG_ERR_TOO_SHORT; + + em = grub_malloc (emlen); + if (!em) + return 1; + + em[0] = 0x00; + em[1] = 0x01; + fflen = emlen - tlen - 3; + for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) + *emptr = 0xff; + *emptr++ = 0x00; + grub_memcpy (emptr, hash->asnoid, hash->asnlen); + emptr += hash->asnlen; + grub_memcpy (emptr, hval, hash->mdlen); + + ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); + grub_free (em); + return ret; +} diff --git a/include/grub/pkcs1_v15.h b/include/grub/pkcs1_v15.h new file mode 100644 index 000000000..5c338c84a --- /dev/null +++ b/include/grub/pkcs1_v15.h @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* + * Given a hash value 'hval', of hash specification 'hash', perform + * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod' + * (See RFC 8017 s 9.2) + */ +gcry_err_code_t +grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval, + const gcry_md_spec_t * hash, gcry_mpi_t mod); +