3 PKCS#1 RSA-PSS padding (RFC-3447).
5 Copyright (C) 2017 Daiki Ueno
7 This file is part of GNU Nettle.
9 GNU Nettle is free software: you can redistribute it and/or
10 modify it under the terms of either:
12 * the GNU Lesser General Public License as published by the Free
13 Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
18 * the GNU General Public License as published by the Free
19 Software Foundation; either version 2 of the License, or (at your
20 option) any later version.
22 or both in parallel, as here.
24 GNU Nettle is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 General Public License for more details.
29 You should have received copies of the GNU General Public License and
30 the GNU Lesser General Public License along with this program. If
31 not, see http://www.gnu.org/licenses/.
48 #include "nettle-internal.h"
50 /* Masks to clear the leftmost N bits. */
51 static const uint8_t pss_masks[8] = {
52 0xFF, 0x7F, 0x3F, 0x1F, 0xF, 0x7, 0x3, 0x1
55 /* Format the PKCS#1 PSS padding for given salt and digest, using
56 * pss_mgf1() as the mask generation function.
58 * The encoded messsage is stored in M, and the consistency can be
59 * checked with pss_verify_mgf1(), which takes the encoded message,
60 * the length of salt, and the digest. */
62 pss_encode_mgf1(mpz_t m, size_t bits,
63 const struct nettle_hash *hash,
64 size_t salt_length, const uint8_t *salt,
65 const uint8_t *digest)
67 TMP_GMP_DECL(em, uint8_t);
68 TMP_DECL(state, uint8_t, NETTLE_MAX_HASH_CONTEXT_SIZE);
70 size_t key_size = (bits + 7) / 8;
73 TMP_GMP_ALLOC(em, key_size);
74 TMP_ALLOC(state, hash->context_size);
76 if (key_size < hash->digest_size + salt_length + 2)
85 hash->update(state, 8, pad);
86 hash->update(state, hash->digest_size, digest);
87 hash->update(state, salt_length, salt);
89 /* Store H in EM, right after maskedDB. */
90 hash->digest(state, hash->digest_size, em + key_size - hash->digest_size - 1);
94 hash->update(state, hash->digest_size, em + key_size - hash->digest_size - 1);
96 pss_mgf1(state, hash, key_size - hash->digest_size - 1, em);
98 /* Compute maskedDB and store it in front of H in EM. */
99 for (j = 0; j < key_size - salt_length - hash->digest_size - 2; j++)
102 memxor(em + j, salt, salt_length);
105 /* Store the trailer field following H. */
106 j += hash->digest_size;
109 /* Clear the leftmost 8 * emLen - emBits of the leftmost octet in EM. */
110 *em &= pss_masks[(8 * key_size - bits)];
112 nettle_mpz_set_str_256_u(m, key_size, em);
117 /* Check the consistency of given PKCS#1 PSS encoded message, created
118 * with pss_encode_mgf1().
120 * Returns 1 if the encoded message is consistent, 0 if it is
123 pss_verify_mgf1(mpz_t m, size_t bits,
124 const struct nettle_hash *hash,
126 const uint8_t *digest)
128 TMP_GMP_DECL(em, uint8_t);
129 TMP_DECL(h2, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
130 TMP_DECL(state, uint8_t, NETTLE_MAX_HASH_CONTEXT_SIZE);
131 uint8_t pad[8], *h, *db, *salt;
132 size_t key_size = (bits + 7) / 8;
136 /* Allocate twice the key size to store the intermediate data DB
137 * following the EM value. */
138 TMP_GMP_ALLOC(em, key_size * 2);
140 TMP_ALLOC(h2, hash->digest_size);
141 TMP_ALLOC(state, hash->context_size);
143 if (key_size < hash->digest_size + salt_length + 2)
146 nettle_mpz_get_str_256(key_size, em, m);
148 /* Check the trailer field. */
149 if (em[key_size - 1] != 0xbc)
153 h = em + (key_size - hash->digest_size - 1);
155 /* Check if the leftmost 8 * emLen - emBits bits of the leftmost
156 * octet of EM are all equal to zero. */
157 if ((*em & ~pss_masks[(8 * key_size - bits)]) != 0)
160 /* Compute dbMask. */
162 hash->update(state, hash->digest_size, h);
165 pss_mgf1(state, hash, key_size - hash->digest_size - 1, db);
168 memxor(db, em, key_size - hash->digest_size - 1);
170 *db &= pss_masks[(8 * key_size - bits)];
171 for (j = 0; j < key_size - salt_length - hash->digest_size - 2; j++)
175 /* Check the octet right after PS is 0x1. */
183 hash->update(state, 8, pad);
184 hash->update(state, hash->digest_size, digest);
185 hash->update(state, salt_length, salt);
186 hash->digest(state, hash->digest_size, h2);
188 /* Check if H' = H. */
189 if (memcmp(h2, h, hash->digest_size) != 0)