1 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com). This product includes software written by Tim 54 * Hudson (tjh (at) 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 ASN1_SEQUENCE(RSA_PSS_PARAMS) = { 71 ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0), 72 ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1), 73 ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2), 74 ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3), 75 } ASN1_SEQUENCE_END(RSA_PSS_PARAMS) 76 77 IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS) 78 79 80 /* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */ 81 static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) { 82 if (alg == NULL || alg->parameter == NULL || 83 OBJ_obj2nid(alg->algorithm) != NID_mgf1 || 84 alg->parameter->type != V_ASN1_SEQUENCE) { 85 return NULL; 86 } 87 88 const uint8_t *p = alg->parameter->value.sequence->data; 89 int plen = alg->parameter->value.sequence->length; 90 return d2i_X509_ALGOR(NULL, &p, plen); 91 } 92 93 static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg, 94 X509_ALGOR **pmaskHash) { 95 *pmaskHash = NULL; 96 97 if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) { 98 return NULL; 99 } 100 101 const uint8_t *p = alg->parameter->value.sequence->data; 102 int plen = alg->parameter->value.sequence->length; 103 RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen); 104 if (pss == NULL) { 105 return NULL; 106 } 107 108 *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm); 109 return pss; 110 } 111 112 /* allocate and set algorithm ID from EVP_MD, default SHA1 */ 113 static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) { 114 if (EVP_MD_type(md) == NID_sha1) { 115 return 1; 116 } 117 *palg = X509_ALGOR_new(); 118 if (*palg == NULL) { 119 return 0; 120 } 121 X509_ALGOR_set_md(*palg, md); 122 return 1; 123 } 124 125 /* Allocate and set MGF1 algorithm ID from EVP_MD */ 126 static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) { 127 X509_ALGOR *algtmp = NULL; 128 ASN1_STRING *stmp = NULL; 129 *palg = NULL; 130 131 if (EVP_MD_type(mgf1md) == NID_sha1) { 132 return 1; 133 } 134 /* need to embed algorithm ID inside another */ 135 if (!rsa_md_to_algor(&algtmp, mgf1md) || 136 !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) { 137 goto err; 138 } 139 *palg = X509_ALGOR_new(); 140 if (!*palg) { 141 goto err; 142 } 143 X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp); 144 stmp = NULL; 145 146 err: 147 ASN1_STRING_free(stmp); 148 X509_ALGOR_free(algtmp); 149 if (*palg) { 150 return 1; 151 } 152 153 return 0; 154 } 155 156 /* convert algorithm ID to EVP_MD, default SHA1 */ 157 static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) { 158 const EVP_MD *md; 159 if (!alg) { 160 return EVP_sha1(); 161 } 162 md = EVP_get_digestbyobj(alg->algorithm); 163 if (md == NULL) { 164 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); 165 } 166 return md; 167 } 168 169 /* convert MGF1 algorithm ID to EVP_MD, default SHA1 */ 170 static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) { 171 const EVP_MD *md; 172 if (!alg) { 173 return EVP_sha1(); 174 } 175 /* Check mask and lookup mask hash algorithm */ 176 if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 || 177 maskHash == NULL) { 178 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); 179 return NULL; 180 } 181 md = EVP_get_digestbyobj(maskHash->algorithm); 182 if (md == NULL) { 183 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); 184 return NULL; 185 } 186 return md; 187 } 188 189 int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) { 190 const EVP_MD *sigmd, *mgf1md; 191 int saltlen; 192 if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) || 193 !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) || 194 !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) { 195 return 0; 196 } 197 198 EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx); 199 if (saltlen == -1) { 200 saltlen = EVP_MD_size(sigmd); 201 } else if (saltlen == -2) { 202 saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2; 203 if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) { 204 saltlen--; 205 } 206 } else { 207 return 0; 208 } 209 210 int ret = 0; 211 ASN1_STRING *os = NULL; 212 RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new(); 213 if (!pss) { 214 goto err; 215 } 216 217 if (saltlen != 20) { 218 pss->saltLength = ASN1_INTEGER_new(); 219 if (!pss->saltLength || 220 !ASN1_INTEGER_set(pss->saltLength, saltlen)) { 221 goto err; 222 } 223 } 224 225 if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) || 226 !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) { 227 goto err; 228 } 229 230 /* Finally create string with pss parameter encoding. */ 231 if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) { 232 goto err; 233 } 234 235 X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os); 236 os = NULL; 237 ret = 1; 238 239 err: 240 RSA_PSS_PARAMS_free(pss); 241 ASN1_STRING_free(os); 242 return ret; 243 } 244 245 int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { 246 assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); 247 248 /* Decode PSS parameters */ 249 int ret = 0; 250 X509_ALGOR *maskHash; 251 RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); 252 if (pss == NULL) { 253 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); 254 goto err; 255 } 256 257 const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); 258 const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm); 259 if (mgf1md == NULL || md == NULL) { 260 goto err; 261 } 262 263 int saltlen = 20; 264 if (pss->saltLength != NULL) { 265 saltlen = ASN1_INTEGER_get(pss->saltLength); 266 267 /* Could perform more salt length sanity checks but the main 268 * RSA routines will trap other invalid values anyway. */ 269 if (saltlen < 0) { 270 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); 271 goto err; 272 } 273 } 274 275 /* low-level routines support only trailer field 0xbc (value 1) 276 * and PKCS#1 says we should reject any other value anyway. */ 277 if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) { 278 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS); 279 goto err; 280 } 281 282 EVP_PKEY_CTX *pctx; 283 if (!EVP_DigestVerifyInit(ctx, &pctx, md, NULL, pkey) || 284 !EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || 285 !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, saltlen) || 286 !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md)) { 287 goto err; 288 } 289 290 ret = 1; 291 292 err: 293 RSA_PSS_PARAMS_free(pss); 294 X509_ALGOR_free(maskHash); 295 return ret; 296 } 297 298 int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent, 299 ASN1_PCTX *pctx) { 300 assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss); 301 302 int rv = 0; 303 X509_ALGOR *maskHash; 304 RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash); 305 if (!pss) { 306 if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) { 307 goto err; 308 } 309 rv = 1; 310 goto err; 311 } 312 313 if (BIO_puts(bp, "\n") <= 0 || 314 !BIO_indent(bp, indent, 128) || 315 BIO_puts(bp, "Hash Algorithm: ") <= 0) { 316 goto err; 317 } 318 319 if (pss->hashAlgorithm) { 320 if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) { 321 goto err; 322 } 323 } else if (BIO_puts(bp, "sha1 (default)") <= 0) { 324 goto err; 325 } 326 327 if (BIO_puts(bp, "\n") <= 0 || 328 !BIO_indent(bp, indent, 128) || 329 BIO_puts(bp, "Mask Algorithm: ") <= 0) { 330 goto err; 331 } 332 333 if (pss->maskGenAlgorithm) { 334 if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 || 335 BIO_puts(bp, " with ") <= 0) { 336 goto err; 337 } 338 339 if (maskHash) { 340 if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) { 341 goto err; 342 } 343 } else if (BIO_puts(bp, "INVALID") <= 0) { 344 goto err; 345 } 346 } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) { 347 goto err; 348 } 349 BIO_puts(bp, "\n"); 350 351 if (!BIO_indent(bp, indent, 128) || 352 BIO_puts(bp, "Salt Length: 0x") <= 0) { 353 goto err; 354 } 355 356 if (pss->saltLength) { 357 if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) { 358 goto err; 359 } 360 } else if (BIO_puts(bp, "14 (default)") <= 0) { 361 goto err; 362 } 363 BIO_puts(bp, "\n"); 364 365 if (!BIO_indent(bp, indent, 128) || 366 BIO_puts(bp, "Trailer Field: 0x") <= 0) { 367 goto err; 368 } 369 370 if (pss->trailerField) { 371 if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) { 372 goto err; 373 } 374 } else if (BIO_puts(bp, "BC (default)") <= 0) { 375 goto err; 376 } 377 BIO_puts(bp, "\n"); 378 379 rv = 1; 380 381 err: 382 RSA_PSS_PARAMS_free(pss); 383 X509_ALGOR_free(maskHash); 384 return rv; 385 } 386