1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2006.
3 */
4 /* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com). */
55
56 #include <openssl/x509.h>
57
58 #include <assert.h>
59
60 #include <openssl/asn1.h>
61 #include <openssl/asn1t.h>
62 #include <openssl/bio.h>
63 #include <openssl/evp.h>
64 #include <openssl/err.h>
65 #include <openssl/obj.h>
66
67 #include "internal.h"
68
69
rsa_pss_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)70 static int rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
71 void *exarg) {
72 if (operation == ASN1_OP_FREE_PRE) {
73 RSA_PSS_PARAMS *pss = (RSA_PSS_PARAMS *)*pval;
74 X509_ALGOR_free(pss->maskHash);
75 }
76 return 1;
77 }
78
79 ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = {
80 ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
81 ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
82 ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
83 ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
84 } ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS)
85
86 IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
87
88
89 /* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
90 static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
91 if (alg == NULL || alg->parameter == NULL ||
92 OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
93 alg->parameter->type != V_ASN1_SEQUENCE) {
94 return NULL;
95 }
96
97 const uint8_t *p = alg->parameter->value.sequence->data;
98 int plen = alg->parameter->value.sequence->length;
99 return d2i_X509_ALGOR(NULL, &p, plen);
100 }
101
rsa_pss_decode(const X509_ALGOR * alg,X509_ALGOR ** pmaskHash)102 static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
103 X509_ALGOR **pmaskHash) {
104 *pmaskHash = NULL;
105
106 if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) {
107 return NULL;
108 }
109
110 const uint8_t *p = alg->parameter->value.sequence->data;
111 int plen = alg->parameter->value.sequence->length;
112 RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
113 if (pss == NULL) {
114 return NULL;
115 }
116
117 *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
118 return pss;
119 }
120
121 /* allocate and set algorithm ID from EVP_MD, default SHA1 */
rsa_md_to_algor(X509_ALGOR ** palg,const EVP_MD * md)122 static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
123 if (EVP_MD_type(md) == NID_sha1) {
124 return 1;
125 }
126 *palg = X509_ALGOR_new();
127 if (*palg == NULL) {
128 return 0;
129 }
130 X509_ALGOR_set_md(*palg, md);
131 return 1;
132 }
133
134 /* Allocate and set MGF1 algorithm ID from EVP_MD */
rsa_md_to_mgf1(X509_ALGOR ** palg,const EVP_MD * mgf1md)135 static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
136 X509_ALGOR *algtmp = NULL;
137 ASN1_STRING *stmp = NULL;
138 *palg = NULL;
139
140 if (EVP_MD_type(mgf1md) == NID_sha1) {
141 return 1;
142 }
143 /* need to embed algorithm ID inside another */
144 if (!rsa_md_to_algor(&algtmp, mgf1md) ||
145 !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
146 goto err;
147 }
148 *palg = X509_ALGOR_new();
149 if (!*palg) {
150 goto err;
151 }
152 X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
153 stmp = NULL;
154
155 err:
156 ASN1_STRING_free(stmp);
157 X509_ALGOR_free(algtmp);
158 if (*palg) {
159 return 1;
160 }
161
162 return 0;
163 }
164
165 /* convert algorithm ID to EVP_MD, default SHA1 */
rsa_algor_to_md(X509_ALGOR * alg)166 static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
167 const EVP_MD *md;
168 if (!alg) {
169 return EVP_sha1();
170 }
171 md = EVP_get_digestbyobj(alg->algorithm);
172 if (md == NULL) {
173 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
174 }
175 return md;
176 }
177
178 /* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
rsa_mgf1_to_md(const X509_ALGOR * alg,X509_ALGOR * maskHash)179 static const EVP_MD *rsa_mgf1_to_md(const X509_ALGOR *alg,
180 X509_ALGOR *maskHash) {
181 const EVP_MD *md;
182 if (!alg) {
183 return EVP_sha1();
184 }
185 /* Check mask and lookup mask hash algorithm */
186 if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
187 maskHash == NULL) {
188 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
189 return NULL;
190 }
191 md = EVP_get_digestbyobj(maskHash->algorithm);
192 if (md == NULL) {
193 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
194 return NULL;
195 }
196 return md;
197 }
198
x509_rsa_ctx_to_pss(EVP_MD_CTX * ctx,X509_ALGOR * algor)199 int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
200 const EVP_MD *sigmd, *mgf1md;
201 int saltlen;
202 if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) ||
203 !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) ||
204 !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) {
205 return 0;
206 }
207
208 EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
209 if (saltlen == -1) {
210 saltlen = EVP_MD_size(sigmd);
211 } else if (saltlen == -2) {
212 // TODO(davidben): Forbid this mode. The world has largely standardized on
213 // salt length matching hash length.
214 saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
215 if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
216 saltlen--;
217 }
218 } else if (saltlen != (int)EVP_MD_size(sigmd)) {
219 // We only allow salt length matching hash length and, for now, the -2 case.
220 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
221 return 0;
222 }
223
224 int ret = 0;
225 ASN1_STRING *os = NULL;
226 RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
227 if (!pss) {
228 goto err;
229 }
230
231 if (saltlen != 20) {
232 pss->saltLength = ASN1_INTEGER_new();
233 if (!pss->saltLength ||
234 !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
235 goto err;
236 }
237 }
238
239 if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
240 !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
241 goto err;
242 }
243
244 /* Finally create string with pss parameter encoding. */
245 if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
246 goto err;
247 }
248
249 X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
250 os = NULL;
251 ret = 1;
252
253 err:
254 RSA_PSS_PARAMS_free(pss);
255 ASN1_STRING_free(os);
256 return ret;
257 }
258
x509_rsa_pss_to_ctx(EVP_MD_CTX * ctx,const X509_ALGOR * sigalg,EVP_PKEY * pkey)259 int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg,
260 EVP_PKEY *pkey) {
261 assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
262
263 /* Decode PSS parameters */
264 int ret = 0;
265 X509_ALGOR *maskHash;
266 RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
267 if (pss == NULL) {
268 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
269 goto err;
270 }
271
272 const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
273 const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm);
274 if (mgf1md == NULL || md == NULL) {
275 goto err;
276 }
277
278 int saltlen = 20;
279 if (pss->saltLength != NULL) {
280 saltlen = ASN1_INTEGER_get(pss->saltLength);
281
282 /* Could perform more salt length sanity checks but the main
283 * RSA routines will trap other invalid values anyway. */
284 if (saltlen < 0) {
285 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
286 goto err;
287 }
288 }
289
290 /* low-level routines support only trailer field 0xbc (value 1)
291 * and PKCS#1 says we should reject any other value anyway. */
292 if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) {
293 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
294 goto err;
295 }
296
297 EVP_PKEY_CTX *pctx;
298 if (!EVP_DigestVerifyInit(ctx, &pctx, md, NULL, pkey) ||
299 !EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
300 !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, saltlen) ||
301 !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md)) {
302 goto err;
303 }
304
305 ret = 1;
306
307 err:
308 RSA_PSS_PARAMS_free(pss);
309 X509_ALGOR_free(maskHash);
310 return ret;
311 }
312
x509_print_rsa_pss_params(BIO * bp,const X509_ALGOR * sigalg,int indent,ASN1_PCTX * pctx)313 int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
314 ASN1_PCTX *pctx) {
315 assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
316
317 int rv = 0;
318 X509_ALGOR *maskHash;
319 RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
320 if (!pss) {
321 if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
322 goto err;
323 }
324 rv = 1;
325 goto err;
326 }
327
328 if (BIO_puts(bp, "\n") <= 0 ||
329 !BIO_indent(bp, indent, 128) ||
330 BIO_puts(bp, "Hash Algorithm: ") <= 0) {
331 goto err;
332 }
333
334 if (pss->hashAlgorithm) {
335 if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
336 goto err;
337 }
338 } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
339 goto err;
340 }
341
342 if (BIO_puts(bp, "\n") <= 0 ||
343 !BIO_indent(bp, indent, 128) ||
344 BIO_puts(bp, "Mask Algorithm: ") <= 0) {
345 goto err;
346 }
347
348 if (pss->maskGenAlgorithm) {
349 if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
350 BIO_puts(bp, " with ") <= 0) {
351 goto err;
352 }
353
354 if (maskHash) {
355 if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
356 goto err;
357 }
358 } else if (BIO_puts(bp, "INVALID") <= 0) {
359 goto err;
360 }
361 } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
362 goto err;
363 }
364 BIO_puts(bp, "\n");
365
366 if (!BIO_indent(bp, indent, 128) ||
367 BIO_puts(bp, "Salt Length: 0x") <= 0) {
368 goto err;
369 }
370
371 if (pss->saltLength) {
372 if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
373 goto err;
374 }
375 } else if (BIO_puts(bp, "14 (default)") <= 0) {
376 goto err;
377 }
378 BIO_puts(bp, "\n");
379
380 if (!BIO_indent(bp, indent, 128) ||
381 BIO_puts(bp, "Trailer Field: 0x") <= 0) {
382 goto err;
383 }
384
385 if (pss->trailerField) {
386 if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
387 goto err;
388 }
389 } else if (BIO_puts(bp, "BC (default)") <= 0) {
390 goto err;
391 }
392 BIO_puts(bp, "\n");
393
394 rv = 1;
395
396 err:
397 RSA_PSS_PARAMS_free(pss);
398 X509_ALGOR_free(maskHash);
399 return rv;
400 }
401