rsa_pss.c
Go to the documentation of this file.
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 
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;
75  }
76  return 1;
77 }
78 
80  ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
81  ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
83  ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
85 
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 
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 */
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 */
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  }
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 */
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  }
172  if (md == NULL) {
174  }
175  return md;
176 }
177 
178 /* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
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) {
189  return NULL;
190  }
191  md = EVP_get_digestbyobj(maskHash->algorithm);
192  if (md == NULL) {
194  return NULL;
195  }
196  return md;
197 }
198 
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.
221  return 0;
222  }
223 
224  int ret = 0;
225  ASN1_STRING *os = NULL;
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 
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 
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) {
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) {
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) {
294  goto err;
295  }
296 
297  EVP_PKEY_CTX *pctx;
298  if (!EVP_DigestVerifyInit(ctx, &pctx, md, NULL, pkey) ||
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 
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 }
EVP_MD_type
#define EVP_MD_type
Definition: boringssl_prefix_symbols.h:1580
asn1_type_st::sequence
ASN1_STRING * sequence
Definition: asn1.h:1504
regen-readme.it
it
Definition: regen-readme.py:15
EVP_DigestVerifyInit
#define EVP_DigestVerifyInit
Definition: boringssl_prefix_symbols.h:1519
RSA_PSS_PARAMS_free
#define RSA_PSS_PARAMS_free
Definition: boringssl_prefix_symbols.h:2078
EVP_PKEY_CTX_get_rsa_mgf1_md
#define EVP_PKEY_CTX_get_rsa_mgf1_md
Definition: boringssl_prefix_symbols.h:1589
X509_ALGOR_free
#define X509_ALGOR_free
Definition: boringssl_prefix_symbols.h:2253
ctx
Definition: benchmark-async.c:30
bio_st
Definition: bio.h:822
env_md_st
Definition: third_party/boringssl-with-bazel/src/crypto/fipsmodule/digest/internal.h:67
X509_algor_st::algorithm
ASN1_OBJECT * algorithm
Definition: x509.h:114
evp.h
rsa_pss_params_st::trailerField
ASN1_INTEGER * trailerField
Definition: x509.h:1848
rsa_pss_params_st::hashAlgorithm
X509_ALGOR * hashAlgorithm
Definition: x509.h:1845
OPENSSL_PUT_ERROR
#define OPENSSL_PUT_ERROR(library, reason)
Definition: err.h:423
bio.h
ASN1_INTEGER_get
#define ASN1_INTEGER_get
Definition: boringssl_prefix_symbols.h:645
X509_ALGOR_set0
OPENSSL_EXPORT int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *obj, int param_type, void *param_value)
V_ASN1_SEQUENCE
#define V_ASN1_SEQUENCE
Definition: asn1.h:136
X509_ALGOR_new
#define X509_ALGOR_new
Definition: boringssl_prefix_symbols.h:2256
error_ref_leak.err
err
Definition: error_ref_leak.py:35
ASN1_STRING_free
#define ASN1_STRING_free
Definition: boringssl_prefix_symbols.h:680
xds_manager.p
p
Definition: xds_manager.py:60
python_utils.upload_rbe_results.indent
indent
Definition: upload_rbe_results.py:183
X509_R_INVALID_PSS_PARAMETERS
#define X509_R_INVALID_PSS_PARAMETERS
Definition: x509.h:2389
rsa_pss_params_st::maskGenAlgorithm
X509_ALGOR * maskGenAlgorithm
Definition: x509.h:1846
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
ASN1_INTEGER_new
OPENSSL_EXPORT ASN1_INTEGER * ASN1_INTEGER_new(void)
IMPLEMENT_ASN1_FUNCTIONS
#define IMPLEMENT_ASN1_FUNCTIONS(stname)
Definition: asn1t.h:636
asn1_string_st::data
unsigned char * data
Definition: asn1.h:546
ASN1_PCTX
struct asn1_pctx_st ASN1_PCTX
Definition: base.h:338
EVP_PKEY_CTX_get_signature_md
#define EVP_PKEY_CTX_get_signature_md
Definition: boringssl_prefix_symbols.h:1593
env_md_ctx_st
Definition: digest.h:306
i2a_ASN1_INTEGER
#define i2a_ASN1_INTEGER
Definition: boringssl_prefix_symbols.h:3171
d2i_X509_ALGOR
#define d2i_X509_ALGOR
Definition: boringssl_prefix_symbols.h:3032
OBJ_nid2obj
#define OBJ_nid2obj
Definition: boringssl_prefix_symbols.h:1855
NID_rsassaPss
#define NID_rsassaPss
Definition: nid.h:4039
OBJ_obj2nid
#define OBJ_obj2nid
Definition: boringssl_prefix_symbols.h:1857
evp_pkey_ctx_st
Definition: third_party/boringssl-with-bazel/src/crypto/evp/internal.h:182
asn1_type_st::type
int type
Definition: asn1.h:1482
X509_algor_st::parameter
ASN1_TYPE * parameter
Definition: x509.h:115
ASN1_ITEM_st
Definition: asn1t.h:459
EVP_PKEY_bits
#define EVP_PKEY_bits
Definition: boringssl_prefix_symbols.h:1614
ASN1_INTEGER_set
#define ASN1_INTEGER_set
Definition: boringssl_prefix_symbols.h:648
evp_pkey_st
Definition: evp.h:1046
asn1_string_st::length
int length
Definition: asn1.h:544
EVP_MD_size
#define EVP_MD_size
Definition: boringssl_prefix_symbols.h:1579
NID_mgf1
#define NID_mgf1
Definition: nid.h:4034
EVP_PKEY_CTX_get0_pkey
#define EVP_PKEY_CTX_get0_pkey
Definition: boringssl_prefix_symbols.h:1587
ASN1_item_pack
#define ASN1_item_pack
Definition: boringssl_prefix_symbols.h:751
d2i_RSA_PSS_PARAMS
#define d2i_RSA_PSS_PARAMS
Definition: boringssl_prefix_symbols.h:3026
err.h
X509_ALGOR_set_md
OPENSSL_EXPORT void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
x509_rsa_pss_to_ctx
int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, const X509_ALGOR *sigalg, EVP_PKEY *pkey)
asn1t.h
internal.h
EVP_PKEY_size
#define EVP_PKEY_size
Definition: boringssl_prefix_symbols.h:1658
rsa_pss_params_st::saltLength
ASN1_INTEGER * saltLength
Definition: x509.h:1847
ASN1_OP_FREE_PRE
#define ASN1_OP_FREE_PRE
Definition: asn1t.h:597
x509_print_rsa_pss_params
int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, ASN1_PCTX *pctx)
NID_sha1
#define NID_sha1
Definition: nid.h:372
X509_algor_st
Definition: x509.h:113
rsa_pss_params_st::maskHash
X509_ALGOR * maskHash
Definition: x509.h:1852
benchmark.md
md
Definition: benchmark.py:86
i2a_ASN1_OBJECT
#define i2a_ASN1_OBJECT
Definition: boringssl_prefix_symbols.h:3172
x509_st
Definition: third_party/boringssl-with-bazel/src/crypto/x509/internal.h:139
rsa_pss_params_st
Definition: x509.h:1844
ASN1_ITEM_rptr
#define ASN1_ITEM_rptr(name)
Definition: asn1.h:302
ASN1_EXP_OPT
#define ASN1_EXP_OPT(stname, field, type, tag)
Definition: asn1t.h:279
RSA_PSS_PARAMS_new
#define RSA_PSS_PARAMS_new
Definition: boringssl_prefix_symbols.h:2080
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
BIO_puts
#define BIO_puts
Definition: boringssl_prefix_symbols.h:830
EVP_PKEY_CTX_set_rsa_mgf1_md
#define EVP_PKEY_CTX_set_rsa_mgf1_md
Definition: boringssl_prefix_symbols.h:1601
ASN1_VALUE
struct ASN1_VALUE_st ASN1_VALUE
Definition: asn1.h:320
EVP_sha1
const OPENSSL_EXPORT EVP_MD * EVP_sha1(void)
RSA_PKCS1_PSS_PADDING
#define RSA_PKCS1_PSS_PADDING
Definition: rsa.h:221
EVP_PKEY_CTX_set_rsa_padding
#define EVP_PKEY_CTX_set_rsa_padding
Definition: boringssl_prefix_symbols.h:1603
obj.h
asn1_type_st::value
union asn1_type_st::@361 value
EVP_get_digestbyobj
#define EVP_get_digestbyobj
Definition: boringssl_prefix_symbols.h:1728
EVP_PKEY_CTX_set_rsa_pss_saltlen
#define EVP_PKEY_CTX_set_rsa_pss_saltlen
Definition: boringssl_prefix_symbols.h:1607
rsa_pss_cb
static int rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
Definition: rsa_pss.c:70
ASN1_SEQUENCE_END_cb
#define ASN1_SEQUENCE_END_cb(stname, tname)
Definition: asn1t.h:161
ASN1_SEQUENCE_cb
#define ASN1_SEQUENCE_cb(tname, cb)
Definition: asn1t.h:147
asn1_string_st
Definition: asn1.h:543
BIO_indent
#define BIO_indent
Definition: boringssl_prefix_symbols.h:801
x509_rsa_ctx_to_pss
int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor)
asn1.h
x509.h
EVP_PKEY_CTX_get_rsa_pss_saltlen
#define EVP_PKEY_CTX_get_rsa_pss_saltlen
Definition: boringssl_prefix_symbols.h:1592


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:13