|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 2/4] crypto: Add RSA support
On Mon, May 12, 2025 at 1:38 PM Jan Beulich <jbeulich@xxxxxxxx> wrote:
>
> On 06.05.2025 16:32, Ross Lagerwall wrote:
> > In preparation for adding support for livepatch signing, add support for
> > RSA crypto.
>
> If this is needed just for live-patch, ...
>
> > --- a/xen/common/Makefile
> > +++ b/xen/common/Makefile
> > @@ -28,6 +28,7 @@ obj-$(CONFIG_LIVEPATCH) += livepatch.o livepatch_elf.o
> > obj-$(CONFIG_LLC_COLORING) += llc-coloring.o
> > obj-$(CONFIG_VM_EVENT) += mem_access.o
> > obj-y += memory.o
> > +obj-y += mpi.o
>
> ... why would this be obj-y? Same for rsa.o further down.
>
> > --- /dev/null
> > +++ b/xen/common/mpi.c
> > @@ -0,0 +1,1724 @@
> > +/* mpi-pow.c - MPI functions
>
> Nit: This doesn't match the filename.
>
> > + * Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc.
> > + *
> > + * This file is part of GnuPG.
> > + *
> > + * GnuPG 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 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * GnuPG 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 this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
> > USA
> > + *
> > + * Note: This code is heavily based on the GNU MP Library.
> > + * Actually it's the same code with only minor changes in the
> > + * way the data is stored; this is to support the abstraction
> > + * of an optional secure memory allocation which may be used
> > + * to avoid revealing of sensitive data due to paging etc.
> > + * The GNU MP Library itself is published under the LGPL;
> > + * however I decided to publish this code under the plain GPL.
> > + *
> > + * mpi.c code extracted from linux @ eef0df6a5953, lib/mpi
>
> I fear this line would go unnoticed with future changes, and hence go stale
> rather easily. Menioning the origin in just the commit message ought to be
> sufficient.
>
> Btw - how heavily did you need to adjust the code to pass our Eclair scan?
> Depending on that I then might raise the question of converting to proper
> Xen style (it currently isn't even proper Linux style, afaict).
Few changes were needed to the code in this file so I preferred to keep
it in the original style.
Since a lot more adjustments were made to rsa.c, I opted to change that
to the Xen style.
>
> > + */
> > +
> > +#include <xen/mpi.h>
> > +#include <xen/lib.h>
> > +#include <xen/err.h>
> > +#include <xen/xmalloc.h>
> > +#include <xen/string.h>
> > +#include <xen/bitops.h>
> > +#include <xen/bug.h>
>
> Please sort alphabetically. Same for the other new files.
>
> > +#define MAX_EXTERN_MPI_BITS 16384
> > +
> > +/* Define it to a value which is good on most machines.
> > + * tested 4, 16, 32 and 64, where 16 gave the best performance when
> > + * checking a 768 and a 1024 bit ElGamal signature.
> > + * (wk 22.12.97) */
> > +#define KARATSUBA_THRESHOLD 16
> > +
> > +typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */
> > +typedef int mpi_size_t; /* (must be a signed type) */
> > +
> > +/* Copy N limbs from S to D. */
> > +#define MPN_COPY(d, s, n) \
> > + do { \
> > + mpi_size_t _i; \
>
> With this and ...
>
> > + for (_i = 0; _i < (n); _i++) \
> > + (d)[_i] = (s)[_i]; \
> > + } while (0)
> > +
> > +#define MPN_COPY_DECR(d, s, n) \
> > + do { \
> > + mpi_size_t _i; \
>
> ... this I wonder why ...
>
> > + for (_i = (n)-1; _i >= 0; _i--) \
> > + (d)[_i] = (s)[_i]; \
> > + } while (0)
> > +
> > +/* Zero N limbs at D */
> > +#define MPN_ZERO(d, n) \
> > + do { \
> > + int _i; \
>
> ... this is plain int. There are apparently many similar issue.
>
> >[...]
> > +leave:
>
> Here and elsewhere - labels indented by at least one blank, please.
>
> > --- /dev/null
> > +++ b/xen/crypto/rsa.c
> > @@ -0,0 +1,194 @@
> > +/* rsa.c
> > +
> > + The RSA publickey algorithm.
> > +
> > + Copyright (C) 2001 Niels Möller
> > +
> > + This file is part of GNU Nettle.
> > +
> > + GNU Nettle is free software: you can redistribute it and/or
> > + modify it under the terms of either:
> > +
> > + * the GNU Lesser General Public License as published by the Free
> > + Software Foundation; either version 3 of the License, or (at your
> > + option) any later version.
> > +
> > + or
> > +
> > + * the GNU General Public License as published by the Free
> > + Software Foundation; either version 2 of the License, or (at your
> > + option) any later version.
> > +
> > + or both in parallel, as here.
> > +
> > + GNU Nettle 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 copies of the GNU General Public License and
> > + the GNU Lesser General Public License along with this program. If
> > + not, see http://www.gnu.org/licenses/.
> > +*/
> > +
> > +#include <xen/rsa.h>
> > +#include <xen/lib.h>
> > +#include <xen/err.h>
> > +#include <xen/bug.h>
> > +#include <xen/string.h>
> > +
> > +void rsa_public_key_init(struct rsa_public_key *key)
> > +{
> > + key->n = NULL;
> > + key->e = NULL;
> > + key->size = 0;
> > +}
> > +
> > +/*
> > + * Computes the size, in octets, of the modulo. Returns 0 if the
> > + * modulo is too small to be useful, or otherwise appears invalid.
> > + */
> > +static size_t rsa_check_size(MPI n)
> > +{
> > + /* Round upwards */
> > + size_t size;
> > +
> > + /* Even moduli are invalid */
> > + if ( mpi_test_bit(n, 0) == 0 )
> > + return 0;
> > +
> > + size = (mpi_get_nbits(n) + 7) / 8;
> > +
> > + if ( size < RSA_MINIMUM_N_OCTETS )
> > + return 0;
> > +
> > + return size;
> > +}
> > +
> > +int rsa_public_key_prepare(struct rsa_public_key *key)
> > +{
> > + if ( !key->n || !key->e || key->size )
> > + return -EINVAL;
> > +
> > + key->size = rsa_check_size(key->n);
> > +
> > + return key->size > 0 ? 0 : -EINVAL;
> > +}
> > +
> > +/*
> > + * Formats the PKCS#1 padding, of the form
> > + *
> > + * 0x00 0x01 0xff ... 0xff 0x00 id ...digest...
> > + *
> > + * where the 0xff ... 0xff part consists of at least 8 octets. The
> > + * total size equals the octet size of n.
> > + */
> > +static uint8_t *pkcs1_signature_prefix(unsigned int key_size, uint8_t
> > *buffer,
> > + unsigned int id_size, const uint8_t
> > *id,
> > + unsigned int digest_size)
> > +{
> > + unsigned int j;
> > +
> > + if ( key_size < 11 + id_size + digest_size )
> > + return NULL;
> > +
> > + j = key_size - digest_size - id_size;
> > +
> > + memcpy(buffer + j, id, id_size);
> > + buffer[0] = 0;
> > + buffer[1] = 1;
> > + buffer[j - 1] = 0;
> > +
> > + ASSERT(j >= 11);
> > + memset(buffer + 2, 0xff, j - 3);
> > +
> > + return buffer + j + id_size;
> > +}
> > +
> > +/*
> > + * From RFC 3447, Public-Key Cryptography Standards (PKCS) #1: RSA
> > + * Cryptography Specifications Version 2.1.
> > + *
> > + * id-sha256 OBJECT IDENTIFIER ::=
> > + * {joint-iso-itu-t(2) country(16) us(840) organization(1)
> > + * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1}
> > + */
> > +static const uint8_t
> > +sha256_prefix[] =
> > +{
> > + /* 19 octets prefix, 32 octets hash, total 51 */
> > + 0x30, 49, /* SEQUENCE */
> > + 0x30, 13, /* SEQUENCE */
> > + 0x06, 9, /* OBJECT IDENTIFIER */
> > + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
> > + 0x05, 0, /* NULL */
> > + 0x04, 32 /* OCTET STRING */
> > + /* Here comes the raw hash value */
> > +};
> > +
> > +static int pkcs1_rsa_sha256_encode(MPI *m, size_t key_size,
> > + struct sha2_256_state *hash)
> > +{
> > + uint8_t *ptr;
> > + uint8_t *buf;
> > +
> > + buf = xmalloc_bytes(key_size);
> > + if ( !buf )
> > + return -ENOMEM;
> > +
> > + ptr = pkcs1_signature_prefix(key_size, buf,
> > + sizeof(sha256_prefix), sha256_prefix,
> > + SHA2_256_DIGEST_SIZE);
> > + if ( !ptr )
> > + {
> > + xfree(buf);
> > + return -EINVAL;
> > + }
> > +
> > + sha2_256_final(hash, ptr);
> > + *m = mpi_read_raw_data(buf, key_size);
> > + xfree(buf);
> > + return 0;
> > +}
> > +
> > +static int rsa_verify(const struct rsa_public_key *key, MPI m, MPI s)
> > +{
> > + int ret;
> > + MPI m1;
> > +
> > + /* (1) Validate 0 <= s < n */
> > + if ( mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0 )
> > + return -EINVAL;
> > +
> > + m1 = mpi_alloc(key->size / BYTES_PER_MPI_LIMB);
> > + if ( !m1 )
> > + return -ENOMEM;
> > +
> > + /* (2) m = s^e mod n */
> > + ret = mpi_powm(m1, s, key->e, key->n);
> > + if ( ret )
> > + goto out;
> > +
> > + ret = mpi_cmp (m, m1) ? -EINVAL : 0;
>
> You look to have striven to convert this file to Xen style; there's a stray
> blank here, though.
>
> > --- /dev/null
> > +++ b/xen/include/xen/mpi.h
> > @@ -0,0 +1,63 @@
> > +/* mpi.h - Multi Precision Integers
> > + * Copyright (C) 1994, 1996, 1998, 1999,
> > + * 2000, 2001 Free Software Foundation, Inc.
> > + *
> > + * This file is part of GNUPG.
> > + *
> > + * GNUPG 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 2 of the License, or
> > + * (at your option) any later version.
>
> While this may want to remain, accompany it with an SPDX header? (Same
> elsewhere perhaps.)
Sure.
>
> > + * GNUPG 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 this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
> > USA
> > + *
> > + * Note: This code is heavily based on the GNU MP Library.
> > + * Actually it's the same code with only minor changes in the
> > + * way the data is stored; this is to support the abstraction
> > + * of an optional secure memory allocation which may be used
> > + * to avoid revealing of sensitive data due to paging etc.
> > + * The GNU MP Library itself is published under the LGPL;
> > + * however I decided to publish this code under the plain GPL.
> > + */
> > +
> > +#ifndef MPI_H
> > +#define MPI_H
>
> This imo wants at least a XEN_ prefix. Same in rsa.h.
>
> > +#include <xen/types.h>
> > +
> > +#define BYTES_PER_MPI_LIMB (BITS_PER_LONG / 8)
> > +#define BITS_PER_MPI_LIMB BITS_PER_LONG
> > +
> > +typedef unsigned long int mpi_limb_t;
> > +typedef signed long int mpi_limb_signed_t;
> > +
> > +struct mpi {
> > + int alloced; /* array size (# of allocated limbs) */
> > + int nlimbs; /* number of valid limbs */
> > + int nbits; /* the real number of valid bits (info only) */
>
> I understand the goal likely is to not meaningfully change the original, but
> none of these look like they can hold negative values, and ...
>
> > + int sign; /* indicates a negative number */
>
> ... this one looks like it's a boolean.
>
> > + unsigned flags; /* bit 0: array must be allocated in secure memory
> > space */
>
> In Xen we use "unsigned int", not plain "unsigned".
I'd prefer not to change the type from int to something else but I'll
fix the unsigned style issue.
Ross
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |