Commit cf43ded0 authored by Daiki Ueno's avatar Daiki Ueno

Add PSS variants for RSA sign/verify functions

Signed-off-by: default avatarDaiki Ueno <dueno@redhat.com>
parent 7d16432b
......@@ -151,6 +151,8 @@ hogweed_SOURCES = sexp.c sexp-format.c \
rsa-sha1-sign.c rsa-sha1-sign-tr.c rsa-sha1-verify.c \
rsa-sha256-sign.c rsa-sha256-sign-tr.c rsa-sha256-verify.c \
rsa-sha512-sign.c rsa-sha512-sign-tr.c rsa-sha512-verify.c \
rsa-pss-sha256-sign-tr.c rsa-pss-sha256-verify.c \
rsa-pss-sha512-sign-tr.c rsa-pss-sha512-verify.c \
rsa-encrypt.c rsa-decrypt.c rsa-decrypt-tr.c \
rsa-keygen.c rsa-blind.c \
rsa2sexp.c sexp2rsa.c \
......
......@@ -3770,6 +3770,43 @@ of the digest together with an object identifier for the used hash
algorithm.
@end deftypefun
While the above functions for the RSA signature operations use the
@cite{PKCS#1} padding scheme, Nettle also provides the variants based on
the PSS padding scheme, specified in @cite{RFC 3447}. These variants
take advantage of a randomly choosen salt value, which could enhance the
security by causing output to be different for equivalent inputs.
However, assuming the same security level as inverting the @acronym{RSA}
algorithm, a longer salt value does not always mean a better security
@uref{http://www.iacr.org/archive/eurocrypt2002/23320268/coron.pdf}.
The typical choices of the length are between 0 and the digest size of
the underlying hash function.
Creating an RSA signature with the PSS padding scheme is done with one
of the following functions:
@deftypefun int rsa_pss_sha256_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{salt_length}, const uint8_t *@var{salt}, const uint8_t *@var{digest}, mpz_t @var{signature})
@deftypefunx int rsa_pss_sha384_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{salt_length}, const uint8_t *@var{salt}, const uint8_t *@var{digest}, mpz_t @var{signature})
@deftypefunx int rsa_pss_sha512_sign_digest_tr(const struct rsa_public_key *@var{pub}, const struct rsa_private_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{salt_length}, const uint8_t *@var{salt}, const uint8_t *@var{digest}, mpz_t @var{signature})
Creates a signature using the PSS padding scheme. @var{salt} should
point to a salt string of size @var{salt_length}. @var{digest} should
point to a digest of size @code{SHA256_DIGEST_SIZE},
@code{SHA384_DIGEST_SIZE}, or @code{SHA512_DIGEST_SIZE}respectively. The
signature is stored in @var{signature} (which must have been
@code{mpz_init}:ed earlier).
Returns one on success, or zero on failure.
@end deftypefun
Verifying an RSA signature with the PSS padding scheme is done with one
of the following functions:
@deftypefun int rsa_pss_sha256_verify_digest (const struct rsa_public_key *@var{key}, size_t @var{salt_length}, const uint8_t *@var{digest}, const mpz_t @var{signature})
@deftypefunx int rsa_pss_sha384_verify_digest (const struct rsa_public_key *@var{key}, size_t @var{salt_length}, const uint8_t *@var{digest}, const mpz_t @var{signature})
@deftypefunx int rsa_pss_sha512_verify_digest (const struct rsa_public_key *@var{key}, size_t @var{salt_length}, const uint8_t *@var{digest}, const mpz_t @var{signature})
Returns 1 if the signature is valid, or 0 if it isn't. @var{digest}
should point to a digest of size @code{SHA256_DIGEST_SIZE},
@code{SHA384_DIGEST_SIZE}, or @code{SHA512_DIGEST_SIZE} respectively.
@end deftypefun
The following function is used to encrypt a clear text message using RSA.
@deftypefun int rsa_encrypt (const struct rsa_public_key *@var{key}, void *@var{random_ctx}, nettle_random_func *@var{random}, size_t @var{length}, const uint8_t *@var{cleartext}, mpz_t @var{ciphertext})
Returns 1 on success, 0 on failure. If the message is too long then this
......
/* rsa-pss-sha256-sign-tr.c
Signatures using RSA and SHA-256, with PSS padding.
Copyright (C) 2017 Daiki Ueno
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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "rsa.h"
#include "bignum.h"
#include "pss.h"
int
rsa_pss_sha256_sign_digest_tr(const struct rsa_public_key *pub,
const struct rsa_private_key *key,
void *random_ctx, nettle_random_func *random,
size_t salt_length, const uint8_t *salt,
const uint8_t *digest,
mpz_t s)
{
mpz_t m;
int res;
mpz_init (m);
res = (pss_encode_mgf1(m, mpz_sizeinbase(pub->n, 2) - 1, &nettle_sha256,
salt_length, salt, digest)
&& rsa_compute_root_tr (pub, key,
random_ctx, random,
s, m));
mpz_clear (m);
return res;
}
/* rsa-pss-sha256-verify.c
Verifying signatures created with RSA and SHA-256, with PSS padding.
Copyright (C) 2017 Daiki Ueno
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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "rsa.h"
#include "bignum.h"
#include "pss.h"
int
rsa_pss_sha256_verify_digest(const struct rsa_public_key *key,
size_t salt_length,
const uint8_t *digest,
const mpz_t signature)
{
int res;
mpz_t m;
mpz_init (m);
res = (_rsa_verify_recover(key, m, signature) &&
pss_verify_mgf1(m, mpz_sizeinbase(key->n, 2) - 1, &nettle_sha256,
salt_length, digest));
mpz_clear (m);
return res;
}
/* rsa-pss-sha512-sign-tr.c
Signatures using RSA and SHA-384/SHA-512, with PSS padding.
Copyright (C) 2017 Daiki Ueno
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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "rsa.h"
#include "bignum.h"
#include "pss.h"
int
rsa_pss_sha384_sign_digest_tr(const struct rsa_public_key *pub,
const struct rsa_private_key *key,
void *random_ctx, nettle_random_func *random,
size_t salt_length, const uint8_t *salt,
const uint8_t *digest,
mpz_t s)
{
mpz_t m;
int res;
mpz_init (m);
res = (pss_encode_mgf1(m, mpz_sizeinbase(pub->n, 2) - 1, &nettle_sha384,
salt_length, salt, digest)
&& rsa_compute_root_tr (pub, key,
random_ctx, random,
s, m));
mpz_clear (m);
return res;
}
int
rsa_pss_sha512_sign_digest_tr(const struct rsa_public_key *pub,
const struct rsa_private_key *key,
void *random_ctx, nettle_random_func *random,
size_t salt_length, const uint8_t *salt,
const uint8_t *digest,
mpz_t s)
{
mpz_t m;
int res;
mpz_init (m);
res = (pss_encode_mgf1(m, mpz_sizeinbase(pub->n, 2) - 1, &nettle_sha512,
salt_length, salt, digest)
&& rsa_compute_root_tr (pub, key,
random_ctx, random,
s, m));
mpz_clear (m);
return res;
}
/* rsa-pss-sha512-verify.c
Verifying signatures created with RSA and SHA-384/SHA-512, with PSS padding.
Copyright (C) 2017 Daiki Ueno
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/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "rsa.h"
#include "bignum.h"
#include "pss.h"
int
rsa_pss_sha384_verify_digest(const struct rsa_public_key *key,
size_t salt_length,
const uint8_t *digest,
const mpz_t signature)
{
int res;
mpz_t m;
mpz_init (m);
res = (_rsa_verify_recover(key, m, signature) &&
pss_verify_mgf1(m, mpz_sizeinbase(key->n, 2) - 1, &nettle_sha384,
salt_length, digest));
mpz_clear (m);
return res;
}
int
rsa_pss_sha512_verify_digest(const struct rsa_public_key *key,
size_t salt_length,
const uint8_t *digest,
const mpz_t signature)
{
int res;
mpz_t m;
mpz_init (m);
res = (_rsa_verify_recover(key, m, signature) &&
pss_verify_mgf1(m, mpz_sizeinbase(key->n, 2) - 1, &nettle_sha512,
salt_length, digest));
mpz_clear (m);
return res;
}
......@@ -62,3 +62,17 @@ _rsa_verify(const struct rsa_public_key *key,
return res;
}
int
_rsa_verify_recover(const struct rsa_public_key *key,
mpz_t m,
const mpz_t s)
{
if ( (mpz_sgn(s) <= 0)
|| (mpz_cmp(s, key->n) >= 0) )
return 0;
mpz_powm(m, s, key->e, key->n);
return 1;
}
......@@ -79,6 +79,12 @@ extern "C" {
#define rsa_sha512_sign_digest nettle_rsa_sha512_sign_digest
#define rsa_sha512_sign_digest_tr nettle_rsa_sha512_sign_digest_tr
#define rsa_sha512_verify_digest nettle_rsa_sha512_verify_digest
#define rsa_pss_sha256_sign_digest_tr nettle_rsa_pss_sha256_sign_digest_tr
#define rsa_pss_sha256_verify_digest nettle_rsa_pss_sha256_verify_digest
#define rsa_pss_sha384_sign_digest_tr nettle_rsa_pss_sha384_sign_digest_tr
#define rsa_pss_sha384_verify_digest nettle_rsa_pss_sha384_verify_digest
#define rsa_pss_sha512_sign_digest_tr nettle_rsa_pss_sha512_sign_digest_tr
#define rsa_pss_sha512_verify_digest nettle_rsa_pss_sha512_verify_digest
#define rsa_encrypt nettle_rsa_encrypt
#define rsa_decrypt nettle_rsa_decrypt
#define rsa_decrypt_tr nettle_rsa_decrypt_tr
......@@ -93,6 +99,7 @@ extern "C" {
#define rsa_keypair_from_der nettle_rsa_keypair_from_der
#define rsa_keypair_to_openpgp nettle_rsa_keypair_to_openpgp
#define _rsa_verify _nettle_rsa_verify
#define _rsa_verify_recover _nettle_rsa_verify_recover
#define _rsa_check_size _nettle_rsa_check_size
#define _rsa_blind _nettle_rsa_blind
#define _rsa_unblind _nettle_rsa_unblind
......@@ -341,6 +348,49 @@ rsa_sha512_verify_digest(const struct rsa_public_key *key,
const uint8_t *digest,
const mpz_t signature);
/* PSS style signatures */
int
rsa_pss_sha256_sign_digest_tr(const struct rsa_public_key *pub,
const struct rsa_private_key *key,
void *random_ctx, nettle_random_func *random,
size_t salt_length, const uint8_t *salt,
const uint8_t *digest,
mpz_t s);
int
rsa_pss_sha256_verify_digest(const struct rsa_public_key *key,
size_t salt_length,
const uint8_t *digest,
const mpz_t signature);
int
rsa_pss_sha384_sign_digest_tr(const struct rsa_public_key *pub,
const struct rsa_private_key *key,
void *random_ctx, nettle_random_func *random,
size_t salt_length, const uint8_t *salt,
const uint8_t *digest,
mpz_t s);
int
rsa_pss_sha384_verify_digest(const struct rsa_public_key *key,
size_t salt_length,
const uint8_t *digest,
const mpz_t signature);
int
rsa_pss_sha512_sign_digest_tr(const struct rsa_public_key *pub,
const struct rsa_private_key *key,
void *random_ctx, nettle_random_func *random,
size_t salt_length, const uint8_t *salt,
const uint8_t *digest,
mpz_t s);
int
rsa_pss_sha512_verify_digest(const struct rsa_public_key *key,
size_t salt_length,
const uint8_t *digest,
const mpz_t signature);
/* RSA encryption, using PKCS#1 */
/* These functions uses the v1.5 padding. What should the v2 (OAEP)
......@@ -480,6 +530,11 @@ _rsa_verify(const struct rsa_public_key *key,
const mpz_t m,
const mpz_t s);
int
_rsa_verify_recover(const struct rsa_public_key *key,
mpz_t m,
const mpz_t s);
size_t
_rsa_check_size(mpz_t n);
......
......@@ -187,6 +187,9 @@ pss-test$(EXEEXT): pss-test.$(OBJEXT)
rsa-sign-tr-test$(EXEEXT): rsa-sign-tr-test.$(OBJEXT)
$(LINK) rsa-sign-tr-test.$(OBJEXT) $(TEST_OBJS) -o rsa-sign-tr-test$(EXEEXT)
rsa-pss-sign-tr-test$(EXEEXT): rsa-pss-sign-tr-test.$(OBJEXT)
$(LINK) rsa-pss-sign-tr-test.$(OBJEXT) $(TEST_OBJS) -o rsa-pss-sign-tr-test$(EXEEXT)
rsa-test$(EXEEXT): rsa-test.$(OBJEXT)
$(LINK) rsa-test.$(OBJEXT) $(TEST_OBJS) -o rsa-test$(EXEEXT)
......
......@@ -36,6 +36,7 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
rsa2sexp-test.c sexp2rsa-test.c \
bignum-test.c random-prime-test.c \
pkcs1-test.c pss-test.c rsa-sign-tr-test.c \
rsa-pss-sign-tr-test.c \
rsa-test.c rsa-encrypt-test.c rsa-keygen-test.c \
dsa-test.c dsa-keygen-test.c \
curve25519-dh-test.c \
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment