summaryrefslogtreecommitdiff
path: root/lib/nettle/int/rsa-pad.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nettle/int/rsa-pad.c')
-rw-r--r--lib/nettle/int/rsa-pad.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/nettle/int/rsa-pad.c b/lib/nettle/int/rsa-pad.c
new file mode 100644
index 0000000000..401bad33f7
--- /dev/null
+++ b/lib/nettle/int/rsa-pad.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of 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 "gnutls_int.h"
+
+#include <nettle/pkcs1.h>
+#include <nettle/pss.h>
+#include <nettle/sha2.h>
+
+/* These are helper functions to perform RSA padding before signing, only used
+ * for the crypto backends that do not support RSA-PKCS1/PSS natively for the
+ * use with TLS (such as TPM2); not recommended for general usage.
+ */
+
+int
+_gnutls_rsa_pkcs1_sign_pad(size_t key_bits,
+ const gnutls_datum_t *data,
+ unsigned char *buffer, size_t buffer_size)
+{
+ size_t key_size = (key_bits + 7) / 8;
+ size_t size;
+ mpz_t m;
+ int ret = 0;
+
+ mpz_init(m);
+ if (!pkcs1_rsa_digest_encode(m, key_size, data->size, data->data)) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+ goto out;
+ }
+
+ size = nettle_mpz_sizeinbase_256_u(m);
+ if (size > buffer_size) {
+ ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ goto out;
+ }
+ nettle_mpz_get_str_256(buffer_size, buffer, m);
+
+ out:
+ mpz_clear(m);
+ return ret;
+}
+
+int
+_gnutls_rsa_pss_sign_pad(gnutls_x509_spki_st *params,
+ size_t key_bits,
+ const gnutls_datum_t *data,
+ unsigned char *buffer, size_t buffer_size)
+{
+ mpz_t m;
+ int ret = 0;
+ const struct nettle_hash *hash;
+ uint8_t salt[SHA512_DIGEST_SIZE];
+ size_t size;
+
+ mpz_init(m);
+
+ switch (params->rsa_pss_dig) {
+ case GNUTLS_DIG_SHA256:
+ hash = &nettle_sha256;
+ break;
+ case GNUTLS_DIG_SHA384:
+ hash = &nettle_sha384;
+ break;
+ case GNUTLS_DIG_SHA512:
+ hash = &nettle_sha512;
+ break;
+ default:
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto out;
+ }
+
+ if (data->size != hash->digest_size) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto out;
+ }
+
+ ret = gnutls_rnd(GNUTLS_RND_NONCE, salt, params->salt_size);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* The emBits for EMSA-PSS encoding is actually one *fewer*
+ * bit than the RSA modulus. */
+ if (!pss_encode_mgf1(m, key_bits - 1, hash, params->salt_size, salt,
+ data->data)) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+ goto out;
+ }
+
+ size = nettle_mpz_sizeinbase_256_u(m);
+ if (size > buffer_size) {
+ ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ goto out;
+ }
+ nettle_mpz_get_str_256(buffer_size, buffer, m);
+
+ out:
+ mpz_clear(m);
+ return ret;
+}