/src/opensc/src/libopensc/padding.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * padding.c: miscellaneous padding functions |
3 | | * |
4 | | * Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi> |
5 | | * Copyright (C) 2003 - 2007 Nils Larsch <larsch@trustcenter.de> |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #ifdef HAVE_CONFIG_H |
23 | | #include "config.h" |
24 | | #endif |
25 | | |
26 | | #ifdef ENABLE_OPENSSL |
27 | | #include <openssl/evp.h> |
28 | | #include <openssl/rand.h> |
29 | | #include <openssl/sha.h> |
30 | | #endif |
31 | | |
32 | | #include <string.h> |
33 | | #include <stdlib.h> |
34 | | |
35 | | #include "common/constant-time.h" |
36 | | #include "internal.h" |
37 | | #include "pkcs11/pkcs11.h" |
38 | | /* TODO doxygen comments */ |
39 | | |
40 | 0 | #define SC_PKCS1_PADDING_MIN_SIZE 11 |
41 | | |
42 | | /* |
43 | | * Prefixes for pkcs-v1 signatures |
44 | | */ |
45 | | static const u8 hdr_md5[] = { |
46 | | 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, |
47 | | 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 |
48 | | }; |
49 | | static const u8 hdr_sha1[] = { |
50 | | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, |
51 | | 0x05, 0x00, 0x04, 0x14 |
52 | | }; |
53 | | static const u8 hdr_sha256[] = { |
54 | | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
55 | | 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 |
56 | | }; |
57 | | static const u8 hdr_sha384[] = { |
58 | | 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
59 | | 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 |
60 | | }; |
61 | | static const u8 hdr_sha512[] = { |
62 | | 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
63 | | 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 |
64 | | }; |
65 | | static const u8 hdr_sha224[] = { |
66 | | 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, |
67 | | 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c |
68 | | }; |
69 | | static const u8 hdr_ripemd160[] = { |
70 | | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, |
71 | | 0x05, 0x00, 0x04, 0x14 |
72 | | }; |
73 | | |
74 | | |
75 | | static const struct digest_info_prefix { |
76 | | unsigned int algorithm; |
77 | | const u8 * hdr; |
78 | | size_t hdr_len; |
79 | | size_t hash_len; |
80 | | } digest_info_prefix[] = { |
81 | | { SC_ALGORITHM_RSA_HASH_NONE, NULL, 0, 0 }, |
82 | | { SC_ALGORITHM_RSA_HASH_MD5, hdr_md5, sizeof(hdr_md5), 16 }, |
83 | | { SC_ALGORITHM_RSA_HASH_SHA1, hdr_sha1, sizeof(hdr_sha1), 20 }, |
84 | | { SC_ALGORITHM_RSA_HASH_SHA256, hdr_sha256, sizeof(hdr_sha256), 32 }, |
85 | | { SC_ALGORITHM_RSA_HASH_SHA384, hdr_sha384, sizeof(hdr_sha384), 48 }, |
86 | | { SC_ALGORITHM_RSA_HASH_SHA512, hdr_sha512, sizeof(hdr_sha512), 64 }, |
87 | | { SC_ALGORITHM_RSA_HASH_SHA224, hdr_sha224, sizeof(hdr_sha224), 28 }, |
88 | | { SC_ALGORITHM_RSA_HASH_RIPEMD160,hdr_ripemd160, sizeof(hdr_ripemd160), 20 }, |
89 | | { SC_ALGORITHM_RSA_HASH_MD5_SHA1, NULL, 0, 36 }, |
90 | | { 0, NULL, 0, 0 } |
91 | | }; |
92 | | |
93 | | /* add/remove pkcs1 BT01 padding */ |
94 | | |
95 | | static int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len, |
96 | | u8 *out, size_t *out_len, size_t mod_length) |
97 | 0 | { |
98 | 0 | size_t i; |
99 | |
|
100 | 0 | if (*out_len < mod_length) |
101 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
102 | 0 | if (in_len + 11 > mod_length) |
103 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
104 | 0 | i = mod_length - in_len; |
105 | 0 | memmove(out + i, in, in_len); |
106 | 0 | *out++ = 0x00; |
107 | 0 | *out++ = 0x01; |
108 | |
|
109 | 0 | memset(out, 0xFF, i - 3); |
110 | 0 | out += i - 3; |
111 | 0 | *out = 0x00; |
112 | |
|
113 | 0 | *out_len = mod_length; |
114 | 0 | return SC_SUCCESS; |
115 | 0 | } |
116 | | |
117 | | int |
118 | | sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len, |
119 | | u8 *out, size_t *out_len) |
120 | 0 | { |
121 | 0 | const u8 *tmp = in_dat; |
122 | 0 | size_t len; |
123 | |
|
124 | 0 | if (in_dat == NULL || in_len < 10) |
125 | 0 | return SC_ERROR_INTERNAL; |
126 | | /* skip leading zero byte */ |
127 | 0 | if (*tmp == 0) { |
128 | 0 | tmp++; |
129 | 0 | in_len--; |
130 | 0 | } |
131 | 0 | len = in_len; |
132 | 0 | if (*tmp != 0x01) |
133 | 0 | return SC_ERROR_WRONG_PADDING; |
134 | 0 | for (tmp++, len--; *tmp == 0xff && len != 0; tmp++, len--) |
135 | 0 | ; |
136 | 0 | if (!len || (in_len - len) < 9 || *tmp++ != 0x00) |
137 | 0 | return SC_ERROR_WRONG_PADDING; |
138 | 0 | len--; |
139 | 0 | if (out == NULL) |
140 | | /* just check the padding */ |
141 | 0 | return SC_SUCCESS; |
142 | 0 | if (*out_len < len) |
143 | 0 | return SC_ERROR_INTERNAL; |
144 | 0 | memmove(out, tmp, len); |
145 | 0 | *out_len = len; |
146 | 0 | return SC_SUCCESS; |
147 | 0 | } |
148 | | |
149 | | /* Remove pkcs1 BT02 padding (adding BT02 padding is currently not |
150 | | * needed/implemented) in constant-time. |
151 | | * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */ |
152 | | int |
153 | | sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, unsigned int data_len, u8 *out, unsigned int *out_len) |
154 | 0 | { |
155 | 0 | unsigned int i = 0; |
156 | 0 | u8 *msg, *msg_orig = NULL; |
157 | 0 | unsigned int good, found_zero_byte, mask, tmp_outlen; |
158 | 0 | unsigned int zero_index = 0, msg_index, mlen = -1, len = 0; |
159 | 0 | LOG_FUNC_CALLED(ctx); |
160 | |
|
161 | 0 | if (data == NULL || data_len <= 0 || data_len > n || |
162 | 0 | n < SC_PKCS1_PADDING_MIN_SIZE || out_len == NULL) |
163 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
164 | | |
165 | 0 | tmp_outlen = *out_len; |
166 | 0 | msg = msg_orig = calloc(n, sizeof(u8)); |
167 | 0 | if (msg == NULL) |
168 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
169 | | |
170 | | /* |
171 | | * We can not check length of input data straight away and still we need to read |
172 | | * from input even when the input is not as long as needed to keep the time constant. |
173 | | * If data has wrong size, it is padded by zeroes from left and the following checks |
174 | | * do not pass. |
175 | | */ |
176 | 0 | len = data_len; |
177 | 0 | for (data += len, msg += n, i = 0; i < n; i++) { |
178 | 0 | mask = ~constant_time_is_zero(len); |
179 | 0 | len -= 1 & mask; |
180 | 0 | data -= 1 & mask; |
181 | 0 | *--msg = *data & mask; |
182 | 0 | } |
183 | | // check first byte to be 0x00 |
184 | 0 | good = constant_time_is_zero(msg[0]); |
185 | | // check second byte to be 0x02 |
186 | 0 | good &= constant_time_eq(msg[1], 2); |
187 | | |
188 | | // find zero byte after random data in padding |
189 | 0 | found_zero_byte = 0; |
190 | 0 | for (i = 2; i < n; i++) { |
191 | 0 | unsigned int equals0 = constant_time_is_zero(msg[i]); |
192 | 0 | zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index); |
193 | 0 | found_zero_byte |= equals0; |
194 | 0 | } |
195 | | |
196 | | // zero_index stands for index of last found zero |
197 | 0 | good &= constant_time_ge(zero_index, 2 + 8); |
198 | | |
199 | | // start of the actual message in data |
200 | 0 | msg_index = zero_index + 1; |
201 | | |
202 | | // length of message |
203 | 0 | mlen = data_len - msg_index; |
204 | | |
205 | | // check that message fits into out buffer |
206 | 0 | good &= constant_time_ge(tmp_outlen, mlen); |
207 | | |
208 | | // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left. |
209 | 0 | tmp_outlen = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, tmp_outlen), |
210 | 0 | n - SC_PKCS1_PADDING_MIN_SIZE, tmp_outlen); |
211 | 0 | for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) { |
212 | 0 | mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0); |
213 | 0 | for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++) |
214 | 0 | msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]); |
215 | 0 | } |
216 | | // move message into out buffer, if good |
217 | 0 | for (i = 0; i < tmp_outlen; i++) { |
218 | 0 | unsigned int msg_index; |
219 | | // when out is longer than message in data, use some bogus index in msg |
220 | 0 | mask = good & constant_time_lt(i, mlen); |
221 | 0 | msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer |
222 | 0 | out[i] = constant_time_select_8(mask, msg[msg_index], out[i]); |
223 | 0 | } |
224 | |
|
225 | 0 | *out_len = constant_time_select(good, mlen, *out_len); |
226 | 0 | free(msg_orig); |
227 | 0 | return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING); |
228 | 0 | } |
229 | | |
230 | | #ifdef ENABLE_OPENSSL |
231 | | static int mgf1(u8 *mask, size_t len, u8 *seed, size_t seedLen, const EVP_MD *dgst) |
232 | 0 | { |
233 | 0 | int i; |
234 | 0 | size_t outlen = 0; |
235 | 0 | u8 cnt[4]; |
236 | 0 | EVP_MD_CTX *md_ctx = NULL; |
237 | 0 | int mdlen; |
238 | 0 | u8 md[EVP_MAX_MD_SIZE]; |
239 | 0 | int rv = 1; |
240 | |
|
241 | 0 | if (!(md_ctx = EVP_MD_CTX_new())) |
242 | 0 | goto out; |
243 | | |
244 | 0 | mdlen = EVP_MD_size(dgst); |
245 | 0 | if (mdlen < 0) |
246 | 0 | goto out; |
247 | | |
248 | 0 | for (i = 0; outlen < len; i++) { |
249 | 0 | cnt[0] = (u8) ((i >> 24) & 255); |
250 | 0 | cnt[1] = (u8) ((i >> 16) & 255); |
251 | 0 | cnt[2] = (u8) ((i >> 8) & 255); |
252 | 0 | cnt[3] = (u8) ((i >> 0) & 255); |
253 | 0 | if (!EVP_DigestInit_ex(md_ctx, dgst, NULL) |
254 | 0 | || !EVP_DigestUpdate(md_ctx, seed, seedLen) |
255 | 0 | || !EVP_DigestUpdate(md_ctx, cnt, 4)) |
256 | 0 | goto out; |
257 | 0 | if (outlen + mdlen <= len) { |
258 | 0 | if (!EVP_DigestFinal_ex(md_ctx, mask + outlen, NULL)) |
259 | 0 | goto out; |
260 | 0 | outlen += mdlen; |
261 | 0 | } else { |
262 | 0 | if (!EVP_DigestFinal_ex(md_ctx, md, NULL)) |
263 | 0 | goto out; |
264 | 0 | memcpy(mask + outlen, md, len - outlen); |
265 | 0 | outlen = len; |
266 | 0 | } |
267 | 0 | } |
268 | 0 | rv = 0; |
269 | 0 | out: |
270 | 0 | OPENSSL_cleanse(md, sizeof(md)); |
271 | 0 | if (md_ctx) |
272 | 0 | EVP_MD_CTX_free(md_ctx); |
273 | 0 | return rv; |
274 | 0 | } |
275 | | |
276 | | /* forward declarations */ |
277 | | static EVP_MD *mgf1_flag2md(sc_context_t *ctx, unsigned long mgf1); |
278 | | static EVP_MD *hash_flag2md(sc_context_t *ctx, unsigned long hash); |
279 | | |
280 | | /* check/remove OAEP - RFC 8017 padding */ |
281 | | int sc_pkcs1_strip_oaep_padding(sc_context_t *ctx, u8 *data, size_t len, unsigned long flags, uint8_t *param, size_t paramlen) |
282 | 0 | { |
283 | 0 | size_t i,j; |
284 | 0 | size_t mdlen, dblen; |
285 | 0 | u8 seed[EVP_MAX_MD_SIZE]; |
286 | 0 | EVP_MD *mgf1_md = NULL, *hash_md = NULL; |
287 | 0 | u8 db[512]; /* up to RSA 4096 */ |
288 | 0 | u8 label[EVP_MAX_MD_SIZE]; |
289 | 0 | EVP_MD_CTX *md_ctx; |
290 | 0 | unsigned int hash_len = 0; |
291 | |
|
292 | 0 | LOG_FUNC_CALLED(ctx); |
293 | 0 | if (data == NULL) |
294 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
295 | | |
296 | | /* https://www.rfc-editor.org/rfc/pdfrfc/rfc8017.txt.pdf, page 26, 3.a. */ |
297 | 0 | hash_md = hash_flag2md(ctx, flags); |
298 | 0 | if (!hash_md) |
299 | 0 | return SC_ERROR_NOT_SUPPORTED; |
300 | | |
301 | 0 | memset(label, 0, sizeof(label)); |
302 | 0 | if ((md_ctx = EVP_MD_CTX_new())) { |
303 | 0 | if (!EVP_DigestInit_ex(md_ctx, hash_md, NULL) |
304 | 0 | || !EVP_DigestUpdate(md_ctx, param, paramlen) |
305 | 0 | || !EVP_DigestFinal_ex(md_ctx, label, &hash_len)) { |
306 | 0 | sc_log_openssl(ctx); |
307 | 0 | hash_len = 0; |
308 | 0 | } |
309 | 0 | EVP_MD_CTX_free(md_ctx); |
310 | 0 | } |
311 | 0 | sc_evp_md_free(hash_md); |
312 | 0 | hash_md = NULL; |
313 | 0 | if (!hash_len) { |
314 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
315 | 0 | } |
316 | | |
317 | 0 | mgf1_md = mgf1_flag2md(ctx, flags); |
318 | 0 | if (!mgf1_md) |
319 | 0 | return SC_ERROR_NOT_SUPPORTED; |
320 | | |
321 | 0 | mdlen = EVP_MD_size(mgf1_md); |
322 | |
|
323 | 0 | if (len < 2 * mdlen + 2) { |
324 | 0 | sc_evp_md_free(mgf1_md); |
325 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); |
326 | 0 | } |
327 | | |
328 | 0 | if (*data != 0) { |
329 | 0 | sc_evp_md_free(mgf1_md); |
330 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); |
331 | 0 | } |
332 | | |
333 | 0 | dblen = len - 1 - mdlen; |
334 | 0 | if (dblen > sizeof(db)) { |
335 | 0 | sc_evp_md_free(mgf1_md); |
336 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
337 | 0 | } |
338 | | |
339 | 0 | if (mgf1(seed, mdlen, data + mdlen + 1, dblen, mgf1_md)) { |
340 | 0 | sc_log_openssl(ctx); |
341 | 0 | sc_evp_md_free(mgf1_md); |
342 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
343 | 0 | } |
344 | 0 | for (i = 0; i < mdlen; i++) |
345 | 0 | seed[i] ^= data[i + 1]; |
346 | |
|
347 | 0 | if (mgf1(db, dblen, seed, mdlen, mgf1_md)) { |
348 | 0 | sc_log_openssl(ctx); |
349 | 0 | sc_evp_md_free(mgf1_md); |
350 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
351 | 0 | } |
352 | 0 | sc_evp_md_free(mgf1_md); |
353 | 0 | for (i = 0; i < dblen; i++) { |
354 | 0 | db[i] ^= data[i + mdlen + 1]; |
355 | | /* clear lHash' if same as lHash */ |
356 | 0 | if (i < hash_len) |
357 | 0 | db[i] ^= label[i]; |
358 | 0 | } |
359 | | /* if the padding is correct, it is a concatenation: |
360 | | * 00...00 || 01 || plaintext |
361 | | * check padding but do not leak information about error: |
362 | | */ |
363 | 0 | for (j = 0, i = 0; i < dblen;) { |
364 | 0 | j += db[i++] + 1; |
365 | 0 | if (i > mdlen) { |
366 | 0 | if (j == i + 1) { |
367 | | /* OK correct padding found */ |
368 | 0 | len = dblen - i; |
369 | 0 | memcpy(data, db + i, len); |
370 | 0 | LOG_FUNC_RETURN(ctx, (int)len); |
371 | 0 | } |
372 | 0 | } |
373 | 0 | } |
374 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); |
375 | 0 | } |
376 | | #endif |
377 | | |
378 | | /* add/remove DigestInfo prefix */ |
379 | | static int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm, |
380 | | const u8 *in, size_t in_len, u8 *out, size_t *out_len) |
381 | 0 | { |
382 | 0 | int i; |
383 | |
|
384 | 0 | for (i = 0; digest_info_prefix[i].algorithm != 0; i++) { |
385 | 0 | if (algorithm == digest_info_prefix[i].algorithm) { |
386 | 0 | const u8 *hdr = digest_info_prefix[i].hdr; |
387 | 0 | size_t hdr_len = digest_info_prefix[i].hdr_len, |
388 | 0 | hash_len = digest_info_prefix[i].hash_len; |
389 | |
|
390 | 0 | if (in_len != hash_len || *out_len < (hdr_len + hash_len)) |
391 | 0 | return SC_ERROR_INTERNAL; |
392 | | |
393 | 0 | memmove(out + hdr_len, in, hash_len); |
394 | 0 | memmove(out, hdr, hdr_len); |
395 | 0 | *out_len = hdr_len + hash_len; |
396 | |
|
397 | 0 | return SC_SUCCESS; |
398 | 0 | } |
399 | 0 | } |
400 | | |
401 | 0 | return SC_ERROR_INTERNAL; |
402 | 0 | } |
403 | | |
404 | | int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm, |
405 | | const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len) |
406 | 0 | { |
407 | 0 | int i; |
408 | |
|
409 | 0 | for (i = 0; digest_info_prefix[i].algorithm != 0; i++) { |
410 | 0 | size_t hdr_len = digest_info_prefix[i].hdr_len, |
411 | 0 | hash_len = digest_info_prefix[i].hash_len; |
412 | 0 | const u8 *hdr = digest_info_prefix[i].hdr; |
413 | |
|
414 | 0 | if (in_len == (hdr_len + hash_len) && |
415 | 0 | !memcmp(in_dat, hdr, hdr_len)) { |
416 | 0 | if (algorithm) |
417 | 0 | *algorithm = digest_info_prefix[i].algorithm; |
418 | 0 | if (out_dat == NULL) |
419 | | /* just check the DigestInfo prefix */ |
420 | 0 | return SC_SUCCESS; |
421 | 0 | if (*out_len < hash_len) |
422 | 0 | return SC_ERROR_INTERNAL; |
423 | 0 | memmove(out_dat, in_dat + hdr_len, hash_len); |
424 | 0 | *out_len = hash_len; |
425 | 0 | return SC_SUCCESS; |
426 | 0 | } |
427 | 0 | } |
428 | 0 | return SC_ERROR_INTERNAL; |
429 | 0 | } |
430 | | |
431 | | #ifdef ENABLE_OPENSSL |
432 | | |
433 | | static EVP_MD* hash_flag2md(sc_context_t *ctx, unsigned long hash) |
434 | 0 | { |
435 | 0 | switch (hash & SC_ALGORITHM_RSA_HASHES) { |
436 | 0 | case SC_ALGORITHM_RSA_HASH_SHA1: |
437 | 0 | return sc_evp_md(ctx, "SHA1"); |
438 | 0 | case SC_ALGORITHM_RSA_HASH_SHA224: |
439 | 0 | return sc_evp_md(ctx, "SHA224"); |
440 | 0 | case SC_ALGORITHM_RSA_HASH_SHA256: |
441 | 0 | return sc_evp_md(ctx, "SHA256"); |
442 | 0 | case SC_ALGORITHM_RSA_HASH_SHA384: |
443 | 0 | return sc_evp_md(ctx, "SHA384"); |
444 | 0 | case SC_ALGORITHM_RSA_HASH_SHA512: |
445 | 0 | return sc_evp_md(ctx, "SHA512"); |
446 | 0 | default: |
447 | 0 | return NULL; |
448 | 0 | } |
449 | 0 | } |
450 | | |
451 | | static EVP_MD* mgf1_flag2md(sc_context_t *ctx, unsigned long mgf1) |
452 | 0 | { |
453 | 0 | switch (mgf1 & SC_ALGORITHM_MGF1_HASHES) { |
454 | 0 | case SC_ALGORITHM_MGF1_SHA1: |
455 | 0 | return sc_evp_md(ctx, "SHA1"); |
456 | 0 | case SC_ALGORITHM_MGF1_SHA224: |
457 | 0 | return sc_evp_md(ctx, "SHA224"); |
458 | 0 | case SC_ALGORITHM_MGF1_SHA256: |
459 | 0 | return sc_evp_md(ctx, "SHA256"); |
460 | 0 | case SC_ALGORITHM_MGF1_SHA384: |
461 | 0 | return sc_evp_md(ctx, "SHA384"); |
462 | 0 | case SC_ALGORITHM_MGF1_SHA512: |
463 | 0 | return sc_evp_md(ctx, "SHA512"); |
464 | 0 | default: |
465 | 0 | return NULL; |
466 | 0 | } |
467 | 0 | } |
468 | | |
469 | | /* large enough up to RSA 4096 */ |
470 | 0 | #define PSS_MAX_SALT_SIZE 512 |
471 | | /* add PKCS#1 v2.0 PSS padding */ |
472 | | static int sc_pkcs1_add_pss_padding(sc_context_t *scctx, unsigned int hash, unsigned int mgf1_hash, |
473 | | const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_bits, size_t sLen) |
474 | 0 | { |
475 | | /* hLen = sLen in our case */ |
476 | 0 | int rv = SC_ERROR_INTERNAL, j, hlen; |
477 | 0 | size_t dblen, plen, round, mgf_rounds, i; |
478 | 0 | int mgf1_hlen; |
479 | 0 | EVP_MD* md = NULL, *mgf1_md = NULL; |
480 | 0 | EVP_MD_CTX* ctx = NULL; |
481 | 0 | u8 buf[8]; |
482 | 0 | u8 salt[PSS_MAX_SALT_SIZE], mask[EVP_MAX_MD_SIZE]; |
483 | 0 | size_t mod_length = BYTES4BITS(mod_bits); |
484 | |
|
485 | 0 | if (*out_len < mod_length) |
486 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
487 | | |
488 | 0 | md = hash_flag2md(scctx, hash); |
489 | 0 | if (md == NULL) { |
490 | 0 | sc_log_openssl(scctx); |
491 | 0 | return SC_ERROR_NOT_SUPPORTED; |
492 | 0 | } |
493 | 0 | hlen = EVP_MD_size(md); |
494 | 0 | dblen = mod_length - hlen - 1; /* emLen - hLen - 1 */ |
495 | 0 | plen = mod_length - sLen - hlen - 1; |
496 | 0 | if (in_len != (unsigned)hlen) { |
497 | 0 | sc_evp_md_free(md); |
498 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
499 | 0 | } |
500 | 0 | if (sLen + (unsigned)hlen + 2 > mod_length) { |
501 | | /* RSA key too small for chosen hash (1296 bits or higher needed for |
502 | | * signing SHA-512 hashes) */ |
503 | 0 | sc_evp_md_free(md); |
504 | 0 | return SC_ERROR_NOT_SUPPORTED; |
505 | 0 | } |
506 | 0 | if (sLen > PSS_MAX_SALT_SIZE) { |
507 | 0 | sc_evp_md_free(md); |
508 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
509 | 0 | } |
510 | 0 | if (RAND_bytes(salt, (unsigned)sLen) != 1) { |
511 | 0 | sc_log_openssl(scctx); |
512 | 0 | sc_evp_md_free(md); |
513 | 0 | return SC_ERROR_INTERNAL; |
514 | 0 | } |
515 | | |
516 | | /* Hash M' to create H */ |
517 | 0 | if (!(ctx = EVP_MD_CTX_create())) |
518 | 0 | goto done; |
519 | 0 | memset(buf, 0x00, 8); |
520 | 0 | if (EVP_DigestInit_ex(ctx, md, NULL) != 1 || |
521 | 0 | EVP_DigestUpdate(ctx, buf, 8) != 1 || |
522 | 0 | EVP_DigestUpdate(ctx, in, hlen) != 1 || /* mHash */ |
523 | 0 | EVP_DigestUpdate(ctx, salt, sLen) != 1) { |
524 | 0 | sc_log_openssl(scctx); |
525 | 0 | goto done; |
526 | 0 | } |
527 | | |
528 | | /* Construct padding2, salt, H, and BC in the output block */ |
529 | | /* DB = PS || 0x01 || salt */ |
530 | 0 | memset(out, 0x00, plen - 1); /* emLen - sLen - hLen - 2 */ |
531 | 0 | out[plen - 1] = 0x01; |
532 | 0 | memcpy(out + plen, salt, sLen); |
533 | 0 | if (EVP_DigestFinal_ex(ctx, out + dblen, NULL) != 1) { /* H */ |
534 | 0 | sc_log_openssl(scctx); |
535 | 0 | goto done; |
536 | 0 | } |
537 | 0 | out[dblen + hlen] = 0xBC; |
538 | | /* EM = DB* || H || 0xbc |
539 | | * *the first part is masked later */ |
540 | | |
541 | | /* Construct the DB mask block by block and XOR it in. */ |
542 | 0 | mgf1_md = mgf1_flag2md(scctx, mgf1_hash); |
543 | 0 | if (mgf1_md == NULL) { |
544 | 0 | sc_log_openssl(scctx); |
545 | 0 | goto done; |
546 | 0 | } |
547 | 0 | mgf1_hlen = EVP_MD_size(mgf1_md); |
548 | |
|
549 | 0 | mgf_rounds = (dblen + mgf1_hlen - 1) / mgf1_hlen; /* round up */ |
550 | 0 | for (round = 0; round < mgf_rounds; ++round) { |
551 | 0 | buf[0] = (round&0xFF000000U) >> 24; |
552 | 0 | buf[1] = (round&0x00FF0000U) >> 16; |
553 | 0 | buf[2] = (round&0x0000FF00U) >> 8; |
554 | 0 | buf[3] = (round&0x000000FFU); |
555 | 0 | if (EVP_DigestInit_ex(ctx, mgf1_md, NULL) != 1 || |
556 | 0 | EVP_DigestUpdate(ctx, out + dblen, hlen) != 1 || /* H (Z parameter of MGF1) */ |
557 | 0 | EVP_DigestUpdate(ctx, buf, 4) != 1 || /* C */ |
558 | 0 | EVP_DigestFinal_ex(ctx, mask, NULL) != 1) { |
559 | 0 | sc_log_openssl(scctx); |
560 | 0 | goto done; |
561 | 0 | } |
562 | | /* this is no longer part of the MGF1, but actually |
563 | | * XORing mask with DB to create maskedDB inplace */ |
564 | 0 | for (i = round * mgf1_hlen, j = 0; i < dblen && j < mgf1_hlen; ++i, ++j) { |
565 | 0 | out[i] ^= mask[j]; |
566 | 0 | } |
567 | 0 | } |
568 | | |
569 | | /* Set leftmost N bits in leftmost octet in maskedDB to zero |
570 | | * to make sure the result is smaller than the modulus ( +1) |
571 | | */ |
572 | 0 | out[0] &= (0xff >> (8 * mod_length - mod_bits + 1)); |
573 | |
|
574 | 0 | *out_len = mod_length; |
575 | 0 | rv = SC_SUCCESS; |
576 | |
|
577 | 0 | done: |
578 | 0 | OPENSSL_cleanse(salt, sizeof(salt)); |
579 | 0 | OPENSSL_cleanse(mask, sizeof(mask)); |
580 | 0 | sc_evp_md_free(md); |
581 | 0 | sc_evp_md_free(mgf1_md); |
582 | 0 | if (ctx) { |
583 | 0 | EVP_MD_CTX_destroy(ctx); |
584 | 0 | } |
585 | 0 | return rv; |
586 | 0 | } |
587 | | |
588 | | static int hash_len2algo(size_t hash_len) |
589 | 0 | { |
590 | 0 | switch (hash_len) { |
591 | 0 | case SHA_DIGEST_LENGTH: |
592 | 0 | return SC_ALGORITHM_RSA_HASH_SHA1; |
593 | 0 | case SHA224_DIGEST_LENGTH: |
594 | 0 | return SC_ALGORITHM_RSA_HASH_SHA224; |
595 | 0 | case SHA256_DIGEST_LENGTH: |
596 | 0 | return SC_ALGORITHM_RSA_HASH_SHA256; |
597 | 0 | case SHA384_DIGEST_LENGTH: |
598 | 0 | return SC_ALGORITHM_RSA_HASH_SHA384; |
599 | 0 | case SHA512_DIGEST_LENGTH: |
600 | 0 | return SC_ALGORITHM_RSA_HASH_SHA512; |
601 | 0 | } |
602 | | /* Should never happen -- the mechanism and data should be already |
603 | | * verified to match one of the above. If not, we will fail later |
604 | | */ |
605 | 0 | return SC_ALGORITHM_RSA_HASH_NONE; |
606 | 0 | } |
607 | | #endif |
608 | | |
609 | | /* general PKCS#1 encoding function */ |
610 | | int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags, |
611 | | const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_bits, void *pMechanism) |
612 | 0 | { |
613 | 0 | int rv, i; |
614 | 0 | size_t tmp_len = *out_len; |
615 | 0 | const u8 *tmp = in; |
616 | 0 | unsigned int hash_algo, pad_algo; |
617 | 0 | size_t mod_len = BYTES4BITS(mod_bits); |
618 | 0 | #ifdef ENABLE_OPENSSL |
619 | 0 | size_t sLen; |
620 | 0 | EVP_MD* md = NULL; |
621 | 0 | unsigned int mgf1_hash; |
622 | 0 | #endif |
623 | |
|
624 | 0 | LOG_FUNC_CALLED(ctx); |
625 | |
|
626 | 0 | hash_algo = flags & SC_ALGORITHM_RSA_HASHES; |
627 | 0 | pad_algo = flags & SC_ALGORITHM_RSA_PADS; |
628 | 0 | if (pad_algo == 0) |
629 | 0 | pad_algo = SC_ALGORITHM_RSA_PAD_NONE; |
630 | 0 | sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo); |
631 | |
|
632 | 0 | if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01 || pad_algo == SC_ALGORITHM_RSA_PAD_NONE) && |
633 | 0 | hash_algo != SC_ALGORITHM_RSA_HASH_NONE) { |
634 | 0 | i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len, out, &tmp_len); |
635 | 0 | if (i != SC_SUCCESS) { |
636 | 0 | sc_log(ctx, "Unable to add digest info 0x%x", hash_algo); |
637 | 0 | LOG_FUNC_RETURN(ctx, i); |
638 | 0 | } |
639 | 0 | tmp = out; |
640 | 0 | } else { |
641 | 0 | tmp_len = in_len; |
642 | 0 | } |
643 | | |
644 | 0 | switch(pad_algo) { |
645 | 0 | case SC_ALGORITHM_RSA_PAD_NONE: |
646 | | /* padding done by card => nothing to do */ |
647 | 0 | if (out != tmp) |
648 | 0 | memcpy(out, tmp, tmp_len); |
649 | 0 | *out_len = tmp_len; |
650 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
651 | 0 | case SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01: |
652 | | /* add pkcs1 bt01 padding */ |
653 | 0 | rv = sc_pkcs1_add_01_padding(tmp, tmp_len, out, out_len, mod_len); |
654 | 0 | LOG_FUNC_RETURN(ctx, rv); |
655 | 0 | case SC_ALGORITHM_RSA_PAD_PSS: |
656 | | /* add PSS padding */ |
657 | 0 | #ifdef ENABLE_OPENSSL |
658 | 0 | mgf1_hash = flags & SC_ALGORITHM_MGF1_HASHES; |
659 | 0 | if (hash_algo == SC_ALGORITHM_RSA_HASH_NONE) { |
660 | | /* this is generic RSA_PKCS1_PSS mechanism with hash |
661 | | * already done outside of the module. The parameters |
662 | | * were already checked so we need to adjust the hash |
663 | | * algorithm to do the padding with the correct hash |
664 | | * function. |
665 | | */ |
666 | 0 | hash_algo = hash_len2algo(tmp_len); |
667 | 0 | } |
668 | | /* sLen is by default same as hash length */ |
669 | 0 | if (!(md = hash_flag2md(ctx, hash_algo))) { |
670 | 0 | sc_log_openssl(ctx); |
671 | 0 | return SC_ERROR_NOT_SUPPORTED; |
672 | 0 | } |
673 | 0 | sLen = EVP_MD_size(md); |
674 | 0 | sc_evp_md_free(md); |
675 | | /* if application provide sLen, use it */ |
676 | 0 | if (pMechanism != NULL) { |
677 | 0 | CK_MECHANISM *mech = (CK_MECHANISM *)pMechanism; |
678 | 0 | CK_RSA_PKCS_PSS_PARAMS *pss_params; |
679 | 0 | if (mech->pParameter && sizeof(CK_RSA_PKCS_PSS_PARAMS) == mech->ulParameterLen) { |
680 | 0 | pss_params = mech->pParameter; |
681 | 0 | sLen = pss_params->sLen; |
682 | 0 | } |
683 | 0 | } |
684 | 0 | rv = sc_pkcs1_add_pss_padding(ctx, hash_algo, mgf1_hash, |
685 | 0 | tmp, tmp_len, out, out_len, mod_bits, sLen); |
686 | | #else |
687 | | rv = SC_ERROR_NOT_SUPPORTED; |
688 | | #endif |
689 | 0 | LOG_FUNC_RETURN(ctx, rv); |
690 | 0 | default: |
691 | | /* We shouldn't be called with an unexpected padding type, we've already |
692 | | * returned SC_ERROR_NOT_SUPPORTED if the card can't be used. */ |
693 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
694 | 0 | } |
695 | 0 | } |
696 | | |
697 | | int sc_get_encoding_flags(sc_context_t *ctx, |
698 | | unsigned long iflags, unsigned long caps, |
699 | | unsigned long *pflags, unsigned long *sflags) |
700 | 0 | { |
701 | 0 | LOG_FUNC_CALLED(ctx); |
702 | 0 | if (pflags == NULL || sflags == NULL) |
703 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
704 | | |
705 | 0 | sc_log(ctx, "iFlags 0x%lX, card capabilities 0x%lX", iflags, caps); |
706 | | |
707 | | /* For ECDSA and GOSTR, we don't do any padding or hashing ourselves, the |
708 | | * card has to support the requested operation. Similarly, for RSA with |
709 | | * raw padding (raw RSA) and ISO9796, we require the card to do it for us. |
710 | | * Finally, for PKCS1 (v1.5 and PSS) and ASNI X9.31 we can apply the padding |
711 | | * ourselves if the card supports raw RSA. */ |
712 | | |
713 | | /* TODO: Could convert GOSTR3410_HASH_GOSTR3411 -> GOSTR3410_RAW and |
714 | | * ECDSA_HASH_ -> ECDSA_RAW using OpenSSL (not much benefit though). */ |
715 | |
|
716 | 0 | if ((caps & iflags) == iflags) { |
717 | | /* Card supports the signature operation we want to do, great, let's |
718 | | * go with it then. */ |
719 | 0 | *sflags = iflags; |
720 | 0 | *pflags = 0; |
721 | |
|
722 | 0 | } else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) && |
723 | 0 | (iflags & SC_ALGORITHM_RSA_PAD_PSS)) { |
724 | 0 | *sflags |= SC_ALGORITHM_RSA_PAD_PSS; |
725 | 0 | *sflags |= iflags & SC_ALGORITHM_MGF1_HASHES; |
726 | 0 | *pflags = iflags & ~(iflags & (SC_ALGORITHM_MGF1_HASHES | SC_ALGORITHM_RSA_PAD_PSS)); |
727 | |
|
728 | 0 | } else if ((caps & SC_ALGORITHM_RSA_RAW) && |
729 | 0 | (iflags & SC_ALGORITHM_RSA_PAD_PKCS1 |
730 | 0 | || iflags & SC_ALGORITHM_RSA_PAD_PSS |
731 | 0 | #ifdef ENABLE_OPENSSL |
732 | 0 | || iflags & SC_ALGORITHM_RSA_PAD_OAEP |
733 | 0 | #endif |
734 | 0 | || iflags & SC_ALGORITHM_RSA_PAD_NONE)) { |
735 | | /* Use the card's raw RSA capability on the padded input */ |
736 | 0 | *sflags = SC_ALGORITHM_RSA_PAD_NONE; |
737 | 0 | *pflags = iflags; |
738 | |
|
739 | 0 | } else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01 | SC_ALGORITHM_RSA_HASH_NONE)) && |
740 | 0 | (iflags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01)) { |
741 | | /* A corner case - the card can partially do PKCS1, if we prepend the |
742 | | * DigestInfo bit it will do the rest. */ |
743 | 0 | *sflags = SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01 | SC_ALGORITHM_RSA_HASH_NONE; |
744 | 0 | *pflags = iflags & SC_ALGORITHM_RSA_HASHES; |
745 | |
|
746 | 0 | } else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02 | SC_ALGORITHM_RSA_HASH_NONE)) && |
747 | 0 | (iflags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02)) { |
748 | 0 | *sflags = SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02 | SC_ALGORITHM_RSA_HASH_NONE; |
749 | 0 | *pflags = iflags & SC_ALGORITHM_RSA_HASHES; |
750 | |
|
751 | 0 | } else if ((iflags & SC_ALGORITHM_AES) == SC_ALGORITHM_AES) { /* TODO: seems like this constant does not belong to the same set of flags used form asymmetric algos. Fix this! */ |
752 | 0 | *sflags = 0; |
753 | 0 | *pflags = 0; |
754 | |
|
755 | 0 | } else if ((iflags & SC_ALGORITHM_AES_FLAGS) > 0) { |
756 | 0 | *sflags = iflags & SC_ALGORITHM_AES_FLAGS; |
757 | 0 | if (iflags & SC_ALGORITHM_AES_CBC_PAD) |
758 | 0 | *pflags = SC_ALGORITHM_AES_CBC_PAD; |
759 | 0 | else |
760 | 0 | *pflags = 0; |
761 | |
|
762 | 0 | } else { |
763 | 0 | LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported algorithm"); |
764 | 0 | } |
765 | | |
766 | 0 | sc_log(ctx, "pad flags 0x%lX, secure algorithm flags 0x%lX", *pflags, *sflags); |
767 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
768 | 0 | } |