195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * project 2006.
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* ====================================================================
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the documentation and/or other materials provided with the
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    distribution.
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    software must display the following acknowledgment:
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software developed by the OpenSSL Project
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    endorse or promote products derived from this software without
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    prior written permission. For written permission, please contact
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    licensing@OpenSSL.org.
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5. Products derived from this software may not be called "OpenSSL"
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    nor may "OpenSSL" appear in their names without prior written
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    permission of the OpenSSL Project.
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6. Redistributions of any form whatsoever must retain the following
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    acknowledgment:
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software developed by the OpenSSL Project
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ====================================================================
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This product includes cryptographic software written by Eric Young
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Hudson (tjh@cryptsoft.com). */
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/evp.h>
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/bn.h>
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/buf.h>
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/digest.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h>
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/obj.h>
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/rsa.h>
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "../rsa/internal.h"
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "internal.h"
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleytypedef struct {
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* Key gen parameters */
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int nbits;
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  BIGNUM *pub_exp;
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* RSA padding mode */
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int pad_mode;
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* message digest */
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  const EVP_MD *md;
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* message digest for MGF1 */
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  const EVP_MD *mgf1md;
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* PSS salt length */
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int saltlen;
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* tbuf is a buffer which is either NULL, or is the size of the RSA modulus.
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley   * It's used to store the output of RSA operations. */
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  uint8_t *tbuf;
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* OAEP label */
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  uint8_t *oaep_label;
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  size_t oaep_labellen;
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} RSA_PKEY_CTX;
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_init(EVP_PKEY_CTX *ctx) {
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx;
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  rctx = OPENSSL_malloc(sizeof(RSA_PKEY_CTX));
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!rctx) {
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  memset(rctx, 0, sizeof(RSA_PKEY_CTX));
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  rctx->nbits = 2048;
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  rctx->pad_mode = RSA_PKCS1_PADDING;
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  rctx->saltlen = -2;
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->data = rctx;
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *dctx, *sctx;
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!pkey_rsa_init(dst)) {
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  sctx = src->data;
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dctx = dst->data;
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dctx->nbits = sctx->nbits;
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (sctx->pub_exp) {
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    dctx->pub_exp = BN_dup(sctx->pub_exp);
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!dctx->pub_exp) {
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dctx->pad_mode = sctx->pad_mode;
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dctx->md = sctx->md;
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dctx->mgf1md = sctx->mgf1md;
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (sctx->oaep_label) {
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (dctx->oaep_label) {
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_free(dctx->oaep_label);
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    dctx->oaep_label = BUF_memdup(sctx->oaep_label, sctx->oaep_labellen);
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!dctx->oaep_label) {
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    dctx->oaep_labellen = sctx->oaep_labellen;
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx) {
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx == NULL) {
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->pub_exp) {
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_free(rctx->pub_exp);
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->tbuf) {
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_free(rctx->tbuf);
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->oaep_label) {
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_free(rctx->oaep_label);
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  OPENSSL_free(rctx);
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) {
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->tbuf) {
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!ctx->tbuf) {
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                         const uint8_t *tbs, size_t tbslen) {
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA *rsa = ctx->pkey->pkey.rsa;
1735129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  const size_t key_len = EVP_PKEY_size(ctx->pkey);
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
1759b561e69b63266a34675ad610f3da76c899c5750David Benjamin  if (!sig) {
1765129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    *siglen = key_len;
1779b561e69b63266a34675ad610f3da76c899c5750David Benjamin    return 1;
1785129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  }
1795129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
1805129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  if (*siglen < key_len) {
1819b561e69b63266a34675ad610f3da76c899c5750David Benjamin    OPENSSL_PUT_ERROR(EVP, pkey_rsa_sign, EVP_R_BUFFER_TOO_SMALL);
1829b561e69b63266a34675ad610f3da76c899c5750David Benjamin    return 0;
1839b561e69b63266a34675ad610f3da76c899c5750David Benjamin  }
1849b561e69b63266a34675ad610f3da76c899c5750David Benjamin
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->md) {
1865129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    unsigned int out_len;
1875129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (tbslen != EVP_MD_size(rctx->md)) {
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(EVP, pkey_rsa_sign, EVP_R_INVALID_DIGEST_LENGTH);
1905129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      return 0;
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (EVP_MD_type(rctx->md) == NID_mdc2) {
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(EVP, pkey_rsa_sign, EVP_R_NO_MDC2_SUPPORT);
1955129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      return 0;
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
1985129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    switch (rctx->pad_mode) {
1995129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      case RSA_PKCS1_PADDING:
2005129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        if (!RSA_sign(EVP_MD_type(rctx->md), tbs, tbslen, sig, &out_len, rsa)) {
2015129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley          return 0;
2025129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        }
2035129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        *siglen = out_len;
2045129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        return 1;
2055129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
2065129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      case RSA_PKCS1_PSS_PADDING:
2075129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        if (!setup_tbuf(rctx, ctx) ||
2085129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley            !RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf, tbs, rctx->md,
2095129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                                            rctx->mgf1md, rctx->saltlen) ||
2105129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley            !RSA_encrypt(rsa, siglen, sig, *siglen, rctx->tbuf, key_len,
2115129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                         RSA_NO_PADDING)) {
2125129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley          return 0;
2135129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        }
2145129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        return 1;
2155129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
2165129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      default:
2175129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        return 0;
2185129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    }
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2215129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  return RSA_sign_raw(rsa, siglen, sig, *siglen, tbs, tbslen, rctx->pad_mode);
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           size_t siglen, const uint8_t *tbs,
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           size_t tbslen) {
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA *rsa = ctx->pkey->pkey.rsa;
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  size_t rslen;
2305129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  const size_t key_len = EVP_PKEY_size(ctx->pkey);
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->md) {
2335129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    switch (rctx->pad_mode) {
2345129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      case RSA_PKCS1_PADDING:
2355129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa);
2365129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
2375129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      case RSA_PKCS1_PSS_PADDING:
2385129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        if (!setup_tbuf(rctx, ctx) ||
2395129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley            !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
2405129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                            RSA_NO_PADDING) ||
2415129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley            !RSA_verify_PKCS1_PSS_mgf1(rsa, tbs, rctx->md, rctx->mgf1md,
2425129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                                       rctx->tbuf, rctx->saltlen)) {
2435129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley          return 0;
2445129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        }
2455129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        return 1;
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2475129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      default:
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2525129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  if (!setup_tbuf(rctx, ctx) ||
2535129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
2545129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                      rctx->pad_mode) ||
2555129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      rslen != tbslen ||
2565129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      CRYPTO_memcmp(tbs, rctx->tbuf, rslen) != 0) {
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                            const uint8_t *in, size_t inlen) {
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
2669b561e69b63266a34675ad610f3da76c899c5750David Benjamin  RSA *rsa = ctx->pkey->pkey.rsa;
2675129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  const size_t key_len = EVP_PKEY_size(ctx->pkey);
2689b561e69b63266a34675ad610f3da76c899c5750David Benjamin
2699b561e69b63266a34675ad610f3da76c899c5750David Benjamin  if (!out) {
2705129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    *outlen = key_len;
2719b561e69b63266a34675ad610f3da76c899c5750David Benjamin    return 1;
2725129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  }
2735129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
2745129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  if (*outlen < key_len) {
2759b561e69b63266a34675ad610f3da76c899c5750David Benjamin    OPENSSL_PUT_ERROR(EVP, pkey_rsa_encrypt, EVP_R_BUFFER_TOO_SMALL);
2769b561e69b63266a34675ad610f3da76c899c5750David Benjamin    return 0;
2779b561e69b63266a34675ad610f3da76c899c5750David Benjamin  }
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
2805129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    if (!setup_tbuf(rctx, ctx) ||
2815129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        !RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, key_len, in, inlen,
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                         rctx->oaep_label, rctx->oaep_labellen,
2835129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                                         rctx->md, rctx->mgf1md) ||
2845129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        !RSA_encrypt(rsa, outlen, out, *outlen, rctx->tbuf, key_len,
2855129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                     RSA_NO_PADDING)) {
2865129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      return 0;
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
2885129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    return 1;
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2915129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  return RSA_encrypt(rsa, outlen, out, *outlen, in, inlen, rctx->pad_mode);
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out,
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                            size_t *outlen, const uint8_t *in,
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                            size_t inlen) {
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
2989b561e69b63266a34675ad610f3da76c899c5750David Benjamin  RSA *rsa = ctx->pkey->pkey.rsa;
2995129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  const size_t key_len = EVP_PKEY_size(ctx->pkey);
3009b561e69b63266a34675ad610f3da76c899c5750David Benjamin
3019b561e69b63266a34675ad610f3da76c899c5750David Benjamin  if (!out) {
3025129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    *outlen = key_len;
3039b561e69b63266a34675ad610f3da76c899c5750David Benjamin    return 1;
3045129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  }
3055129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
3065129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  if (*outlen < key_len) {
3079b561e69b63266a34675ad610f3da76c899c5750David Benjamin    OPENSSL_PUT_ERROR(EVP, pkey_rsa_decrypt, EVP_R_BUFFER_TOO_SMALL);
3089b561e69b63266a34675ad610f3da76c899c5750David Benjamin    return 0;
3099b561e69b63266a34675ad610f3da76c899c5750David Benjamin  }
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
3125129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    size_t plaintext_len;
3135129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    int message_len;
3145129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
3155129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    if (!setup_tbuf(rctx, ctx) ||
3165129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        !RSA_decrypt(rsa, &plaintext_len, rctx->tbuf, key_len, in, inlen,
3175129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley                     RSA_NO_PADDING)) {
3185129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      return 0;
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3215129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    message_len = RSA_padding_check_PKCS1_OAEP_mgf1(
3225129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        out, key_len, rctx->tbuf, plaintext_len, rctx->oaep_label,
3235129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley        rctx->oaep_labellen, rctx->md, rctx->mgf1md);
3245129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    if (message_len < 0) {
3255129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley      return 0;
3265129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    }
3275129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    *outlen = message_len;
3285129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    return 1;
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3315129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  return RSA_decrypt(rsa, outlen, out, key_len, in, inlen, rctx->pad_mode);
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int check_padding_md(const EVP_MD *md, int padding) {
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!md) {
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (padding == RSA_NO_PADDING) {
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(EVP, check_padding_md, EVP_R_INVALID_PADDING_MODE);
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int is_known_padding(int padding_mode) {
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  switch (padding_mode) {
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case RSA_PKCS1_PADDING:
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case RSA_NO_PADDING:
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case RSA_PKCS1_OAEP_PADDING:
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case RSA_PKCS1_PSS_PADDING:
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    default:
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  switch (type) {
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_PADDING:
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) ||
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          (p1 == RSA_PKCS1_PSS_PADDING &&
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley           0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) ||
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          (p1 == RSA_PKCS1_OAEP_PADDING &&
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley           0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) {
36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl,
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                          EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) &&
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          rctx->md == NULL) {
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->md = EVP_sha1();
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      rctx->pad_mode = p1;
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_GET_RSA_PADDING:
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(int *)p2 = rctx->pad_mode;
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PSS_SALTLEN);
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        *(int *)p2 = rctx->saltlen;
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      } else {
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        if (p1 < -2) {
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          return -2;
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        }
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->saltlen = p1;
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (p1 < 256) {
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_KEYBITS);
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      rctx->nbits = p1;
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!p2) {
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      BN_free(rctx->pub_exp);
41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      rctx->pub_exp = p2;
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_OAEP_MD:
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) {
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        *(const EVP_MD **)p2 = rctx->md;
42395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      } else {
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->md = p2;
42595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
42695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_MD:
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!check_padding_md(p2, rctx->pad_mode)) {
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      rctx->md = p2;
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
43495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_GET_MD:
43695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(const EVP_MD **)p2 = rctx->md;
43795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_MGF1_MD:
44095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING &&
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
44395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_MGF1_MD);
44495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
44695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
44795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        if (rctx->mgf1md) {
44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          *(const EVP_MD **)p2 = rctx->mgf1md;
44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        } else {
45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          *(const EVP_MD **)p2 = rctx->md;
45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        }
45295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      } else {
45395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->mgf1md = p2;
45495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
45695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
45895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
46095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (rctx->oaep_label) {
46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_free(rctx->oaep_label);
46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (p2 && p1 > 0) {
46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        /* TODO(fork): this seems wrong. Shouldn't it take a copy of the
46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley         * buffer? */
46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->oaep_label = p2;
46995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->oaep_labellen = p1;
47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      } else {
47195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->oaep_label = NULL;
47295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        rctx->oaep_labellen = 0;
47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
47495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
47595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
47695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
47795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return -2;
48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
48195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *(uint8_t **)p2 = rctx->oaep_label;
48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return rctx->oaep_labellen;
48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case EVP_PKEY_CTRL_DIGESTINIT:
48595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
48695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    default:
48895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return -2;
48995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
49095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
49195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
49395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA *rsa = NULL;
49495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  RSA_PKEY_CTX *rctx = ctx->data;
49595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!rctx->pub_exp) {
49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    rctx->pub_exp = BN_new();
49895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4))
49995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
50095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
50195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  rsa = RSA_new();
50295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!rsa) {
50395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
50495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
50595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5065129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  if (!RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, NULL)) {
50795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    RSA_free(rsa);
5085129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley    return 0;
50995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
5105129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley
5115129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  EVP_PKEY_assign_RSA(pkey, rsa);
5125129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley  return 1;
51395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
51495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst EVP_PKEY_METHOD rsa_pkey_meth = {
5169b561e69b63266a34675ad610f3da76c899c5750David Benjamin    EVP_PKEY_RSA,           0 /* flags */,        pkey_rsa_init,
5179b561e69b63266a34675ad610f3da76c899c5750David Benjamin    pkey_rsa_copy,          pkey_rsa_cleanup,     0 /* paramgen_init */,
5189b561e69b63266a34675ad610f3da76c899c5750David Benjamin    0 /* paramgen */,       0 /* keygen_init */,  pkey_rsa_keygen,
5199b561e69b63266a34675ad610f3da76c899c5750David Benjamin    0 /* sign_init */,      pkey_rsa_sign,        0 /* verify_init */,
5209b561e69b63266a34675ad610f3da76c899c5750David Benjamin    pkey_rsa_verify,        0 /* signctx_init */, 0 /* signctx */,
5219b561e69b63266a34675ad610f3da76c899c5750David Benjamin    0 /* verifyctx_init */, 0 /* verifyctx */,    0 /* encrypt_init */,
5229b561e69b63266a34675ad610f3da76c899c5750David Benjamin    pkey_rsa_encrypt,       0 /* decrypt_init */, pkey_rsa_decrypt,
5239b561e69b63266a34675ad610f3da76c899c5750David Benjamin    0 /* derive_init */,    0 /* derive */,       pkey_rsa_ctrl,
52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley};
52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) {
52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING,
52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           padding, NULL);
52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) {
53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING,
53395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           0, out_padding);
53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) {
53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, NULL);
54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *out_salt_len) {
54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
54495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY),
54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, out_salt_len);
54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) {
54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL);
55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e) {
55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN,
55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e);
55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md);
56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void*) out_md);
56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void*) md);
57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA,
57695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
57795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md);
57895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
57995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, const uint8_t *label,
58195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                     size_t label_len) {
58295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int label_len_int = label_len;
58395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (((size_t) label_len_int) != label_len) {
58495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return -2;
58595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
58695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
58895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_RSA_OAEP_LABEL, label_len,
58995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           (void *)label);
59095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                     const uint8_t **out_label) {
59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *) out_label);
59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
597