1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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;
}
|