Implement PSS encoding functions
[gd/nettle] / pss.c
1 /* pss.c
2
3    PKCS#1 RSA-PSS padding (RFC-3447).
4
5    Copyright (C) 2017 Daiki Ueno
6
7    This file is part of GNU Nettle.
8
9    GNU Nettle is free software: you can redistribute it and/or
10    modify it under the terms of either:
11
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.
15
16    or
17
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.
21
22    or both in parallel, as here.
23
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.
28
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/.
32 */
33
34 #if HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <assert.h>
39 #include <string.h>
40
41 #include "pss.h"
42 #include "pss-mgf1.h"
43
44 #include "bignum.h"
45 #include "gmp-glue.h"
46
47 #include "memxor.h"
48 #include "nettle-internal.h"
49
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
53 };
54
55 /* Format the PKCS#1 PSS padding for given salt and digest, using
56  * pss_mgf1() as the mask generation function.
57  *
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.  */
61 int
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)
66 {
67   TMP_GMP_DECL(em, uint8_t);
68   TMP_DECL(state, uint8_t, NETTLE_MAX_HASH_CONTEXT_SIZE);
69   uint8_t pad[8];
70   size_t key_size = (bits + 7) / 8;
71   size_t j;
72
73   TMP_GMP_ALLOC(em, key_size);
74   TMP_ALLOC(state, hash->context_size);
75
76   if (key_size < hash->digest_size + salt_length + 2)
77     {
78       TMP_GMP_FREE(em);
79       return 0;
80     }
81
82   /* Compute M'.  */
83   hash->init(state);
84   memset(pad, 0, 8);
85   hash->update(state, 8, pad);
86   hash->update(state, hash->digest_size, digest);
87   hash->update(state, salt_length, salt);
88
89   /* Store H in EM, right after maskedDB.  */
90   hash->digest(state, hash->digest_size, em + key_size - hash->digest_size - 1);
91
92   /* Compute dbMask.  */
93   hash->init(state);
94   hash->update(state, hash->digest_size, em + key_size - hash->digest_size - 1);
95
96   pss_mgf1(state, hash, key_size - hash->digest_size - 1, em);
97
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++)
100     em[j] ^= 0;
101   em[j++] ^= 1;
102   memxor(em + j, salt, salt_length);
103   j += salt_length;
104
105   /* Store the trailer field following H.  */
106   j += hash->digest_size;
107   *(em + j) = 0xbc;
108
109   /* Clear the leftmost 8 * emLen - emBits of the leftmost octet in EM.  */
110   *em &= pss_masks[(8 * key_size - bits)];
111
112   nettle_mpz_set_str_256_u(m, key_size, em);
113   TMP_GMP_FREE(em);
114   return 1;
115 }
116
117 /* Check the consistency of given PKCS#1 PSS encoded message, created
118  * with pss_encode_mgf1().
119  *
120  * Returns 1 if the encoded message is consistent, 0 if it is
121  * inconsistent.  */
122 int
123 pss_verify_mgf1(mpz_t m, size_t bits,
124                 const struct nettle_hash *hash,
125                 size_t salt_length,
126                 const uint8_t *digest)
127 {
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;
133   size_t j;
134   int ret = 0;
135
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);
139
140   TMP_ALLOC(h2, hash->digest_size);
141   TMP_ALLOC(state, hash->context_size);
142
143   if (key_size < hash->digest_size + salt_length + 2)
144     goto cleanup;
145
146   nettle_mpz_get_str_256(key_size, em, m);
147
148   /* Check the trailer field.  */
149   if (em[key_size - 1] != 0xbc)
150     goto cleanup;
151
152   /* Extract H.  */
153   h = em + (key_size - hash->digest_size - 1);
154
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)
158     goto cleanup;
159
160   /* Compute dbMask.  */
161   hash->init(state);
162   hash->update(state, hash->digest_size, h);
163
164   db = em + key_size;
165   pss_mgf1(state, hash, key_size - hash->digest_size - 1, db);
166
167   /* Compute DB.  */
168   memxor(db, em, key_size - hash->digest_size - 1);
169
170   *db &= pss_masks[(8 * key_size - bits)];
171   for (j = 0; j < key_size - salt_length - hash->digest_size - 2; j++)
172     if (db[j] != 0)
173       goto cleanup;
174
175   /* Check the octet right after PS is 0x1.  */
176   if (db[j] != 0x1)
177     goto cleanup;
178   salt = db + j + 1;
179
180   /* Compute H'.  */
181   memset(pad, 0, 8);
182   hash->init(state);
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);
187
188   /* Check if H' = H.  */
189   if (memcmp(h2, h, hash->digest_size) != 0)
190     goto cleanup;
191
192   ret = 1;
193  cleanup:
194   TMP_GMP_FREE(em);
195   return ret;
196 }