Line data Source code
1 : /* rsa_pss.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 2005.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 2005 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include <stdio.h>
61 : #include "cryptlib.h"
62 : #include <openssl/bn.h>
63 : #include <openssl/rsa.h>
64 : #include <openssl/evp.h>
65 : #include <openssl/rand.h>
66 : #include <openssl/sha.h>
67 :
68 : static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
69 :
70 : #if defined(_MSC_VER) && defined(_ARM_)
71 : # pragma optimize("g", off)
72 : #endif
73 :
74 0 : int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
75 : const EVP_MD *Hash, const unsigned char *EM,
76 : int sLen)
77 : {
78 0 : return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
79 : }
80 :
81 0 : int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
82 : const EVP_MD *Hash, const EVP_MD *mgf1Hash,
83 : const unsigned char *EM, int sLen)
84 : {
85 : int i;
86 : int ret = 0;
87 : int hLen, maskedDBLen, MSBits, emLen;
88 : const unsigned char *H;
89 : unsigned char *DB = NULL;
90 : EVP_MD_CTX ctx;
91 : unsigned char H_[EVP_MAX_MD_SIZE];
92 0 : EVP_MD_CTX_init(&ctx);
93 :
94 0 : if (mgf1Hash == NULL)
95 : mgf1Hash = Hash;
96 :
97 0 : hLen = EVP_MD_size(Hash);
98 0 : if (hLen < 0)
99 : goto err;
100 : /*-
101 : * Negative sLen has special meanings:
102 : * -1 sLen == hLen
103 : * -2 salt length is autorecovered from signature
104 : * -N reserved
105 : */
106 0 : if (sLen == -1)
107 : sLen = hLen;
108 0 : else if (sLen == -2)
109 : sLen = -2;
110 0 : else if (sLen < -2) {
111 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
112 0 : goto err;
113 : }
114 :
115 0 : MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
116 0 : emLen = RSA_size(rsa);
117 0 : if (EM[0] & (0xFF << MSBits)) {
118 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID);
119 0 : goto err;
120 : }
121 0 : if (MSBits == 0) {
122 0 : EM++;
123 0 : emLen--;
124 : }
125 0 : if (emLen < (hLen + sLen + 2)) { /* sLen can be small negative */
126 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
127 0 : goto err;
128 : }
129 0 : if (EM[emLen - 1] != 0xbc) {
130 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID);
131 0 : goto err;
132 : }
133 0 : maskedDBLen = emLen - hLen - 1;
134 0 : H = EM + maskedDBLen;
135 0 : DB = OPENSSL_malloc(maskedDBLen);
136 0 : if (!DB) {
137 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE);
138 0 : goto err;
139 : }
140 0 : if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0)
141 : goto err;
142 0 : for (i = 0; i < maskedDBLen; i++)
143 0 : DB[i] ^= EM[i];
144 0 : if (MSBits)
145 0 : DB[0] &= 0xFF >> (8 - MSBits);
146 0 : for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ;
147 0 : if (DB[i++] != 0x1) {
148 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED);
149 0 : goto err;
150 : }
151 0 : if (sLen >= 0 && (maskedDBLen - i) != sLen) {
152 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
153 0 : goto err;
154 : }
155 0 : if (!EVP_DigestInit_ex(&ctx, Hash, NULL)
156 0 : || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes)
157 0 : || !EVP_DigestUpdate(&ctx, mHash, hLen))
158 : goto err;
159 0 : if (maskedDBLen - i) {
160 0 : if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i))
161 : goto err;
162 : }
163 0 : if (!EVP_DigestFinal_ex(&ctx, H_, NULL))
164 : goto err;
165 0 : if (memcmp(H_, H, hLen)) {
166 0 : RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE);
167 : ret = 0;
168 : } else
169 : ret = 1;
170 :
171 : err:
172 0 : if (DB)
173 0 : OPENSSL_free(DB);
174 0 : EVP_MD_CTX_cleanup(&ctx);
175 :
176 0 : return ret;
177 :
178 : }
179 :
180 0 : int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
181 : const unsigned char *mHash,
182 : const EVP_MD *Hash, int sLen)
183 : {
184 0 : return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
185 : }
186 :
187 0 : int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
188 : const unsigned char *mHash,
189 : const EVP_MD *Hash, const EVP_MD *mgf1Hash,
190 : int sLen)
191 : {
192 : int i;
193 : int ret = 0;
194 : int hLen, maskedDBLen, MSBits, emLen;
195 : unsigned char *H, *salt = NULL, *p;
196 : EVP_MD_CTX ctx;
197 :
198 0 : if (mgf1Hash == NULL)
199 : mgf1Hash = Hash;
200 :
201 0 : hLen = EVP_MD_size(Hash);
202 0 : if (hLen < 0)
203 : goto err;
204 : /*-
205 : * Negative sLen has special meanings:
206 : * -1 sLen == hLen
207 : * -2 salt length is maximized
208 : * -N reserved
209 : */
210 0 : if (sLen == -1)
211 : sLen = hLen;
212 0 : else if (sLen == -2)
213 : sLen = -2;
214 0 : else if (sLen < -2) {
215 0 : RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
216 0 : goto err;
217 : }
218 :
219 0 : MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
220 0 : emLen = RSA_size(rsa);
221 0 : if (MSBits == 0) {
222 0 : *EM++ = 0;
223 0 : emLen--;
224 : }
225 0 : if (sLen == -2) {
226 0 : sLen = emLen - hLen - 2;
227 0 : } else if (emLen < (hLen + sLen + 2)) {
228 0 : RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
229 : RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
230 0 : goto err;
231 : }
232 0 : if (sLen > 0) {
233 0 : salt = OPENSSL_malloc(sLen);
234 0 : if (!salt) {
235 0 : RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
236 : ERR_R_MALLOC_FAILURE);
237 0 : goto err;
238 : }
239 0 : if (RAND_bytes(salt, sLen) <= 0)
240 : goto err;
241 : }
242 0 : maskedDBLen = emLen - hLen - 1;
243 0 : H = EM + maskedDBLen;
244 0 : EVP_MD_CTX_init(&ctx);
245 0 : if (!EVP_DigestInit_ex(&ctx, Hash, NULL)
246 0 : || !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes)
247 0 : || !EVP_DigestUpdate(&ctx, mHash, hLen))
248 : goto err;
249 0 : if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen))
250 : goto err;
251 0 : if (!EVP_DigestFinal_ex(&ctx, H, NULL))
252 : goto err;
253 0 : EVP_MD_CTX_cleanup(&ctx);
254 :
255 : /* Generate dbMask in place then perform XOR on it */
256 0 : if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash))
257 : goto err;
258 :
259 : p = EM;
260 :
261 : /*
262 : * Initial PS XORs with all zeroes which is a NOP so just update pointer.
263 : * Note from a test above this value is guaranteed to be non-negative.
264 : */
265 0 : p += emLen - sLen - hLen - 2;
266 0 : *p++ ^= 0x1;
267 0 : if (sLen > 0) {
268 0 : for (i = 0; i < sLen; i++)
269 0 : *p++ ^= salt[i];
270 : }
271 0 : if (MSBits)
272 0 : EM[0] &= 0xFF >> (8 - MSBits);
273 :
274 : /* H is already in place so just set final 0xbc */
275 :
276 0 : EM[emLen - 1] = 0xbc;
277 :
278 : ret = 1;
279 :
280 : err:
281 0 : if (salt)
282 0 : OPENSSL_free(salt);
283 :
284 0 : return ret;
285 :
286 : }
287 :
288 : #if defined(_MSC_VER)
289 : # pragma optimize("",on)
290 : #endif
|