Openssl 1.1.0h
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_saos.c rsa_err.c \
|
||||
rsa_pk1.c rsa_ssl.c rsa_none.c rsa_oaep.c rsa_chk.c rsa_null.c \
|
||||
rsa_pss.c rsa_x931.c rsa_asn1.c rsa_depr.c rsa_ameth.c rsa_prn.c \
|
||||
rsa_pmeth.c rsa_crpt.c rsa_x931g.c rsa_meth.c
|
||||
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/cms.h>
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include "rsa_locl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
static int rsa_cms_sign(CMS_SignerInfo *si);
|
||||
static int rsa_cms_verify(CMS_SignerInfo *si);
|
||||
static int rsa_cms_decrypt(CMS_RecipientInfo *ri);
|
||||
static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
|
||||
#endif
|
||||
|
||||
static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
|
||||
{
|
||||
unsigned char *penc = NULL;
|
||||
int penclen;
|
||||
penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc);
|
||||
if (penclen <= 0)
|
||||
return 0;
|
||||
if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA),
|
||||
V_ASN1_NULL, NULL, penc, penclen))
|
||||
return 1;
|
||||
|
||||
OPENSSL_free(penc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int pklen;
|
||||
RSA *rsa = NULL;
|
||||
|
||||
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey))
|
||||
return 0;
|
||||
if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) {
|
||||
RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign_RSA(pkey, rsa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
if (BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) != 0
|
||||
|| BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int old_rsa_priv_decode(EVP_PKEY *pkey,
|
||||
const unsigned char **pder, int derlen)
|
||||
{
|
||||
RSA *rsa;
|
||||
|
||||
if ((rsa = d2i_RSAPrivateKey(NULL, pder, derlen)) == NULL) {
|
||||
RSAerr(RSA_F_OLD_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign_RSA(pkey, rsa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
|
||||
{
|
||||
return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
|
||||
}
|
||||
|
||||
static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
|
||||
{
|
||||
unsigned char *rk = NULL;
|
||||
int rklen;
|
||||
rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
|
||||
|
||||
if (rklen <= 0) {
|
||||
RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_rsaEncryption), 0,
|
||||
V_ASN1_NULL, NULL, rk, rklen)) {
|
||||
RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int pklen;
|
||||
if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8))
|
||||
return 0;
|
||||
return old_rsa_priv_decode(pkey, &p, pklen);
|
||||
}
|
||||
|
||||
static int int_rsa_size(const EVP_PKEY *pkey)
|
||||
{
|
||||
return RSA_size(pkey->pkey.rsa);
|
||||
}
|
||||
|
||||
static int rsa_bits(const EVP_PKEY *pkey)
|
||||
{
|
||||
return BN_num_bits(pkey->pkey.rsa->n);
|
||||
}
|
||||
|
||||
static int rsa_security_bits(const EVP_PKEY *pkey)
|
||||
{
|
||||
return RSA_security_bits(pkey->pkey.rsa);
|
||||
}
|
||||
|
||||
static void int_rsa_free(EVP_PKEY *pkey)
|
||||
{
|
||||
RSA_free(pkey->pkey.rsa);
|
||||
}
|
||||
|
||||
static int do_rsa_print(BIO *bp, const RSA *x, int off, int priv)
|
||||
{
|
||||
char *str;
|
||||
const char *s;
|
||||
int ret = 0, mod_len = 0;
|
||||
|
||||
if (x->n != NULL)
|
||||
mod_len = BN_num_bits(x->n);
|
||||
|
||||
if (!BIO_indent(bp, off, 128))
|
||||
goto err;
|
||||
|
||||
if (priv && x->d) {
|
||||
if (BIO_printf(bp, "Private-Key: (%d bit)\n", mod_len) <= 0)
|
||||
goto err;
|
||||
str = "modulus:";
|
||||
s = "publicExponent:";
|
||||
} else {
|
||||
if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0)
|
||||
goto err;
|
||||
str = "Modulus:";
|
||||
s = "Exponent:";
|
||||
}
|
||||
if (!ASN1_bn_print(bp, str, x->n, NULL, off))
|
||||
goto err;
|
||||
if (!ASN1_bn_print(bp, s, x->e, NULL, off))
|
||||
goto err;
|
||||
if (priv) {
|
||||
if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off))
|
||||
goto err;
|
||||
if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off))
|
||||
goto err;
|
||||
if (!ASN1_bn_print(bp, "prime2:", x->q, NULL, off))
|
||||
goto err;
|
||||
if (!ASN1_bn_print(bp, "exponent1:", x->dmp1, NULL, off))
|
||||
goto err;
|
||||
if (!ASN1_bn_print(bp, "exponent2:", x->dmq1, NULL, off))
|
||||
goto err;
|
||||
if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off))
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
|
||||
}
|
||||
|
||||
static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
|
||||
}
|
||||
|
||||
/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
|
||||
static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg)
|
||||
{
|
||||
if (alg == NULL)
|
||||
return NULL;
|
||||
if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
|
||||
return NULL;
|
||||
return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
|
||||
alg->parameter);
|
||||
}
|
||||
|
||||
static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
|
||||
X509_ALGOR **pmaskHash)
|
||||
{
|
||||
RSA_PSS_PARAMS *pss;
|
||||
|
||||
*pmaskHash = NULL;
|
||||
|
||||
pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
|
||||
alg->parameter);
|
||||
|
||||
if (!pss)
|
||||
return NULL;
|
||||
|
||||
*pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
|
||||
|
||||
return pss;
|
||||
}
|
||||
|
||||
static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
|
||||
X509_ALGOR *maskHash, int indent)
|
||||
{
|
||||
int rv = 0;
|
||||
if (!pss) {
|
||||
if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto err;
|
||||
if (!BIO_indent(bp, indent, 128))
|
||||
goto err;
|
||||
if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
|
||||
goto err;
|
||||
|
||||
if (pss->hashAlgorithm) {
|
||||
if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "sha1 (default)") <= 0)
|
||||
goto err;
|
||||
|
||||
if (BIO_puts(bp, "\n") <= 0)
|
||||
goto err;
|
||||
|
||||
if (!BIO_indent(bp, indent, 128))
|
||||
goto err;
|
||||
|
||||
if (BIO_puts(bp, "Mask Algorithm: ") <= 0)
|
||||
goto err;
|
||||
if (pss->maskGenAlgorithm) {
|
||||
if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0)
|
||||
goto err;
|
||||
if (BIO_puts(bp, " with ") <= 0)
|
||||
goto err;
|
||||
if (maskHash) {
|
||||
if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "INVALID") <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0)
|
||||
goto err;
|
||||
BIO_puts(bp, "\n");
|
||||
|
||||
if (!BIO_indent(bp, indent, 128))
|
||||
goto err;
|
||||
if (BIO_puts(bp, "Salt Length: 0x") <= 0)
|
||||
goto err;
|
||||
if (pss->saltLength) {
|
||||
if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "14 (default)") <= 0)
|
||||
goto err;
|
||||
BIO_puts(bp, "\n");
|
||||
|
||||
if (!BIO_indent(bp, indent, 128))
|
||||
goto err;
|
||||
if (BIO_puts(bp, "Trailer Field: 0x") <= 0)
|
||||
goto err;
|
||||
if (pss->trailerField) {
|
||||
if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
|
||||
goto err;
|
||||
} else if (BIO_puts(bp, "BC (default)") <= 0)
|
||||
goto err;
|
||||
BIO_puts(bp, "\n");
|
||||
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
|
||||
const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx)
|
||||
{
|
||||
if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss) {
|
||||
int rv;
|
||||
RSA_PSS_PARAMS *pss;
|
||||
X509_ALGOR *maskHash;
|
||||
pss = rsa_pss_decode(sigalg, &maskHash);
|
||||
rv = rsa_pss_param_print(bp, pss, maskHash, indent);
|
||||
RSA_PSS_PARAMS_free(pss);
|
||||
X509_ALGOR_free(maskHash);
|
||||
if (!rv)
|
||||
return 0;
|
||||
} else if (!sig && BIO_puts(bp, "\n") <= 0)
|
||||
return 0;
|
||||
if (sig)
|
||||
return X509_signature_dump(bp, sig, indent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
{
|
||||
X509_ALGOR *alg = NULL;
|
||||
switch (op) {
|
||||
|
||||
case ASN1_PKEY_CTRL_PKCS7_SIGN:
|
||||
if (arg1 == 0)
|
||||
PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, NULL, &alg);
|
||||
break;
|
||||
|
||||
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
|
||||
if (arg1 == 0)
|
||||
PKCS7_RECIP_INFO_get0_alg(arg2, &alg);
|
||||
break;
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case ASN1_PKEY_CTRL_CMS_SIGN:
|
||||
if (arg1 == 0)
|
||||
return rsa_cms_sign(arg2);
|
||||
else if (arg1 == 1)
|
||||
return rsa_cms_verify(arg2);
|
||||
break;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
|
||||
if (arg1 == 0)
|
||||
return rsa_cms_encrypt(arg2);
|
||||
else if (arg1 == 1)
|
||||
return rsa_cms_decrypt(arg2);
|
||||
break;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
|
||||
*(int *)arg2 = CMS_RECIPINFO_TRANS;
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha256;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
|
||||
if (alg)
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* allocate and set algorithm ID from EVP_MD, default SHA1 */
|
||||
static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md)
|
||||
{
|
||||
if (EVP_MD_type(md) == NID_sha1)
|
||||
return 1;
|
||||
*palg = X509_ALGOR_new();
|
||||
if (*palg == NULL)
|
||||
return 0;
|
||||
X509_ALGOR_set_md(*palg, md);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate and set MGF1 algorithm ID from EVP_MD */
|
||||
static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
|
||||
{
|
||||
X509_ALGOR *algtmp = NULL;
|
||||
ASN1_STRING *stmp = NULL;
|
||||
*palg = NULL;
|
||||
if (EVP_MD_type(mgf1md) == NID_sha1)
|
||||
return 1;
|
||||
/* need to embed algorithm ID inside another */
|
||||
if (!rsa_md_to_algor(&algtmp, mgf1md))
|
||||
goto err;
|
||||
if (!ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp))
|
||||
goto err;
|
||||
*palg = X509_ALGOR_new();
|
||||
if (*palg == NULL)
|
||||
goto err;
|
||||
X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
|
||||
stmp = NULL;
|
||||
err:
|
||||
ASN1_STRING_free(stmp);
|
||||
X509_ALGOR_free(algtmp);
|
||||
if (*palg)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* convert algorithm ID to EVP_MD, default SHA1 */
|
||||
static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
if (!alg)
|
||||
return EVP_sha1();
|
||||
md = EVP_get_digestbyobj(alg->algorithm);
|
||||
if (md == NULL)
|
||||
RSAerr(RSA_F_RSA_ALGOR_TO_MD, RSA_R_UNKNOWN_DIGEST);
|
||||
return md;
|
||||
}
|
||||
|
||||
/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
|
||||
static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
if (!alg)
|
||||
return EVP_sha1();
|
||||
/* Check mask and lookup mask hash algorithm */
|
||||
if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
|
||||
RSAerr(RSA_F_RSA_MGF1_TO_MD, RSA_R_UNSUPPORTED_MASK_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
if (!maskHash) {
|
||||
RSAerr(RSA_F_RSA_MGF1_TO_MD, RSA_R_UNSUPPORTED_MASK_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
md = EVP_get_digestbyobj(maskHash->algorithm);
|
||||
if (md == NULL) {
|
||||
RSAerr(RSA_F_RSA_MGF1_TO_MD, RSA_R_UNKNOWN_MASK_DIGEST);
|
||||
return NULL;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert EVP_PKEY_CTX is PSS mode into corresponding algorithm parameter,
|
||||
* suitable for setting an AlgorithmIdentifier.
|
||||
*/
|
||||
|
||||
static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
|
||||
{
|
||||
const EVP_MD *sigmd, *mgf1md;
|
||||
RSA_PSS_PARAMS *pss = NULL;
|
||||
ASN1_STRING *os = NULL;
|
||||
EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
|
||||
int saltlen, rv = 0;
|
||||
if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
|
||||
goto err;
|
||||
if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
|
||||
goto err;
|
||||
if (saltlen == -1)
|
||||
saltlen = EVP_MD_size(sigmd);
|
||||
else if (saltlen == -2) {
|
||||
saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
|
||||
if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0)
|
||||
saltlen--;
|
||||
}
|
||||
pss = RSA_PSS_PARAMS_new();
|
||||
if (pss == NULL)
|
||||
goto err;
|
||||
if (saltlen != 20) {
|
||||
pss->saltLength = ASN1_INTEGER_new();
|
||||
if (pss->saltLength == NULL)
|
||||
goto err;
|
||||
if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
|
||||
goto err;
|
||||
}
|
||||
if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
|
||||
goto err;
|
||||
if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
|
||||
goto err;
|
||||
/* Finally create string with pss parameter encoding. */
|
||||
if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os))
|
||||
goto err;
|
||||
rv = 1;
|
||||
err:
|
||||
RSA_PSS_PARAMS_free(pss);
|
||||
if (rv)
|
||||
return os;
|
||||
ASN1_STRING_free(os);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* From PSS AlgorithmIdentifier set public key parameters. If pkey isn't NULL
|
||||
* then the EVP_MD_CTX is setup and initialised. If it is NULL parameters are
|
||||
* passed to pkctx instead.
|
||||
*/
|
||||
|
||||
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
|
||||
X509_ALGOR *sigalg, EVP_PKEY *pkey)
|
||||
{
|
||||
int rv = -1;
|
||||
int saltlen;
|
||||
const EVP_MD *mgf1md = NULL, *md = NULL;
|
||||
RSA_PSS_PARAMS *pss;
|
||||
X509_ALGOR *maskHash;
|
||||
/* Sanity check: make sure it is PSS */
|
||||
if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
|
||||
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
|
||||
return -1;
|
||||
}
|
||||
/* Decode PSS parameters */
|
||||
pss = rsa_pss_decode(sigalg, &maskHash);
|
||||
|
||||
if (pss == NULL) {
|
||||
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
|
||||
if (!mgf1md)
|
||||
goto err;
|
||||
md = rsa_algor_to_md(pss->hashAlgorithm);
|
||||
if (!md)
|
||||
goto err;
|
||||
|
||||
if (pss->saltLength) {
|
||||
saltlen = ASN1_INTEGER_get(pss->saltLength);
|
||||
|
||||
/*
|
||||
* Could perform more salt length sanity checks but the main RSA
|
||||
* routines will trap other invalid values anyway.
|
||||
*/
|
||||
if (saltlen < 0) {
|
||||
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_SALT_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
saltlen = 20;
|
||||
|
||||
/*
|
||||
* low-level routines support only trailer field 0xbc (value 1) and
|
||||
* PKCS#1 says we should reject any other value anyway.
|
||||
*/
|
||||
if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
|
||||
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_TRAILER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We have all parameters now set up context */
|
||||
|
||||
if (pkey) {
|
||||
if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
|
||||
goto err;
|
||||
} else {
|
||||
const EVP_MD *checkmd;
|
||||
if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0)
|
||||
goto err;
|
||||
if (EVP_MD_type(md) != EVP_MD_type(checkmd)) {
|
||||
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
|
||||
goto err;
|
||||
/* Carry on */
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
RSA_PSS_PARAMS_free(pss);
|
||||
X509_ALGOR_free(maskHash);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
static int rsa_cms_verify(CMS_SignerInfo *si)
|
||||
{
|
||||
int nid, nid2;
|
||||
X509_ALGOR *alg;
|
||||
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
|
||||
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
|
||||
nid = OBJ_obj2nid(alg->algorithm);
|
||||
if (nid == NID_rsaEncryption)
|
||||
return 1;
|
||||
if (nid == NID_rsassaPss)
|
||||
return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
|
||||
/* Workaround for some implementation that use a signature OID */
|
||||
if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
|
||||
if (nid2 == NID_rsaEncryption)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Customised RSA item verification routine. This is called when a signature
|
||||
* is encountered requiring special handling. We currently only handle PSS.
|
||||
*/
|
||||
|
||||
static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
|
||||
X509_ALGOR *sigalg, ASN1_BIT_STRING *sig,
|
||||
EVP_PKEY *pkey)
|
||||
{
|
||||
/* Sanity check: make sure it is PSS */
|
||||
if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
|
||||
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
|
||||
return -1;
|
||||
}
|
||||
if (rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) {
|
||||
/* Carry on */
|
||||
return 2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
static int rsa_cms_sign(CMS_SignerInfo *si)
|
||||
{
|
||||
int pad_mode = RSA_PKCS1_PADDING;
|
||||
X509_ALGOR *alg;
|
||||
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
|
||||
ASN1_STRING *os = NULL;
|
||||
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
|
||||
if (pkctx) {
|
||||
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (pad_mode == RSA_PKCS1_PADDING) {
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
/* We don't support it */
|
||||
if (pad_mode != RSA_PKCS1_PSS_PADDING)
|
||||
return 0;
|
||||
os = rsa_ctx_to_pss(pkctx);
|
||||
if (!os)
|
||||
return 0;
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
|
||||
X509_ALGOR *alg1, X509_ALGOR *alg2,
|
||||
ASN1_BIT_STRING *sig)
|
||||
{
|
||||
int pad_mode;
|
||||
EVP_PKEY_CTX *pkctx = EVP_MD_CTX_pkey_ctx(ctx);
|
||||
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
|
||||
return 0;
|
||||
if (pad_mode == RSA_PKCS1_PADDING)
|
||||
return 2;
|
||||
if (pad_mode == RSA_PKCS1_PSS_PADDING) {
|
||||
ASN1_STRING *os1 = NULL;
|
||||
os1 = rsa_ctx_to_pss(pkctx);
|
||||
if (!os1)
|
||||
return 0;
|
||||
/* Duplicate parameters if we have to */
|
||||
if (alg2) {
|
||||
ASN1_STRING *os2 = ASN1_STRING_dup(os1);
|
||||
if (!os2) {
|
||||
ASN1_STRING_free(os1);
|
||||
return 0;
|
||||
}
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_rsassaPss),
|
||||
V_ASN1_SEQUENCE, os2);
|
||||
}
|
||||
X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_rsassaPss),
|
||||
V_ASN1_SEQUENCE, os1);
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg,
|
||||
X509_ALGOR **pmaskHash)
|
||||
{
|
||||
RSA_OAEP_PARAMS *pss;
|
||||
|
||||
*pmaskHash = NULL;
|
||||
|
||||
pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
|
||||
alg->parameter);
|
||||
|
||||
if (!pss)
|
||||
return NULL;
|
||||
|
||||
*pmaskHash = rsa_mgf1_decode(pss->maskGenFunc);
|
||||
|
||||
return pss;
|
||||
}
|
||||
|
||||
static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
EVP_PKEY_CTX *pkctx;
|
||||
X509_ALGOR *cmsalg;
|
||||
int nid;
|
||||
int rv = -1;
|
||||
unsigned char *label = NULL;
|
||||
int labellen = 0;
|
||||
const EVP_MD *mgf1md = NULL, *md = NULL;
|
||||
RSA_OAEP_PARAMS *oaep;
|
||||
X509_ALGOR *maskHash;
|
||||
pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (!pkctx)
|
||||
return 0;
|
||||
if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
|
||||
return -1;
|
||||
nid = OBJ_obj2nid(cmsalg->algorithm);
|
||||
if (nid == NID_rsaEncryption)
|
||||
return 1;
|
||||
if (nid != NID_rsaesOaep) {
|
||||
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE);
|
||||
return -1;
|
||||
}
|
||||
/* Decode OAEP parameters */
|
||||
oaep = rsa_oaep_decode(cmsalg, &maskHash);
|
||||
|
||||
if (oaep == NULL) {
|
||||
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mgf1md = rsa_mgf1_to_md(oaep->maskGenFunc, maskHash);
|
||||
if (!mgf1md)
|
||||
goto err;
|
||||
md = rsa_algor_to_md(oaep->hashFunc);
|
||||
if (!md)
|
||||
goto err;
|
||||
|
||||
if (oaep->pSourceFunc) {
|
||||
X509_ALGOR *plab = oaep->pSourceFunc;
|
||||
if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
|
||||
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE);
|
||||
goto err;
|
||||
}
|
||||
if (plab->parameter->type != V_ASN1_OCTET_STRING) {
|
||||
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
label = plab->parameter->value.octet_string->data;
|
||||
/* Stop label being freed when OAEP parameters are freed */
|
||||
plab->parameter->value.octet_string->data = NULL;
|
||||
labellen = plab->parameter->value.octet_string->length;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
|
||||
goto err;
|
||||
/* Carry on */
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
RSA_OAEP_PARAMS_free(oaep);
|
||||
X509_ALGOR_free(maskHash);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
const EVP_MD *md, *mgf1md;
|
||||
RSA_OAEP_PARAMS *oaep = NULL;
|
||||
ASN1_STRING *os = NULL;
|
||||
X509_ALGOR *alg;
|
||||
EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
|
||||
unsigned char *label;
|
||||
if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
|
||||
return 0;
|
||||
if (pkctx) {
|
||||
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (pad_mode == RSA_PKCS1_PADDING) {
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
/* Not supported */
|
||||
if (pad_mode != RSA_PKCS1_OAEP_PADDING)
|
||||
return 0;
|
||||
if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
|
||||
goto err;
|
||||
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
|
||||
goto err;
|
||||
labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
|
||||
if (labellen < 0)
|
||||
goto err;
|
||||
oaep = RSA_OAEP_PARAMS_new();
|
||||
if (oaep == NULL)
|
||||
goto err;
|
||||
if (!rsa_md_to_algor(&oaep->hashFunc, md))
|
||||
goto err;
|
||||
if (!rsa_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
|
||||
goto err;
|
||||
if (labellen > 0) {
|
||||
ASN1_OCTET_STRING *los;
|
||||
oaep->pSourceFunc = X509_ALGOR_new();
|
||||
if (oaep->pSourceFunc == NULL)
|
||||
goto err;
|
||||
los = ASN1_OCTET_STRING_new();
|
||||
if (los == NULL)
|
||||
goto err;
|
||||
if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
|
||||
ASN1_OCTET_STRING_free(los);
|
||||
goto err;
|
||||
}
|
||||
X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
|
||||
V_ASN1_OCTET_STRING, los);
|
||||
}
|
||||
/* create string with pss parameter encoding. */
|
||||
if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
|
||||
goto err;
|
||||
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
|
||||
os = NULL;
|
||||
rv = 1;
|
||||
err:
|
||||
RSA_OAEP_PARAMS_free(oaep);
|
||||
ASN1_STRING_free(os);
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
|
||||
{
|
||||
EVP_PKEY_RSA,
|
||||
EVP_PKEY_RSA,
|
||||
ASN1_PKEY_SIGPARAM_NULL,
|
||||
|
||||
"RSA",
|
||||
"OpenSSL RSA method",
|
||||
|
||||
rsa_pub_decode,
|
||||
rsa_pub_encode,
|
||||
rsa_pub_cmp,
|
||||
rsa_pub_print,
|
||||
|
||||
rsa_priv_decode,
|
||||
rsa_priv_encode,
|
||||
rsa_priv_print,
|
||||
|
||||
int_rsa_size,
|
||||
rsa_bits,
|
||||
rsa_security_bits,
|
||||
|
||||
0, 0, 0, 0, 0, 0,
|
||||
|
||||
rsa_sig_print,
|
||||
int_rsa_free,
|
||||
rsa_pkey_ctrl,
|
||||
old_rsa_priv_decode,
|
||||
old_rsa_priv_encode,
|
||||
rsa_item_verify,
|
||||
rsa_item_sign},
|
||||
|
||||
{
|
||||
EVP_PKEY_RSA2,
|
||||
EVP_PKEY_RSA,
|
||||
ASN1_PKEY_ALIAS}
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
/* Override the default free and new methods */
|
||||
static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
if (operation == ASN1_OP_NEW_PRE) {
|
||||
*pval = (ASN1_VALUE *)RSA_new();
|
||||
if (*pval != NULL)
|
||||
return 2;
|
||||
return 0;
|
||||
} else if (operation == ASN1_OP_FREE_PRE) {
|
||||
RSA_free((RSA *)*pval);
|
||||
*pval = NULL;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
|
||||
ASN1_SIMPLE(RSA, version, LONG),
|
||||
ASN1_SIMPLE(RSA, n, BIGNUM),
|
||||
ASN1_SIMPLE(RSA, e, BIGNUM),
|
||||
ASN1_SIMPLE(RSA, d, CBIGNUM),
|
||||
ASN1_SIMPLE(RSA, p, CBIGNUM),
|
||||
ASN1_SIMPLE(RSA, q, CBIGNUM),
|
||||
ASN1_SIMPLE(RSA, dmp1, CBIGNUM),
|
||||
ASN1_SIMPLE(RSA, dmq1, CBIGNUM),
|
||||
ASN1_SIMPLE(RSA, iqmp, CBIGNUM)
|
||||
} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey)
|
||||
|
||||
|
||||
ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = {
|
||||
ASN1_SIMPLE(RSA, n, BIGNUM),
|
||||
ASN1_SIMPLE(RSA, e, BIGNUM),
|
||||
} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey)
|
||||
|
||||
ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
|
||||
ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
|
||||
ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
|
||||
ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
|
||||
ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3)
|
||||
} ASN1_SEQUENCE_END(RSA_PSS_PARAMS)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
|
||||
|
||||
ASN1_SEQUENCE(RSA_OAEP_PARAMS) = {
|
||||
ASN1_EXP_OPT(RSA_OAEP_PARAMS, hashFunc, X509_ALGOR, 0),
|
||||
ASN1_EXP_OPT(RSA_OAEP_PARAMS, maskGenFunc, X509_ALGOR, 1),
|
||||
ASN1_EXP_OPT(RSA_OAEP_PARAMS, pSourceFunc, X509_ALGOR, 2),
|
||||
} ASN1_SEQUENCE_END(RSA_OAEP_PARAMS)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS)
|
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey)
|
||||
|
||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey)
|
||||
|
||||
RSA *RSAPublicKey_dup(RSA *rsa)
|
||||
{
|
||||
return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), rsa);
|
||||
}
|
||||
|
||||
RSA *RSAPrivateKey_dup(RSA *rsa)
|
||||
{
|
||||
return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), rsa);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
int RSA_check_key(const RSA *key)
|
||||
{
|
||||
return RSA_check_key_ex(key, NULL);
|
||||
}
|
||||
|
||||
int RSA_check_key_ex(const RSA *key, BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *i, *j, *k, *l, *m;
|
||||
BN_CTX *ctx;
|
||||
int ret = 1;
|
||||
|
||||
if (key->p == NULL || key->q == NULL || key->n == NULL
|
||||
|| key->e == NULL || key->d == NULL) {
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_VALUE_MISSING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = BN_new();
|
||||
j = BN_new();
|
||||
k = BN_new();
|
||||
l = BN_new();
|
||||
m = BN_new();
|
||||
ctx = BN_CTX_new();
|
||||
if (i == NULL || j == NULL || k == NULL || l == NULL
|
||||
|| m == NULL || ctx == NULL) {
|
||||
ret = -1;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_is_one(key->e)) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
|
||||
}
|
||||
if (!BN_is_odd(key->e)) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_BAD_E_VALUE);
|
||||
}
|
||||
|
||||
/* p prime? */
|
||||
if (BN_is_prime_ex(key->p, BN_prime_checks, NULL, cb) != 1) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_P_NOT_PRIME);
|
||||
}
|
||||
|
||||
/* q prime? */
|
||||
if (BN_is_prime_ex(key->q, BN_prime_checks, NULL, cb) != 1) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_Q_NOT_PRIME);
|
||||
}
|
||||
|
||||
/* n = p*q? */
|
||||
if (!BN_mul(i, key->p, key->q, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (BN_cmp(i, key->n) != 0) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
|
||||
}
|
||||
|
||||
/* d*e = 1 mod lcm(p-1,q-1)? */
|
||||
if (!BN_sub(i, key->p, BN_value_one())) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_sub(j, key->q, BN_value_one())) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* now compute k = lcm(i,j) */
|
||||
if (!BN_mul(l, i, j, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_gcd(m, i, j, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_div(k, NULL, l, m, ctx)) { /* remainder is 0 */
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod_mul(i, key->d, key->e, k, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_is_one(i)) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_D_E_NOT_CONGRUENT_TO_1);
|
||||
}
|
||||
|
||||
if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
|
||||
/* dmp1 = d mod (p-1)? */
|
||||
if (!BN_sub(i, key->p, BN_value_one())) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod(j, key->d, i, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (BN_cmp(j, key->dmp1) != 0) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMP1_NOT_CONGRUENT_TO_D);
|
||||
}
|
||||
|
||||
/* dmq1 = d mod (q-1)? */
|
||||
if (!BN_sub(i, key->q, BN_value_one())) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod(j, key->d, i, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (BN_cmp(j, key->dmq1) != 0) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
|
||||
}
|
||||
|
||||
/* iqmp = q^-1 mod p? */
|
||||
if (!BN_mod_inverse(i, key->q, key->p, ctx)) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
if (BN_cmp(i, key->iqmp) != 0) {
|
||||
ret = 0;
|
||||
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_IQMP_NOT_INVERSE_OF_Q);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
BN_free(i);
|
||||
BN_free(j);
|
||||
BN_free(k);
|
||||
BN_free(l);
|
||||
BN_free(m);
|
||||
BN_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/lhash.h>
|
||||
#include "internal/bn_int.h"
|
||||
#include <openssl/rand.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
int RSA_bits(const RSA *r)
|
||||
{
|
||||
return (BN_num_bits(r->n));
|
||||
}
|
||||
|
||||
int RSA_size(const RSA *r)
|
||||
{
|
||||
return (BN_num_bytes(r->n));
|
||||
}
|
||||
|
||||
int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||
RSA *rsa, int padding)
|
||||
{
|
||||
return (rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding));
|
||||
}
|
||||
|
||||
int RSA_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
return (rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding));
|
||||
}
|
||||
|
||||
int RSA_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
return (rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding));
|
||||
}
|
||||
|
||||
int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||
RSA *rsa, int padding)
|
||||
{
|
||||
return (rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding));
|
||||
}
|
||||
|
||||
int RSA_flags(const RSA *r)
|
||||
{
|
||||
return ((r == NULL) ? 0 : r->meth->flags);
|
||||
}
|
||||
|
||||
void RSA_blinding_off(RSA *rsa)
|
||||
{
|
||||
BN_BLINDING_free(rsa->blinding);
|
||||
rsa->blinding = NULL;
|
||||
rsa->flags &= ~RSA_FLAG_BLINDING;
|
||||
rsa->flags |= RSA_FLAG_NO_BLINDING;
|
||||
}
|
||||
|
||||
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (rsa->blinding != NULL)
|
||||
RSA_blinding_off(rsa);
|
||||
|
||||
rsa->blinding = RSA_setup_blinding(rsa, ctx);
|
||||
if (rsa->blinding == NULL)
|
||||
goto err;
|
||||
|
||||
rsa->flags |= RSA_FLAG_BLINDING;
|
||||
rsa->flags &= ~RSA_FLAG_NO_BLINDING;
|
||||
ret = 1;
|
||||
err:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
|
||||
const BIGNUM *q, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *ret = NULL, *r0, *r1, *r2;
|
||||
|
||||
if (d == NULL || p == NULL || q == NULL)
|
||||
return NULL;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
r0 = BN_CTX_get(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
r2 = BN_CTX_get(ctx);
|
||||
if (r2 == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_sub(r1, p, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_sub(r2, q, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_mul(r0, r1, r2, ctx))
|
||||
goto err;
|
||||
|
||||
ret = BN_mod_inverse(NULL, d, r0, ctx);
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
|
||||
{
|
||||
BIGNUM *e;
|
||||
BN_CTX *ctx;
|
||||
BN_BLINDING *ret = NULL;
|
||||
|
||||
if (in_ctx == NULL) {
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
} else
|
||||
ctx = in_ctx;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
e = BN_CTX_get(ctx);
|
||||
if (e == NULL) {
|
||||
RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->e == NULL) {
|
||||
e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
|
||||
if (e == NULL) {
|
||||
RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
e = rsa->e;
|
||||
|
||||
if ((RAND_status() == 0) && rsa->d != NULL
|
||||
&& bn_get_words(rsa->d) != NULL) {
|
||||
/*
|
||||
* if PRNG is not properly seeded, resort to secret exponent as
|
||||
* unpredictable seed
|
||||
*/
|
||||
RAND_add(bn_get_words(rsa->d), bn_get_dmax(rsa->d) * sizeof(BN_ULONG),
|
||||
0.0);
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM *n = BN_new();
|
||||
|
||||
if (n == NULL) {
|
||||
RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
|
||||
|
||||
ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
|
||||
rsa->_method_mod_n);
|
||||
/* We MUST free n before any further use of rsa->n */
|
||||
BN_free(n);
|
||||
}
|
||||
if (ret == NULL) {
|
||||
RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_BLINDING_set_current_thread(ret);
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (ctx != in_ctx)
|
||||
BN_CTX_free(ctx);
|
||||
if (e != rsa->e)
|
||||
BN_free(e);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* NB: This file contains deprecated functions (compatibility wrappers to the
|
||||
* "new" versions).
|
||||
*/
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
#if OPENSSL_API_COMPAT >= 0x00908000L
|
||||
NON_EMPTY_TRANSLATION_UNIT
|
||||
|
||||
#else
|
||||
|
||||
# include <stdio.h>
|
||||
# include <time.h>
|
||||
# include "internal/cryptlib.h"
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/rsa.h>
|
||||
|
||||
RSA *RSA_generate_key(int bits, unsigned long e_value,
|
||||
void (*callback) (int, int, void *), void *cb_arg)
|
||||
{
|
||||
int i;
|
||||
BN_GENCB *cb = BN_GENCB_new();
|
||||
RSA *rsa = RSA_new();
|
||||
BIGNUM *e = BN_new();
|
||||
|
||||
if (cb == NULL || rsa == NULL || e == NULL)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* The problem is when building with 8, 16, or 32 BN_ULONG, unsigned long
|
||||
* can be larger
|
||||
*/
|
||||
for (i = 0; i < (int)sizeof(unsigned long) * 8; i++) {
|
||||
if (e_value & (1UL << i))
|
||||
if (BN_set_bit(e, i) == 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_GENCB_set_old(cb, callback, cb_arg);
|
||||
|
||||
if (RSA_generate_key_ex(rsa, bits, e, cb)) {
|
||||
BN_free(e);
|
||||
BN_GENCB_free(cb);
|
||||
return rsa;
|
||||
}
|
||||
err:
|
||||
BN_free(e);
|
||||
RSA_free(rsa);
|
||||
BN_GENCB_free(cb);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_RSA,func,0)
|
||||
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_RSA,0,reason)
|
||||
|
||||
static ERR_STRING_DATA RSA_str_functs[] = {
|
||||
{ERR_FUNC(RSA_F_CHECK_PADDING_MD), "check_padding_md"},
|
||||
{ERR_FUNC(RSA_F_ENCODE_PKCS1), "encode_pkcs1"},
|
||||
{ERR_FUNC(RSA_F_INT_RSA_VERIFY), "int_rsa_verify"},
|
||||
{ERR_FUNC(RSA_F_OLD_RSA_PRIV_DECODE), "old_rsa_priv_decode"},
|
||||
{ERR_FUNC(RSA_F_PKEY_RSA_CTRL), "pkey_rsa_ctrl"},
|
||||
{ERR_FUNC(RSA_F_PKEY_RSA_CTRL_STR), "pkey_rsa_ctrl_str"},
|
||||
{ERR_FUNC(RSA_F_PKEY_RSA_SIGN), "pkey_rsa_sign"},
|
||||
{ERR_FUNC(RSA_F_PKEY_RSA_VERIFY), "pkey_rsa_verify"},
|
||||
{ERR_FUNC(RSA_F_PKEY_RSA_VERIFYRECOVER), "pkey_rsa_verifyrecover"},
|
||||
{ERR_FUNC(RSA_F_RSA_ALGOR_TO_MD), "rsa_algor_to_md"},
|
||||
{ERR_FUNC(RSA_F_RSA_BUILTIN_KEYGEN), "rsa_builtin_keygen"},
|
||||
{ERR_FUNC(RSA_F_RSA_CHECK_KEY), "RSA_check_key"},
|
||||
{ERR_FUNC(RSA_F_RSA_CHECK_KEY_EX), "RSA_check_key_ex"},
|
||||
{ERR_FUNC(RSA_F_RSA_CMS_DECRYPT), "rsa_cms_decrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_ITEM_VERIFY), "rsa_item_verify"},
|
||||
{ERR_FUNC(RSA_F_RSA_METH_DUP), "RSA_meth_dup"},
|
||||
{ERR_FUNC(RSA_F_RSA_METH_NEW), "RSA_meth_new"},
|
||||
{ERR_FUNC(RSA_F_RSA_METH_SET1_NAME), "RSA_meth_set1_name"},
|
||||
{ERR_FUNC(RSA_F_RSA_MGF1_TO_MD), "rsa_mgf1_to_md"},
|
||||
{ERR_FUNC(RSA_F_RSA_NEW_METHOD), "RSA_new_method"},
|
||||
{ERR_FUNC(RSA_F_RSA_NULL), "RSA_NULL"},
|
||||
{ERR_FUNC(RSA_F_RSA_NULL_PRIVATE_DECRYPT), "RSA_null_private_decrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_NULL_PRIVATE_ENCRYPT), "RSA_null_private_encrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_NULL_PUBLIC_DECRYPT), "RSA_null_public_decrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_NULL_PUBLIC_ENCRYPT), "RSA_null_public_encrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_OSSL_PRIVATE_DECRYPT), "rsa_ossl_private_decrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT), "rsa_ossl_private_encrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_OSSL_PUBLIC_DECRYPT), "rsa_ossl_public_decrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT), "rsa_ossl_public_encrypt"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_NONE), "RSA_padding_add_none"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP),
|
||||
"RSA_padding_add_PKCS1_OAEP"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1),
|
||||
"RSA_padding_add_PKCS1_OAEP_mgf1"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_PSS), "RSA_padding_add_PKCS1_PSS"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1),
|
||||
"RSA_padding_add_PKCS1_PSS_mgf1"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1),
|
||||
"RSA_padding_add_PKCS1_type_1"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2),
|
||||
"RSA_padding_add_PKCS1_type_2"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_SSLV23), "RSA_padding_add_SSLv23"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_ADD_X931), "RSA_padding_add_X931"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_NONE), "RSA_padding_check_none"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP),
|
||||
"RSA_padding_check_PKCS1_OAEP"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1),
|
||||
"RSA_padding_check_PKCS1_OAEP_mgf1"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1),
|
||||
"RSA_padding_check_PKCS1_type_1"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2),
|
||||
"RSA_padding_check_PKCS1_type_2"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_SSLV23), "RSA_padding_check_SSLv23"},
|
||||
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_X931), "RSA_padding_check_X931"},
|
||||
{ERR_FUNC(RSA_F_RSA_PRINT), "RSA_print"},
|
||||
{ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"},
|
||||
{ERR_FUNC(RSA_F_RSA_PRIV_ENCODE), "rsa_priv_encode"},
|
||||
{ERR_FUNC(RSA_F_RSA_PSS_TO_CTX), "rsa_pss_to_ctx"},
|
||||
{ERR_FUNC(RSA_F_RSA_PUB_DECODE), "rsa_pub_decode"},
|
||||
{ERR_FUNC(RSA_F_RSA_SETUP_BLINDING), "RSA_setup_blinding"},
|
||||
{ERR_FUNC(RSA_F_RSA_SIGN), "RSA_sign"},
|
||||
{ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING),
|
||||
"RSA_sign_ASN1_OCTET_STRING"},
|
||||
{ERR_FUNC(RSA_F_RSA_VERIFY), "RSA_verify"},
|
||||
{ERR_FUNC(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING),
|
||||
"RSA_verify_ASN1_OCTET_STRING"},
|
||||
{ERR_FUNC(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1), "RSA_verify_PKCS1_PSS_mgf1"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA RSA_str_reasons[] = {
|
||||
{ERR_REASON(RSA_R_ALGORITHM_MISMATCH), "algorithm mismatch"},
|
||||
{ERR_REASON(RSA_R_BAD_E_VALUE), "bad e value"},
|
||||
{ERR_REASON(RSA_R_BAD_FIXED_HEADER_DECRYPT), "bad fixed header decrypt"},
|
||||
{ERR_REASON(RSA_R_BAD_PAD_BYTE_COUNT), "bad pad byte count"},
|
||||
{ERR_REASON(RSA_R_BAD_SIGNATURE), "bad signature"},
|
||||
{ERR_REASON(RSA_R_BLOCK_TYPE_IS_NOT_01), "block type is not 01"},
|
||||
{ERR_REASON(RSA_R_BLOCK_TYPE_IS_NOT_02), "block type is not 02"},
|
||||
{ERR_REASON(RSA_R_DATA_GREATER_THAN_MOD_LEN),
|
||||
"data greater than mod len"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_LARGE), "data too large"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE),
|
||||
"data too large for key size"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_LARGE_FOR_MODULUS),
|
||||
"data too large for modulus"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_SMALL), "data too small"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE),
|
||||
"data too small for key size"},
|
||||
{ERR_REASON(RSA_R_DIGEST_DOES_NOT_MATCH), "digest does not match"},
|
||||
{ERR_REASON(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY),
|
||||
"digest too big for rsa key"},
|
||||
{ERR_REASON(RSA_R_DMP1_NOT_CONGRUENT_TO_D), "dmp1 not congruent to d"},
|
||||
{ERR_REASON(RSA_R_DMQ1_NOT_CONGRUENT_TO_D), "dmq1 not congruent to d"},
|
||||
{ERR_REASON(RSA_R_D_E_NOT_CONGRUENT_TO_1), "d e not congruent to 1"},
|
||||
{ERR_REASON(RSA_R_FIRST_OCTET_INVALID), "first octet invalid"},
|
||||
{ERR_REASON(RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE),
|
||||
"illegal or unsupported padding mode"},
|
||||
{ERR_REASON(RSA_R_INVALID_DIGEST), "invalid digest"},
|
||||
{ERR_REASON(RSA_R_INVALID_DIGEST_LENGTH), "invalid digest length"},
|
||||
{ERR_REASON(RSA_R_INVALID_HEADER), "invalid header"},
|
||||
{ERR_REASON(RSA_R_INVALID_LABEL), "invalid label"},
|
||||
{ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH), "invalid message length"},
|
||||
{ERR_REASON(RSA_R_INVALID_MGF1_MD), "invalid mgf1 md"},
|
||||
{ERR_REASON(RSA_R_INVALID_OAEP_PARAMETERS), "invalid oaep parameters"},
|
||||
{ERR_REASON(RSA_R_INVALID_PADDING), "invalid padding"},
|
||||
{ERR_REASON(RSA_R_INVALID_PADDING_MODE), "invalid padding mode"},
|
||||
{ERR_REASON(RSA_R_INVALID_PSS_PARAMETERS), "invalid pss parameters"},
|
||||
{ERR_REASON(RSA_R_INVALID_PSS_SALTLEN), "invalid pss saltlen"},
|
||||
{ERR_REASON(RSA_R_INVALID_SALT_LENGTH), "invalid salt length"},
|
||||
{ERR_REASON(RSA_R_INVALID_TRAILER), "invalid trailer"},
|
||||
{ERR_REASON(RSA_R_INVALID_X931_DIGEST), "invalid x931 digest"},
|
||||
{ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q), "iqmp not inverse of q"},
|
||||
{ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL), "key size too small"},
|
||||
{ERR_REASON(RSA_R_LAST_OCTET_INVALID), "last octet invalid"},
|
||||
{ERR_REASON(RSA_R_MODULUS_TOO_LARGE), "modulus too large"},
|
||||
{ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT), "no public exponent"},
|
||||
{ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),
|
||||
"null before block missing"},
|
||||
{ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q), "n does not equal p q"},
|
||||
{ERR_REASON(RSA_R_OAEP_DECODING_ERROR), "oaep decoding error"},
|
||||
{ERR_REASON(RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),
|
||||
"operation not supported for this keytype"},
|
||||
{ERR_REASON(RSA_R_PADDING_CHECK_FAILED), "padding check failed"},
|
||||
{ERR_REASON(RSA_R_PKCS_DECODING_ERROR), "pkcs decoding error"},
|
||||
{ERR_REASON(RSA_R_P_NOT_PRIME), "p not prime"},
|
||||
{ERR_REASON(RSA_R_Q_NOT_PRIME), "q not prime"},
|
||||
{ERR_REASON(RSA_R_RSA_OPERATIONS_NOT_SUPPORTED),
|
||||
"rsa operations not supported"},
|
||||
{ERR_REASON(RSA_R_SLEN_CHECK_FAILED), "salt length check failed"},
|
||||
{ERR_REASON(RSA_R_SLEN_RECOVERY_FAILED), "salt length recovery failed"},
|
||||
{ERR_REASON(RSA_R_SSLV3_ROLLBACK_ATTACK), "sslv3 rollback attack"},
|
||||
{ERR_REASON(RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),
|
||||
"the asn1 object identifier is not known for this md"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_ALGORITHM_TYPE), "unknown algorithm type"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_DIGEST), "unknown digest"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_MASK_DIGEST), "unknown mask digest"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_PADDING_TYPE), "unknown padding type"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_ENCRYPTION_TYPE),
|
||||
"unsupported encryption type"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_LABEL_SOURCE), "unsupported label source"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_MASK_ALGORITHM),
|
||||
"unsupported mask algorithm"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_MASK_PARAMETER),
|
||||
"unsupported mask parameter"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_SIGNATURE_TYPE),
|
||||
"unsupported signature type"},
|
||||
{ERR_REASON(RSA_R_VALUE_MISSING), "value missing"},
|
||||
{ERR_REASON(RSA_R_WRONG_SIGNATURE_LENGTH), "wrong signature length"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ERR_load_RSA_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
if (ERR_func_error_string(RSA_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings(0, RSA_str_functs);
|
||||
ERR_load_strings(0, RSA_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* NB: these functions have been "upgraded", the deprecated versions (which
|
||||
* are compatibility wrappers using these functions) are in rsa_depr.c. -
|
||||
* Geoff
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
|
||||
BN_GENCB *cb);
|
||||
|
||||
/*
|
||||
* NB: this wrapper would normally be placed in rsa_lib.c and the static
|
||||
* implementation would probably be in rsa_eay.c. Nonetheless, is kept here
|
||||
* so that we don't introduce a new linker dependency. Eg. any application
|
||||
* that wasn't previously linking object code related to key-generation won't
|
||||
* have to now just because key-generation is part of RSA_METHOD.
|
||||
*/
|
||||
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
|
||||
{
|
||||
if (rsa->meth->rsa_keygen)
|
||||
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
|
||||
return rsa_builtin_keygen(rsa, bits, e_value, cb);
|
||||
}
|
||||
|
||||
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
|
||||
int bitsp, bitsq, ok = -1, n = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
unsigned long error = 0;
|
||||
|
||||
/*
|
||||
* When generating ridiculously small keys, we can get stuck
|
||||
* continually regenerating the same prime values.
|
||||
*/
|
||||
if (bits < 16) {
|
||||
ok = 0; /* we set our own err */
|
||||
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
r0 = BN_CTX_get(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
r2 = BN_CTX_get(ctx);
|
||||
r3 = BN_CTX_get(ctx);
|
||||
if (r3 == NULL)
|
||||
goto err;
|
||||
|
||||
bitsp = (bits + 1) / 2;
|
||||
bitsq = bits - bitsp;
|
||||
|
||||
/* We need the RSA components non-NULL */
|
||||
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->d && ((rsa->d = BN_secure_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->p && ((rsa->p = BN_secure_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->q && ((rsa->q = BN_secure_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->dmp1 && ((rsa->dmp1 = BN_secure_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->dmq1 && ((rsa->dmq1 = BN_secure_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL))
|
||||
goto err;
|
||||
|
||||
if (BN_copy(rsa->e, e_value) == NULL)
|
||||
goto err;
|
||||
|
||||
BN_set_flags(r2, BN_FLG_CONSTTIME);
|
||||
/* generate p and q */
|
||||
for (;;) {
|
||||
if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
|
||||
goto err;
|
||||
if (!BN_sub(r2, rsa->p, BN_value_one()))
|
||||
goto err;
|
||||
ERR_set_mark();
|
||||
if (BN_mod_inverse(r1, r2, rsa->e, ctx) != NULL) {
|
||||
/* GCD == 1 since inverse exists */
|
||||
break;
|
||||
}
|
||||
error = ERR_peek_last_error();
|
||||
if (ERR_GET_LIB(error) == ERR_LIB_BN
|
||||
&& ERR_GET_REASON(error) == BN_R_NO_INVERSE) {
|
||||
/* GCD != 1 */
|
||||
ERR_pop_to_mark();
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 2, n++))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
for (;;) {
|
||||
do {
|
||||
if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
|
||||
goto err;
|
||||
} while (BN_cmp(rsa->p, rsa->q) == 0);
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err;
|
||||
ERR_set_mark();
|
||||
if (BN_mod_inverse(r1, r2, rsa->e, ctx) != NULL) {
|
||||
/* GCD == 1 since inverse exists */
|
||||
break;
|
||||
}
|
||||
error = ERR_peek_last_error();
|
||||
if (ERR_GET_LIB(error) == ERR_LIB_BN
|
||||
&& ERR_GET_REASON(error) == BN_R_NO_INVERSE) {
|
||||
/* GCD != 1 */
|
||||
ERR_pop_to_mark();
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 2, n++))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 3, 1))
|
||||
goto err;
|
||||
if (BN_cmp(rsa->p, rsa->q) < 0) {
|
||||
tmp = rsa->p;
|
||||
rsa->p = rsa->q;
|
||||
rsa->q = tmp;
|
||||
}
|
||||
|
||||
/* calculate n */
|
||||
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d */
|
||||
if (!BN_sub(r1, rsa->p, BN_value_one()))
|
||||
goto err; /* p-1 */
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err; /* q-1 */
|
||||
if (!BN_mul(r0, r1, r2, ctx))
|
||||
goto err; /* (p-1)(q-1) */
|
||||
{
|
||||
BIGNUM *pr0 = BN_new();
|
||||
|
||||
if (pr0 == NULL)
|
||||
goto err;
|
||||
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
|
||||
if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
|
||||
BN_free(pr0);
|
||||
goto err; /* d */
|
||||
}
|
||||
/* We MUST free pr0 before any further use of r0 */
|
||||
BN_free(pr0);
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM *d = BN_new();
|
||||
|
||||
if (d == NULL)
|
||||
goto err;
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
|
||||
if ( /* calculate d mod (p-1) */
|
||||
!BN_mod(rsa->dmp1, d, r1, ctx)
|
||||
/* calculate d mod (q-1) */
|
||||
|| !BN_mod(rsa->dmq1, d, r2, ctx)) {
|
||||
BN_free(d);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free d before any further use of rsa->d */
|
||||
BN_free(d);
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM *p = BN_new();
|
||||
|
||||
if (p == NULL)
|
||||
goto err;
|
||||
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
|
||||
|
||||
/* calculate inverse of q mod p */
|
||||
if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) {
|
||||
BN_free(p);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free p before any further use of rsa->p */
|
||||
BN_free(p);
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
|
||||
ok = 0;
|
||||
}
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/lhash.h>
|
||||
#include "internal/bn_int.h"
|
||||
#include <openssl/engine.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
RSA *RSA_new(void)
|
||||
{
|
||||
return RSA_new_method(NULL);
|
||||
}
|
||||
|
||||
const RSA_METHOD *RSA_get_method(const RSA *rsa)
|
||||
{
|
||||
return rsa->meth;
|
||||
}
|
||||
|
||||
int RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
|
||||
{
|
||||
/*
|
||||
* NB: The caller is specifically setting a method, so it's not up to us
|
||||
* to deal with which ENGINE it comes from.
|
||||
*/
|
||||
const RSA_METHOD *mtmp;
|
||||
mtmp = rsa->meth;
|
||||
if (mtmp->finish)
|
||||
mtmp->finish(rsa);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(rsa->engine);
|
||||
rsa->engine = NULL;
|
||||
#endif
|
||||
rsa->meth = meth;
|
||||
if (meth->init)
|
||||
meth->init(rsa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
RSA *RSA_new_method(ENGINE *engine)
|
||||
{
|
||||
RSA *ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->references = 1;
|
||||
ret->lock = CRYPTO_THREAD_lock_new();
|
||||
if (ret->lock == NULL) {
|
||||
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->meth = RSA_get_default_method();
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
|
||||
if (engine) {
|
||||
if (!ENGINE_init(engine)) {
|
||||
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
|
||||
goto err;
|
||||
}
|
||||
ret->engine = engine;
|
||||
} else
|
||||
ret->engine = ENGINE_get_default_RSA();
|
||||
if (ret->engine) {
|
||||
ret->meth = ENGINE_get_RSA(ret->engine);
|
||||
if (ret->meth == NULL) {
|
||||
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
|
||||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
|
||||
RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_INIT_FAIL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
RSA_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RSA_free(RSA *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (r == NULL)
|
||||
return;
|
||||
|
||||
CRYPTO_atomic_add(&r->references, -1, &i, r->lock);
|
||||
REF_PRINT_COUNT("RSA", r);
|
||||
if (i > 0)
|
||||
return;
|
||||
REF_ASSERT_ISNT(i < 0);
|
||||
|
||||
if (r->meth->finish)
|
||||
r->meth->finish(r);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(r->engine);
|
||||
#endif
|
||||
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
|
||||
|
||||
CRYPTO_THREAD_lock_free(r->lock);
|
||||
|
||||
BN_clear_free(r->n);
|
||||
BN_clear_free(r->e);
|
||||
BN_clear_free(r->d);
|
||||
BN_clear_free(r->p);
|
||||
BN_clear_free(r->q);
|
||||
BN_clear_free(r->dmp1);
|
||||
BN_clear_free(r->dmq1);
|
||||
BN_clear_free(r->iqmp);
|
||||
BN_BLINDING_free(r->blinding);
|
||||
BN_BLINDING_free(r->mt_blinding);
|
||||
OPENSSL_free(r->bignum_data);
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
|
||||
int RSA_up_ref(RSA *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (CRYPTO_atomic_add(&r->references, 1, &i, r->lock) <= 0)
|
||||
return 0;
|
||||
|
||||
REF_PRINT_COUNT("RSA", r);
|
||||
REF_ASSERT_ISNT(i < 2);
|
||||
return ((i > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
int RSA_set_ex_data(RSA *r, int idx, void *arg)
|
||||
{
|
||||
return (CRYPTO_set_ex_data(&r->ex_data, idx, arg));
|
||||
}
|
||||
|
||||
void *RSA_get_ex_data(const RSA *r, int idx)
|
||||
{
|
||||
return (CRYPTO_get_ex_data(&r->ex_data, idx));
|
||||
}
|
||||
|
||||
int RSA_security_bits(const RSA *rsa)
|
||||
{
|
||||
return BN_security_bits(BN_num_bits(rsa->n), -1);
|
||||
}
|
||||
|
||||
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
|
||||
{
|
||||
/* If the fields n and e in r are NULL, the corresponding input
|
||||
* parameters MUST be non-NULL for n and e. d may be
|
||||
* left NULL (in case only the public key is used).
|
||||
*/
|
||||
if ((r->n == NULL && n == NULL)
|
||||
|| (r->e == NULL && e == NULL))
|
||||
return 0;
|
||||
|
||||
if (n != NULL) {
|
||||
BN_free(r->n);
|
||||
r->n = n;
|
||||
}
|
||||
if (e != NULL) {
|
||||
BN_free(r->e);
|
||||
r->e = e;
|
||||
}
|
||||
if (d != NULL) {
|
||||
BN_free(r->d);
|
||||
r->d = d;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
|
||||
{
|
||||
/* If the fields p and q in r are NULL, the corresponding input
|
||||
* parameters MUST be non-NULL.
|
||||
*/
|
||||
if ((r->p == NULL && p == NULL)
|
||||
|| (r->q == NULL && q == NULL))
|
||||
return 0;
|
||||
|
||||
if (p != NULL) {
|
||||
BN_free(r->p);
|
||||
r->p = p;
|
||||
}
|
||||
if (q != NULL) {
|
||||
BN_free(r->q);
|
||||
r->q = q;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
|
||||
{
|
||||
/* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
|
||||
* parameters MUST be non-NULL.
|
||||
*/
|
||||
if ((r->dmp1 == NULL && dmp1 == NULL)
|
||||
|| (r->dmq1 == NULL && dmq1 == NULL)
|
||||
|| (r->iqmp == NULL && iqmp == NULL))
|
||||
return 0;
|
||||
|
||||
if (dmp1 != NULL) {
|
||||
BN_free(r->dmp1);
|
||||
r->dmp1 = dmp1;
|
||||
}
|
||||
if (dmq1 != NULL) {
|
||||
BN_free(r->dmq1);
|
||||
r->dmq1 = dmq1;
|
||||
}
|
||||
if (iqmp != NULL) {
|
||||
BN_free(r->iqmp);
|
||||
r->iqmp = iqmp;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void RSA_get0_key(const RSA *r,
|
||||
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
|
||||
{
|
||||
if (n != NULL)
|
||||
*n = r->n;
|
||||
if (e != NULL)
|
||||
*e = r->e;
|
||||
if (d != NULL)
|
||||
*d = r->d;
|
||||
}
|
||||
|
||||
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
|
||||
{
|
||||
if (p != NULL)
|
||||
*p = r->p;
|
||||
if (q != NULL)
|
||||
*q = r->q;
|
||||
}
|
||||
|
||||
void RSA_get0_crt_params(const RSA *r,
|
||||
const BIGNUM **dmp1, const BIGNUM **dmq1,
|
||||
const BIGNUM **iqmp)
|
||||
{
|
||||
if (dmp1 != NULL)
|
||||
*dmp1 = r->dmp1;
|
||||
if (dmq1 != NULL)
|
||||
*dmq1 = r->dmq1;
|
||||
if (iqmp != NULL)
|
||||
*iqmp = r->iqmp;
|
||||
}
|
||||
|
||||
void RSA_clear_flags(RSA *r, int flags)
|
||||
{
|
||||
r->flags &= ~flags;
|
||||
}
|
||||
|
||||
int RSA_test_flags(const RSA *r, int flags)
|
||||
{
|
||||
return r->flags & flags;
|
||||
}
|
||||
|
||||
void RSA_set_flags(RSA *r, int flags)
|
||||
{
|
||||
r->flags |= flags;
|
||||
}
|
||||
|
||||
ENGINE *RSA_get0_engine(const RSA *r)
|
||||
{
|
||||
return r->engine;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
struct rsa_st {
|
||||
/*
|
||||
* The first parameter is used to pickup errors where this is passed
|
||||
* instead of aEVP_PKEY, it is set to 0
|
||||
*/
|
||||
int pad;
|
||||
long version;
|
||||
const RSA_METHOD *meth;
|
||||
/* functional reference if 'meth' is ENGINE-provided */
|
||||
ENGINE *engine;
|
||||
BIGNUM *n;
|
||||
BIGNUM *e;
|
||||
BIGNUM *d;
|
||||
BIGNUM *p;
|
||||
BIGNUM *q;
|
||||
BIGNUM *dmp1;
|
||||
BIGNUM *dmq1;
|
||||
BIGNUM *iqmp;
|
||||
/* be careful using this if the RSA structure is shared */
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
int references;
|
||||
int flags;
|
||||
/* Used to cache montgomery values */
|
||||
BN_MONT_CTX *_method_mod_n;
|
||||
BN_MONT_CTX *_method_mod_p;
|
||||
BN_MONT_CTX *_method_mod_q;
|
||||
/*
|
||||
* all BIGNUM values are actually in the following data, if it is not
|
||||
* NULL
|
||||
*/
|
||||
char *bignum_data;
|
||||
BN_BLINDING *blinding;
|
||||
BN_BLINDING *mt_blinding;
|
||||
CRYPTO_RWLOCK *lock;
|
||||
};
|
||||
|
||||
struct rsa_meth_st {
|
||||
char *name;
|
||||
int (*rsa_pub_enc) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
int (*rsa_pub_dec) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
int (*rsa_priv_enc) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
int (*rsa_priv_dec) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
/* Can be null */
|
||||
int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
|
||||
/* Can be null */
|
||||
int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
/* called at new */
|
||||
int (*init) (RSA *rsa);
|
||||
/* called at free */
|
||||
int (*finish) (RSA *rsa);
|
||||
/* RSA_METHOD_FLAG_* things */
|
||||
int flags;
|
||||
/* may be needed! */
|
||||
char *app_data;
|
||||
/*
|
||||
* New sign and verify functions: some libraries don't allow arbitrary
|
||||
* data to be signed/verified: this allows them to be used. Note: for
|
||||
* this to work the RSA_public_decrypt() and RSA_private_encrypt() should
|
||||
* *NOT* be used RSA_sign(), RSA_verify() should be used instead.
|
||||
*/
|
||||
int (*rsa_sign) (int type,
|
||||
const unsigned char *m, unsigned int m_length,
|
||||
unsigned char *sigret, unsigned int *siglen,
|
||||
const RSA *rsa);
|
||||
int (*rsa_verify) (int dtype, const unsigned char *m,
|
||||
unsigned int m_length, const unsigned char *sigbuf,
|
||||
unsigned int siglen, const RSA *rsa);
|
||||
/*
|
||||
* If this callback is NULL, the builtin software RSA key-gen will be
|
||||
* used. This is for behavioural compatibility whilst the code gets
|
||||
* rewired, but one day it would be nice to assume there are no such
|
||||
* things as "builtin software" implementations.
|
||||
*/
|
||||
int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
|
||||
};
|
||||
|
||||
extern int int_rsa_verify(int dtype, const unsigned char *m,
|
||||
unsigned int m_len, unsigned char *rm,
|
||||
size_t *prm_len, const unsigned char *sigbuf,
|
||||
size_t siglen, RSA *rsa);
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "rsa_locl.h"
|
||||
#include <openssl/err.h>
|
||||
|
||||
RSA_METHOD *RSA_meth_new(const char *name, int flags)
|
||||
{
|
||||
RSA_METHOD *meth = OPENSSL_zalloc(sizeof(*meth));
|
||||
|
||||
if (meth != NULL) {
|
||||
meth->flags = flags;
|
||||
|
||||
meth->name = OPENSSL_strdup(name);
|
||||
if (meth->name != NULL)
|
||||
return meth;
|
||||
|
||||
OPENSSL_free(meth);
|
||||
}
|
||||
|
||||
RSAerr(RSA_F_RSA_METH_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RSA_meth_free(RSA_METHOD *meth)
|
||||
{
|
||||
if (meth != NULL) {
|
||||
OPENSSL_free(meth->name);
|
||||
OPENSSL_free(meth);
|
||||
}
|
||||
}
|
||||
|
||||
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
|
||||
{
|
||||
RSA_METHOD *ret = OPENSSL_malloc(sizeof(*ret));
|
||||
|
||||
if (ret != NULL) {
|
||||
memcpy(ret, meth, sizeof(*meth));
|
||||
|
||||
ret->name = OPENSSL_strdup(meth->name);
|
||||
if (ret->name != NULL)
|
||||
return ret;
|
||||
|
||||
OPENSSL_free(ret);
|
||||
}
|
||||
|
||||
RSAerr(RSA_F_RSA_METH_DUP, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *RSA_meth_get0_name(const RSA_METHOD *meth)
|
||||
{
|
||||
return meth->name;
|
||||
}
|
||||
|
||||
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
|
||||
{
|
||||
char *tmpname = OPENSSL_strdup(name);
|
||||
|
||||
if (tmpname == NULL) {
|
||||
RSAerr(RSA_F_RSA_METH_SET1_NAME, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_free(meth->name);
|
||||
meth->name = tmpname;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_meth_get_flags(RSA_METHOD *meth)
|
||||
{
|
||||
return meth->flags;
|
||||
}
|
||||
|
||||
int RSA_meth_set_flags(RSA_METHOD *meth, int flags)
|
||||
{
|
||||
meth->flags = flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *RSA_meth_get0_app_data(const RSA_METHOD *meth)
|
||||
{
|
||||
return meth->app_data;
|
||||
}
|
||||
|
||||
int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
|
||||
{
|
||||
meth->app_data = app_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth))
|
||||
(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
return meth->rsa_pub_enc;
|
||||
}
|
||||
|
||||
int RSA_meth_set_pub_enc(RSA_METHOD *meth,
|
||||
int (*pub_enc) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa,
|
||||
int padding))
|
||||
{
|
||||
meth->rsa_pub_enc = pub_enc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth))
|
||||
(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
return meth->rsa_pub_dec;
|
||||
}
|
||||
|
||||
int RSA_meth_set_pub_dec(RSA_METHOD *meth,
|
||||
int (*pub_dec) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa,
|
||||
int padding))
|
||||
{
|
||||
meth->rsa_pub_dec = pub_dec;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))
|
||||
(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
return meth->rsa_priv_enc;
|
||||
}
|
||||
|
||||
int RSA_meth_set_priv_enc(RSA_METHOD *meth,
|
||||
int (*priv_enc) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa,
|
||||
int padding))
|
||||
{
|
||||
meth->rsa_priv_enc = priv_enc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))
|
||||
(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
return meth->rsa_priv_dec;
|
||||
}
|
||||
|
||||
int RSA_meth_set_priv_dec(RSA_METHOD *meth,
|
||||
int (*priv_dec) (int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa,
|
||||
int padding))
|
||||
{
|
||||
meth->rsa_priv_dec = priv_dec;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Can be null */
|
||||
int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))
|
||||
(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
|
||||
{
|
||||
return meth->rsa_mod_exp;
|
||||
}
|
||||
|
||||
int RSA_meth_set_mod_exp(RSA_METHOD *meth,
|
||||
int (*mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa,
|
||||
BN_CTX *ctx))
|
||||
{
|
||||
meth->rsa_mod_exp = mod_exp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Can be null */
|
||||
int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))
|
||||
(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
|
||||
{
|
||||
return meth->bn_mod_exp;
|
||||
}
|
||||
|
||||
int RSA_meth_set_bn_mod_exp(RSA_METHOD *meth,
|
||||
int (*bn_mod_exp) (BIGNUM *r,
|
||||
const BIGNUM *a,
|
||||
const BIGNUM *p,
|
||||
const BIGNUM *m,
|
||||
BN_CTX *ctx,
|
||||
BN_MONT_CTX *m_ctx))
|
||||
{
|
||||
meth->bn_mod_exp = bn_mod_exp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* called at new */
|
||||
int (*RSA_meth_get_init(const RSA_METHOD *meth)) (RSA *rsa)
|
||||
{
|
||||
return meth->init;
|
||||
}
|
||||
|
||||
int RSA_meth_set_init(RSA_METHOD *meth, int (*init) (RSA *rsa))
|
||||
{
|
||||
meth->init = init;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* called at free */
|
||||
int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa)
|
||||
{
|
||||
return meth->finish;
|
||||
}
|
||||
|
||||
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa))
|
||||
{
|
||||
meth->finish = finish;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_sign(const RSA_METHOD *meth))
|
||||
(int type,
|
||||
const unsigned char *m, unsigned int m_length,
|
||||
unsigned char *sigret, unsigned int *siglen,
|
||||
const RSA *rsa)
|
||||
{
|
||||
return meth->rsa_sign;
|
||||
}
|
||||
|
||||
int RSA_meth_set_sign(RSA_METHOD *meth,
|
||||
int (*sign) (int type, const unsigned char *m,
|
||||
unsigned int m_length,
|
||||
unsigned char *sigret, unsigned int *siglen,
|
||||
const RSA *rsa))
|
||||
{
|
||||
meth->rsa_sign = sign;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_verify(const RSA_METHOD *meth))
|
||||
(int dtype, const unsigned char *m,
|
||||
unsigned int m_length, const unsigned char *sigbuf,
|
||||
unsigned int siglen, const RSA *rsa)
|
||||
{
|
||||
return meth->rsa_verify;
|
||||
}
|
||||
|
||||
int RSA_meth_set_verify(RSA_METHOD *meth,
|
||||
int (*verify) (int dtype, const unsigned char *m,
|
||||
unsigned int m_length,
|
||||
const unsigned char *sigbuf,
|
||||
unsigned int siglen, const RSA *rsa))
|
||||
{
|
||||
meth->rsa_verify = verify;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*RSA_meth_get_keygen(const RSA_METHOD *meth))
|
||||
(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
|
||||
{
|
||||
return meth->rsa_keygen;
|
||||
}
|
||||
|
||||
int RSA_meth_set_keygen(RSA_METHOD *meth,
|
||||
int (*keygen) (RSA *rsa, int bits, BIGNUM *e,
|
||||
BN_GENCB *cb))
|
||||
{
|
||||
meth->rsa_keygen = keygen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
int RSA_padding_add_none(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen)
|
||||
{
|
||||
if (flen > tlen) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (flen < tlen) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_NONE, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
memcpy(to, from, (unsigned int)flen);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int RSA_padding_check_none(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen, int num)
|
||||
{
|
||||
|
||||
if (flen > tlen) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_NONE, RSA_R_DATA_TOO_LARGE);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset(to, 0, tlen - flen);
|
||||
memcpy(to + tlen - flen, from, flen);
|
||||
return (tlen);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
/*
|
||||
* This is a dummy RSA implementation that just returns errors when called.
|
||||
* It is designed to allow some RSA functions to work while stopping those
|
||||
* covered by the RSA patent. That is RSA, encryption, decryption, signing
|
||||
* and verify is not allowed but RSA key generation, key checking and other
|
||||
* operations (like storing RSA keys) are permitted.
|
||||
*/
|
||||
|
||||
static int RSA_null_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_null_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_null_public_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_null_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int RSA_null_init(RSA *rsa);
|
||||
static int RSA_null_finish(RSA *rsa);
|
||||
static RSA_METHOD rsa_null_meth = {
|
||||
"Null RSA",
|
||||
RSA_null_public_encrypt,
|
||||
RSA_null_public_decrypt,
|
||||
RSA_null_private_encrypt,
|
||||
RSA_null_private_decrypt,
|
||||
NULL,
|
||||
NULL,
|
||||
RSA_null_init,
|
||||
RSA_null_finish,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const RSA_METHOD *RSA_null_method(void)
|
||||
{
|
||||
return (&rsa_null_meth);
|
||||
}
|
||||
|
||||
static int RSA_null_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_NULL_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int RSA_null_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_NULL_PRIVATE_ENCRYPT,
|
||||
RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int RSA_null_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_NULL_PRIVATE_DECRYPT,
|
||||
RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int RSA_null_public_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_NULL_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int RSA_null_init(RSA *rsa)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int RSA_null_finish(RSA *rsa)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
|
||||
|
||||
/*
|
||||
* See Victor Shoup, "OAEP reconsidered," Nov. 2000, <URL:
|
||||
* http://www.shoup.net/papers/oaep.ps.Z> for problems with the security
|
||||
* proof for the original OAEP scheme, which EME-OAEP is based on. A new
|
||||
* proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern,
|
||||
* "RSA-OEAP is Still Alive!", Dec. 2000, <URL:
|
||||
* http://eprint.iacr.org/2000/061/>. The new proof has stronger requirements
|
||||
* for the underlying permutation: "partial-one-wayness" instead of
|
||||
* one-wayness. For the RSA function, this is an equivalent notion.
|
||||
*/
|
||||
|
||||
#include "internal/constant_time_locl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen,
|
||||
const unsigned char *param, int plen)
|
||||
{
|
||||
return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen,
|
||||
param, plen, NULL, NULL);
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen,
|
||||
const unsigned char *param, int plen,
|
||||
const EVP_MD *md, const EVP_MD *mgf1md)
|
||||
{
|
||||
int i, emlen = tlen - 1;
|
||||
unsigned char *db, *seed;
|
||||
unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];
|
||||
int mdlen;
|
||||
|
||||
if (md == NULL)
|
||||
md = EVP_sha1();
|
||||
if (mgf1md == NULL)
|
||||
mgf1md = md;
|
||||
|
||||
mdlen = EVP_MD_size(md);
|
||||
|
||||
if (flen > emlen - 2 * mdlen - 1) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (emlen < 2 * mdlen + 1) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
|
||||
RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
to[0] = 0;
|
||||
seed = to + 1;
|
||||
db = to + mdlen + 1;
|
||||
|
||||
if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
|
||||
return 0;
|
||||
memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
|
||||
db[emlen - flen - mdlen - 1] = 0x01;
|
||||
memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
|
||||
if (RAND_bytes(seed, mdlen) <= 0)
|
||||
return 0;
|
||||
#ifdef PKCS_TESTVECT
|
||||
memcpy(seed,
|
||||
"\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
|
||||
20);
|
||||
#endif
|
||||
|
||||
dbmask = OPENSSL_malloc(emlen - mdlen);
|
||||
if (dbmask == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)
|
||||
goto err;
|
||||
for (i = 0; i < emlen - mdlen; i++)
|
||||
db[i] ^= dbmask[i];
|
||||
|
||||
if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)
|
||||
goto err;
|
||||
for (i = 0; i < mdlen; i++)
|
||||
seed[i] ^= seedmask[i];
|
||||
|
||||
OPENSSL_free(dbmask);
|
||||
return 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(dbmask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen, int num,
|
||||
const unsigned char *param, int plen)
|
||||
{
|
||||
return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num,
|
||||
param, plen, NULL, NULL);
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen,
|
||||
int num, const unsigned char *param,
|
||||
int plen, const EVP_MD *md,
|
||||
const EVP_MD *mgf1md)
|
||||
{
|
||||
int i, dblen = 0, mlen = -1, one_index = 0, msg_index;
|
||||
unsigned int good, found_one_byte;
|
||||
const unsigned char *maskedseed, *maskeddb;
|
||||
/*
|
||||
* |em| is the encoded message, zero-padded to exactly |num| bytes: em =
|
||||
* Y || maskedSeed || maskedDB
|
||||
*/
|
||||
unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE],
|
||||
phash[EVP_MAX_MD_SIZE];
|
||||
int mdlen;
|
||||
|
||||
if (md == NULL)
|
||||
md = EVP_sha1();
|
||||
if (mgf1md == NULL)
|
||||
mgf1md = md;
|
||||
|
||||
mdlen = EVP_MD_size(md);
|
||||
|
||||
if (tlen <= 0 || flen <= 0)
|
||||
return -1;
|
||||
/*
|
||||
* |num| is the length of the modulus; |flen| is the length of the
|
||||
* encoded message. Therefore, for any |from| that was obtained by
|
||||
* decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
|
||||
* num < 2 * mdlen + 2 must hold for the modulus irrespective of
|
||||
* the ciphertext, see PKCS #1 v2.2, section 7.1.2.
|
||||
* This does not leak any side-channel information.
|
||||
*/
|
||||
if (num < flen || num < 2 * mdlen + 2)
|
||||
goto decoding_err;
|
||||
|
||||
dblen = num - mdlen - 1;
|
||||
db = OPENSSL_malloc(dblen);
|
||||
em = OPENSSL_malloc(num);
|
||||
if (db == NULL || em == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always do this zero-padding copy (even when num == flen) to avoid
|
||||
* leaking that information. The copy still leaks some side-channel
|
||||
* information, but it's impossible to have a fixed memory access
|
||||
* pattern since we can't read out of the bounds of |from|.
|
||||
*
|
||||
* TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
|
||||
*/
|
||||
memset(em, 0, num);
|
||||
memcpy(em + num - flen, from, flen);
|
||||
|
||||
/*
|
||||
* The first byte must be zero, however we must not leak if this is
|
||||
* true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
|
||||
* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
|
||||
*/
|
||||
good = constant_time_is_zero(em[0]);
|
||||
|
||||
maskedseed = em + 1;
|
||||
maskeddb = em + 1 + mdlen;
|
||||
|
||||
if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
|
||||
goto cleanup;
|
||||
for (i = 0; i < mdlen; i++)
|
||||
seed[i] ^= maskedseed[i];
|
||||
|
||||
if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md))
|
||||
goto cleanup;
|
||||
for (i = 0; i < dblen; i++)
|
||||
db[i] ^= maskeddb[i];
|
||||
|
||||
if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL))
|
||||
goto cleanup;
|
||||
|
||||
good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
|
||||
|
||||
found_one_byte = 0;
|
||||
for (i = mdlen; i < dblen; i++) {
|
||||
/*
|
||||
* Padding consists of a number of 0-bytes, followed by a 1.
|
||||
*/
|
||||
unsigned int equals1 = constant_time_eq(db[i], 1);
|
||||
unsigned int equals0 = constant_time_is_zero(db[i]);
|
||||
one_index = constant_time_select_int(~found_one_byte & equals1,
|
||||
i, one_index);
|
||||
found_one_byte |= equals1;
|
||||
good &= (found_one_byte | equals0);
|
||||
}
|
||||
|
||||
good &= found_one_byte;
|
||||
|
||||
/*
|
||||
* At this point |good| is zero unless the plaintext was valid,
|
||||
* so plaintext-awareness ensures timing side-channels are no longer a
|
||||
* concern.
|
||||
*/
|
||||
if (!good)
|
||||
goto decoding_err;
|
||||
|
||||
msg_index = one_index + 1;
|
||||
mlen = dblen - msg_index;
|
||||
|
||||
if (tlen < mlen) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, RSA_R_DATA_TOO_LARGE);
|
||||
mlen = -1;
|
||||
} else {
|
||||
memcpy(to, db + msg_index, mlen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
decoding_err:
|
||||
/*
|
||||
* To avoid chosen ciphertext attacks, the error message should not
|
||||
* reveal which kind of decoding error happened.
|
||||
*/
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
|
||||
RSA_R_OAEP_DECODING_ERROR);
|
||||
cleanup:
|
||||
OPENSSL_clear_free(db, dblen);
|
||||
OPENSSL_clear_free(em, num);
|
||||
return mlen;
|
||||
}
|
||||
|
||||
int PKCS1_MGF1(unsigned char *mask, long len,
|
||||
const unsigned char *seed, long seedlen, const EVP_MD *dgst)
|
||||
{
|
||||
long i, outlen = 0;
|
||||
unsigned char cnt[4];
|
||||
EVP_MD_CTX *c = EVP_MD_CTX_new();
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
int mdlen;
|
||||
int rv = -1;
|
||||
|
||||
if (c == NULL)
|
||||
goto err;
|
||||
mdlen = EVP_MD_size(dgst);
|
||||
if (mdlen < 0)
|
||||
goto err;
|
||||
for (i = 0; outlen < len; i++) {
|
||||
cnt[0] = (unsigned char)((i >> 24) & 255);
|
||||
cnt[1] = (unsigned char)((i >> 16) & 255);
|
||||
cnt[2] = (unsigned char)((i >> 8)) & 255;
|
||||
cnt[3] = (unsigned char)(i & 255);
|
||||
if (!EVP_DigestInit_ex(c, dgst, NULL)
|
||||
|| !EVP_DigestUpdate(c, seed, seedlen)
|
||||
|| !EVP_DigestUpdate(c, cnt, 4))
|
||||
goto err;
|
||||
if (outlen + mdlen <= len) {
|
||||
if (!EVP_DigestFinal_ex(c, mask + outlen, NULL))
|
||||
goto err;
|
||||
outlen += mdlen;
|
||||
} else {
|
||||
if (!EVP_DigestFinal_ex(c, md, NULL))
|
||||
goto err;
|
||||
memcpy(mask + outlen, md, len - outlen);
|
||||
outlen = len;
|
||||
}
|
||||
}
|
||||
rv = 0;
|
||||
err:
|
||||
EVP_MD_CTX_free(c);
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,800 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/bn_int.h"
|
||||
#include "rsa_locl.h"
|
||||
|
||||
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding);
|
||||
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa,
|
||||
BN_CTX *ctx);
|
||||
static int rsa_ossl_init(RSA *rsa);
|
||||
static int rsa_ossl_finish(RSA *rsa);
|
||||
static RSA_METHOD rsa_pkcs1_ossl_meth = {
|
||||
"OpenSSL PKCS#1 RSA",
|
||||
rsa_ossl_public_encrypt,
|
||||
rsa_ossl_public_decrypt, /* signature verification */
|
||||
rsa_ossl_private_encrypt, /* signing */
|
||||
rsa_ossl_private_decrypt,
|
||||
rsa_ossl_mod_exp,
|
||||
BN_mod_exp_mont, /* XXX probably we should not use Montgomery
|
||||
* if e == 3 */
|
||||
rsa_ossl_init,
|
||||
rsa_ossl_finish,
|
||||
RSA_FLAG_FIPS_METHOD, /* flags */
|
||||
NULL,
|
||||
0, /* rsa_sign */
|
||||
0, /* rsa_verify */
|
||||
NULL /* rsa_keygen */
|
||||
};
|
||||
|
||||
static const RSA_METHOD *default_RSA_meth = &rsa_pkcs1_ossl_meth;
|
||||
|
||||
void RSA_set_default_method(const RSA_METHOD *meth)
|
||||
{
|
||||
default_RSA_meth = meth;
|
||||
}
|
||||
|
||||
const RSA_METHOD *RSA_get_default_method(void)
|
||||
{
|
||||
return default_RSA_meth;
|
||||
}
|
||||
|
||||
const RSA_METHOD *RSA_PKCS1_OpenSSL(void)
|
||||
{
|
||||
return &rsa_pkcs1_ossl_meth;
|
||||
}
|
||||
|
||||
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for large moduli, enforce exponent limit */
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
|
||||
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (f == NULL || ret == NULL || buf == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
|
||||
break;
|
||||
case RSA_SSLV23_PADDING:
|
||||
i = RSA_padding_add_SSLv23(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
i = RSA_padding_add_none(buf, num, from, flen);
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
|
||||
if (BN_bin2bn(buf, num, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
/* usually the padding functions would catch this */
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
|
||||
if (!BN_MONT_CTX_set_locked
|
||||
(&rsa->_method_mod_n, rsa->lock, rsa->n, ctx))
|
||||
goto err;
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* put in leading 0 bytes if the number is less than the length of the
|
||||
* modulus
|
||||
*/
|
||||
j = BN_num_bytes(ret);
|
||||
i = BN_bn2bin(ret, &(to[num - j]));
|
||||
for (k = 0; k < (num - i); k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
OPENSSL_clear_free(buf, num);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
|
||||
{
|
||||
BN_BLINDING *ret;
|
||||
|
||||
CRYPTO_THREAD_write_lock(rsa->lock);
|
||||
|
||||
if (rsa->blinding == NULL) {
|
||||
rsa->blinding = RSA_setup_blinding(rsa, ctx);
|
||||
}
|
||||
|
||||
ret = rsa->blinding;
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_BLINDING_is_current_thread(ret)) {
|
||||
/* rsa->blinding is ours! */
|
||||
|
||||
*local = 1;
|
||||
} else {
|
||||
/* resort to rsa->mt_blinding instead */
|
||||
|
||||
/*
|
||||
* instructs rsa_blinding_convert(), rsa_blinding_invert() that the
|
||||
* BN_BLINDING is shared, meaning that accesses require locks, and
|
||||
* that the blinding factor must be stored outside the BN_BLINDING
|
||||
*/
|
||||
*local = 0;
|
||||
|
||||
if (rsa->mt_blinding == NULL) {
|
||||
rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
|
||||
}
|
||||
ret = rsa->mt_blinding;
|
||||
}
|
||||
|
||||
err:
|
||||
CRYPTO_THREAD_unlock(rsa->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
if (unblind == NULL)
|
||||
/*
|
||||
* Local blinding: store the unblinding factor in BN_BLINDING.
|
||||
*/
|
||||
return BN_BLINDING_convert_ex(f, NULL, b, ctx);
|
||||
else {
|
||||
/*
|
||||
* Shared blinding: store the unblinding factor outside BN_BLINDING.
|
||||
*/
|
||||
int ret;
|
||||
|
||||
BN_BLINDING_lock(b);
|
||||
ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
|
||||
BN_BLINDING_unlock(b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
/*
|
||||
* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex
|
||||
* will use the unblinding factor stored in BN_BLINDING. If BN_BLINDING
|
||||
* is shared between threads, unblind must be non-null:
|
||||
* BN_BLINDING_invert_ex will then use the local unblinding factor, and
|
||||
* will only read the modulus from BN_BLINDING. In both cases it's safe
|
||||
* to access the blinding without a lock.
|
||||
*/
|
||||
return BN_BLINDING_invert_ex(f, unblind, b, ctx);
|
||||
}
|
||||
|
||||
/* signing */
|
||||
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret, *res;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
/*
|
||||
* Used only if the blinding structure is shared. A non-NULL unblind
|
||||
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
|
||||
* the unblinding factor outside the blinding structure.
|
||||
*/
|
||||
BIGNUM *unblind = NULL;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (f == NULL || ret == NULL || buf == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_X931_PADDING:
|
||||
i = RSA_padding_add_X931(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
i = RSA_padding_add_none(buf, num, from, flen);
|
||||
break;
|
||||
case RSA_SSLV23_PADDING:
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
|
||||
if (BN_bin2bn(buf, num, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
/* usually the padding functions would catch this */
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
|
||||
if (blinding == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding != NULL) {
|
||||
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
((rsa->p != NULL) &&
|
||||
(rsa->q != NULL) &&
|
||||
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
|
||||
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
BIGNUM *d = BN_new();
|
||||
if (d == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
|
||||
if (!BN_MONT_CTX_set_locked
|
||||
(&rsa->_method_mod_n, rsa->lock, rsa->n, ctx)) {
|
||||
BN_free(d);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
|
||||
rsa->_method_mod_n)) {
|
||||
BN_free(d);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free d before any further use of rsa->d */
|
||||
BN_free(d);
|
||||
}
|
||||
|
||||
if (blinding)
|
||||
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
|
||||
goto err;
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
BN_sub(f, rsa->n, ret);
|
||||
if (BN_cmp(ret, f) > 0)
|
||||
res = f;
|
||||
else
|
||||
res = ret;
|
||||
} else
|
||||
res = ret;
|
||||
|
||||
/*
|
||||
* put in leading 0 bytes if the number is less than the length of the
|
||||
* modulus
|
||||
*/
|
||||
j = BN_num_bytes(res);
|
||||
i = BN_bn2bin(res, &(to[num - j]));
|
||||
for (k = 0; k < (num - i); k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
OPENSSL_clear_free(buf, num);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int j, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
/*
|
||||
* Used only if the blinding structure is shared. A non-NULL unblind
|
||||
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
|
||||
* the unblinding factor outside the blinding structure.
|
||||
*/
|
||||
BIGNUM *unblind = NULL;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (f == NULL || ret == NULL || buf == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This check was for equality but PGP does evil things and chops off the
|
||||
* top '0' bytes
|
||||
*/
|
||||
if (flen > num) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT,
|
||||
RSA_R_DATA_GREATER_THAN_MOD_LEN);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* make data into a big number */
|
||||
if (BN_bin2bn(from, (int)flen, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
|
||||
if (blinding == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding != NULL) {
|
||||
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* do the decrypt */
|
||||
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
((rsa->p != NULL) &&
|
||||
(rsa->q != NULL) &&
|
||||
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
|
||||
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
BIGNUM *d = BN_new();
|
||||
if (d == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
|
||||
if (!BN_MONT_CTX_set_locked
|
||||
(&rsa->_method_mod_n, rsa->lock, rsa->n, ctx)) {
|
||||
BN_free(d);
|
||||
goto err;
|
||||
}
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
|
||||
rsa->_method_mod_n)) {
|
||||
BN_free(d);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free d before any further use of rsa->d */
|
||||
BN_free(d);
|
||||
}
|
||||
|
||||
if (blinding)
|
||||
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
j = BN_bn2bin(ret, p); /* j is only used with no-padding mode */
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
|
||||
break;
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
|
||||
break;
|
||||
case RSA_SSLV23_PADDING:
|
||||
r = RSA_padding_check_SSLv23(to, num, buf, j, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, j, num);
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (r < 0)
|
||||
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
|
||||
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
OPENSSL_clear_free(buf, num);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/* signature verification */
|
||||
static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for large moduli, enforce exponent limit */
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
|
||||
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = OPENSSL_malloc(num);
|
||||
if (f == NULL || ret == NULL || buf == NULL) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This check was for equality but PGP does evil things and chops off the
|
||||
* top '0' bytes
|
||||
*/
|
||||
if (flen > num) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_bin2bn(from, flen, f) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(f, rsa->n) >= 0) {
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
|
||||
if (!BN_MONT_CTX_set_locked
|
||||
(&rsa->_method_mod_n, rsa->lock, rsa->n, ctx))
|
||||
goto err;
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
|
||||
if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12))
|
||||
if (!BN_sub(ret, rsa->n, ret))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
i = BN_bn2bin(ret, p);
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_X931_PADDING:
|
||||
r = RSA_padding_check_X931(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, i, num);
|
||||
break;
|
||||
default:
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (r < 0)
|
||||
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
|
||||
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
OPENSSL_clear_free(buf, num);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *r1, *m1, *vrfy;
|
||||
int ret = 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
r1 = BN_CTX_get(ctx);
|
||||
m1 = BN_CTX_get(ctx);
|
||||
vrfy = BN_CTX_get(ctx);
|
||||
if (vrfy == NULL)
|
||||
goto err;
|
||||
|
||||
{
|
||||
BIGNUM *p = BN_new(), *q = BN_new();
|
||||
|
||||
/*
|
||||
* Make sure BN_mod_inverse in Montgomery initialization uses the
|
||||
* BN_FLG_CONSTTIME flag
|
||||
*/
|
||||
if (p == NULL || q == NULL) {
|
||||
BN_free(p);
|
||||
BN_free(q);
|
||||
goto err;
|
||||
}
|
||||
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
|
||||
BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
|
||||
if (!BN_MONT_CTX_set_locked
|
||||
(&rsa->_method_mod_p, rsa->lock, p, ctx)
|
||||
|| !BN_MONT_CTX_set_locked(&rsa->_method_mod_q,
|
||||
rsa->lock, q, ctx)) {
|
||||
BN_free(p);
|
||||
BN_free(q);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We MUST free p and q before any further use of rsa->p and rsa->q
|
||||
*/
|
||||
BN_free(p);
|
||||
BN_free(q);
|
||||
}
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
|
||||
if (!BN_MONT_CTX_set_locked
|
||||
(&rsa->_method_mod_n, rsa->lock, rsa->n, ctx))
|
||||
goto err;
|
||||
|
||||
/* compute I mod q */
|
||||
{
|
||||
BIGNUM *c = BN_new();
|
||||
if (c == NULL)
|
||||
goto err;
|
||||
BN_with_flags(c, I, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!BN_mod(r1, c, rsa->q, ctx)) {
|
||||
BN_free(c);
|
||||
goto err;
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM *dmq1 = BN_new();
|
||||
if (dmq1 == NULL) {
|
||||
BN_free(c);
|
||||
goto err;
|
||||
}
|
||||
BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
|
||||
|
||||
/* compute r1^dmq1 mod q */
|
||||
if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx,
|
||||
rsa->_method_mod_q)) {
|
||||
BN_free(c);
|
||||
BN_free(dmq1);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free dmq1 before any further use of rsa->dmq1 */
|
||||
BN_free(dmq1);
|
||||
}
|
||||
|
||||
/* compute I mod p */
|
||||
if (!BN_mod(r1, c, rsa->p, ctx)) {
|
||||
BN_free(c);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free c before any further use of I */
|
||||
BN_free(c);
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM *dmp1 = BN_new();
|
||||
if (dmp1 == NULL)
|
||||
goto err;
|
||||
BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
|
||||
|
||||
/* compute r1^dmp1 mod p */
|
||||
if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx,
|
||||
rsa->_method_mod_p)) {
|
||||
BN_free(dmp1);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free dmp1 before any further use of rsa->dmp1 */
|
||||
BN_free(dmp1);
|
||||
}
|
||||
|
||||
if (!BN_sub(r0, r0, m1))
|
||||
goto err;
|
||||
/*
|
||||
* This will help stop the size of r0 increasing, which does affect the
|
||||
* multiply if it optimised for a power of 2 size
|
||||
*/
|
||||
if (BN_is_negative(r0))
|
||||
if (!BN_add(r0, r0, rsa->p))
|
||||
goto err;
|
||||
|
||||
if (!BN_mul(r1, r0, rsa->iqmp, ctx))
|
||||
goto err;
|
||||
|
||||
{
|
||||
BIGNUM *pr1 = BN_new();
|
||||
if (pr1 == NULL)
|
||||
goto err;
|
||||
BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!BN_mod(r0, pr1, rsa->p, ctx)) {
|
||||
BN_free(pr1);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free pr1 before any further use of r1 */
|
||||
BN_free(pr1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If p < q it is occasionally possible for the correction of adding 'p'
|
||||
* if r0 is negative above to leave the result still negative. This can
|
||||
* break the private key operations: the following second correction
|
||||
* should *always* correct this rare occurrence. This will *never* happen
|
||||
* with OpenSSL generated keys because they ensure p > q [steve]
|
||||
*/
|
||||
if (BN_is_negative(r0))
|
||||
if (!BN_add(r0, r0, rsa->p))
|
||||
goto err;
|
||||
if (!BN_mul(r1, r0, rsa->q, ctx))
|
||||
goto err;
|
||||
if (!BN_add(r0, r1, m1))
|
||||
goto err;
|
||||
|
||||
if (rsa->e && rsa->n) {
|
||||
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
/*
|
||||
* If 'I' was greater than (or equal to) rsa->n, the operation will
|
||||
* be equivalent to using 'I mod n'. However, the result of the
|
||||
* verify will *always* be less than 'n' so we don't check for
|
||||
* absolute equality, just congruency.
|
||||
*/
|
||||
if (!BN_sub(vrfy, vrfy, I))
|
||||
goto err;
|
||||
if (!BN_mod(vrfy, vrfy, rsa->n, ctx))
|
||||
goto err;
|
||||
if (BN_is_negative(vrfy))
|
||||
if (!BN_add(vrfy, vrfy, rsa->n))
|
||||
goto err;
|
||||
if (!BN_is_zero(vrfy)) {
|
||||
/*
|
||||
* 'I' and 'vrfy' aren't congruent mod n. Don't leak
|
||||
* miscalculated CRT output, just do a raw (slower) mod_exp and
|
||||
* return that instead.
|
||||
*/
|
||||
|
||||
BIGNUM *d = BN_new();
|
||||
if (d == NULL)
|
||||
goto err;
|
||||
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,
|
||||
rsa->_method_mod_n)) {
|
||||
BN_free(d);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free d before any further use of rsa->d */
|
||||
BN_free(d);
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int rsa_ossl_init(RSA *rsa)
|
||||
{
|
||||
rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int rsa_ossl_finish(RSA *rsa)
|
||||
{
|
||||
BN_MONT_CTX_free(rsa->_method_mod_n);
|
||||
BN_MONT_CTX_free(rsa->_method_mod_p);
|
||||
BN_MONT_CTX_free(rsa->_method_mod_q);
|
||||
return (1);
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/constant_time_locl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen)
|
||||
{
|
||||
int j;
|
||||
unsigned char *p;
|
||||
|
||||
if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
p = (unsigned char *)to;
|
||||
|
||||
*(p++) = 0;
|
||||
*(p++) = 1; /* Private Key BT (Block Type) */
|
||||
|
||||
/* pad out with 0xff data */
|
||||
j = tlen - 3 - flen;
|
||||
memset(p, 0xff, j);
|
||||
p += j;
|
||||
*(p++) = '\0';
|
||||
memcpy(p, from, (unsigned int)flen);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen,
|
||||
int num)
|
||||
{
|
||||
int i, j;
|
||||
const unsigned char *p;
|
||||
|
||||
p = from;
|
||||
|
||||
/*
|
||||
* The format is
|
||||
* 00 || 01 || PS || 00 || D
|
||||
* PS - padding string, at least 8 bytes of FF
|
||||
* D - data.
|
||||
*/
|
||||
|
||||
if (num < 11)
|
||||
return -1;
|
||||
|
||||
/* Accept inputs with and without the leading 0-byte. */
|
||||
if (num == flen) {
|
||||
if ((*p++) != 0x00) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
|
||||
RSA_R_INVALID_PADDING);
|
||||
return -1;
|
||||
}
|
||||
flen--;
|
||||
}
|
||||
|
||||
if ((num != (flen + 1)) || (*(p++) != 0x01)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
|
||||
RSA_R_BLOCK_TYPE_IS_NOT_01);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* scan over padding data */
|
||||
j = flen - 1; /* one for type. */
|
||||
for (i = 0; i < j; i++) {
|
||||
if (*p != 0xff) { /* should decrypt to 0xff */
|
||||
if (*p == 0) {
|
||||
p++;
|
||||
break;
|
||||
} else {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
|
||||
RSA_R_BAD_FIXED_HEADER_DECRYPT);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (i == j) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
|
||||
RSA_R_NULL_BEFORE_BLOCK_MISSING);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (i < 8) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
|
||||
RSA_R_BAD_PAD_BYTE_COUNT);
|
||||
return (-1);
|
||||
}
|
||||
i++; /* Skip over the '\0' */
|
||||
j -= i;
|
||||
if (j > tlen) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, RSA_R_DATA_TOO_LARGE);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(to, p, (unsigned int)j);
|
||||
|
||||
return (j);
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char *p;
|
||||
|
||||
if (flen > (tlen - 11)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
p = (unsigned char *)to;
|
||||
|
||||
*(p++) = 0;
|
||||
*(p++) = 2; /* Public Key BT (Block Type) */
|
||||
|
||||
/* pad out with non-zero random data */
|
||||
j = tlen - 3 - flen;
|
||||
|
||||
if (RAND_bytes(p, j) <= 0)
|
||||
return (0);
|
||||
for (i = 0; i < j; i++) {
|
||||
if (*p == '\0')
|
||||
do {
|
||||
if (RAND_bytes(p, 1) <= 0)
|
||||
return (0);
|
||||
} while (*p == '\0');
|
||||
p++;
|
||||
}
|
||||
|
||||
*(p++) = '\0';
|
||||
|
||||
memcpy(p, from, (unsigned int)flen);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen,
|
||||
int num)
|
||||
{
|
||||
int i;
|
||||
/* |em| is the encoded message, zero-padded to exactly |num| bytes */
|
||||
unsigned char *em = NULL;
|
||||
unsigned int good, found_zero_byte;
|
||||
int zero_index = 0, msg_index, mlen = -1;
|
||||
|
||||
if (tlen < 0 || flen < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard",
|
||||
* section 7.2.2.
|
||||
*/
|
||||
|
||||
if (flen > num)
|
||||
goto err;
|
||||
|
||||
if (num < 11)
|
||||
goto err;
|
||||
|
||||
em = OPENSSL_zalloc(num);
|
||||
if (em == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Always do this zero-padding copy (even when num == flen) to avoid
|
||||
* leaking that information. The copy still leaks some side-channel
|
||||
* information, but it's impossible to have a fixed memory access
|
||||
* pattern since we can't read out of the bounds of |from|.
|
||||
*
|
||||
* TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
|
||||
*/
|
||||
memcpy(em + num - flen, from, flen);
|
||||
|
||||
good = constant_time_is_zero(em[0]);
|
||||
good &= constant_time_eq(em[1], 2);
|
||||
|
||||
found_zero_byte = 0;
|
||||
for (i = 2; i < num; i++) {
|
||||
unsigned int equals0 = constant_time_is_zero(em[i]);
|
||||
zero_index =
|
||||
constant_time_select_int(~found_zero_byte & equals0, i,
|
||||
zero_index);
|
||||
found_zero_byte |= equals0;
|
||||
}
|
||||
|
||||
/*
|
||||
* PS must be at least 8 bytes long, and it starts two bytes into |em|.
|
||||
* If we never found a 0-byte, then |zero_index| is 0 and the check
|
||||
* also fails.
|
||||
*/
|
||||
good &= constant_time_ge((unsigned int)(zero_index), 2 + 8);
|
||||
|
||||
/*
|
||||
* Skip the zero byte. This is incorrect if we never found a zero-byte
|
||||
* but in this case we also do not copy the message out.
|
||||
*/
|
||||
msg_index = zero_index + 1;
|
||||
mlen = num - msg_index;
|
||||
|
||||
/*
|
||||
* For good measure, do this check in constant time as well; it could
|
||||
* leak something if |tlen| was assuming valid padding.
|
||||
*/
|
||||
good &= constant_time_ge((unsigned int)(tlen), (unsigned int)(mlen));
|
||||
|
||||
/*
|
||||
* We can't continue in constant-time because we need to copy the result
|
||||
* and we cannot fake its length. This unavoidably leaks timing
|
||||
* information at the API boundary.
|
||||
*/
|
||||
if (!good) {
|
||||
mlen = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(to, em + msg_index, mlen);
|
||||
|
||||
err:
|
||||
OPENSSL_clear_free(em, num);
|
||||
if (mlen == -1)
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,
|
||||
RSA_R_PKCS_DECODING_ERROR);
|
||||
return mlen;
|
||||
}
|
||||
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/cms.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "rsa_locl.h"
|
||||
|
||||
/* RSA pkey context structure */
|
||||
|
||||
typedef struct {
|
||||
/* Key gen parameters */
|
||||
int nbits;
|
||||
BIGNUM *pub_exp;
|
||||
/* Keygen callback info */
|
||||
int gentmp[2];
|
||||
/* RSA padding mode */
|
||||
int pad_mode;
|
||||
/* message digest */
|
||||
const EVP_MD *md;
|
||||
/* message digest for MGF1 */
|
||||
const EVP_MD *mgf1md;
|
||||
/* PSS salt length */
|
||||
int saltlen;
|
||||
/* Temp buffer */
|
||||
unsigned char *tbuf;
|
||||
/* OAEP label */
|
||||
unsigned char *oaep_label;
|
||||
size_t oaep_labellen;
|
||||
} RSA_PKEY_CTX;
|
||||
|
||||
static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
RSA_PKEY_CTX *rctx;
|
||||
rctx = OPENSSL_zalloc(sizeof(*rctx));
|
||||
if (rctx == NULL)
|
||||
return 0;
|
||||
rctx->nbits = 1024;
|
||||
rctx->pad_mode = RSA_PKCS1_PADDING;
|
||||
rctx->saltlen = -2;
|
||||
ctx->data = rctx;
|
||||
ctx->keygen_info = rctx->gentmp;
|
||||
ctx->keygen_info_count = 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
RSA_PKEY_CTX *dctx, *sctx;
|
||||
if (!pkey_rsa_init(dst))
|
||||
return 0;
|
||||
sctx = src->data;
|
||||
dctx = dst->data;
|
||||
dctx->nbits = sctx->nbits;
|
||||
if (sctx->pub_exp) {
|
||||
dctx->pub_exp = BN_dup(sctx->pub_exp);
|
||||
if (!dctx->pub_exp)
|
||||
return 0;
|
||||
}
|
||||
dctx->pad_mode = sctx->pad_mode;
|
||||
dctx->md = sctx->md;
|
||||
dctx->mgf1md = sctx->mgf1md;
|
||||
if (sctx->oaep_label) {
|
||||
OPENSSL_free(dctx->oaep_label);
|
||||
dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
|
||||
if (!dctx->oaep_label)
|
||||
return 0;
|
||||
dctx->oaep_labellen = sctx->oaep_labellen;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
|
||||
{
|
||||
if (ctx->tbuf)
|
||||
return 1;
|
||||
ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
|
||||
if (ctx->tbuf == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
if (rctx) {
|
||||
BN_free(rctx->pub_exp);
|
||||
OPENSSL_free(rctx->tbuf);
|
||||
OPENSSL_free(rctx->oaep_label);
|
||||
OPENSSL_free(rctx);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
|
||||
size_t *siglen, const unsigned char *tbs,
|
||||
size_t tbslen)
|
||||
{
|
||||
int ret;
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
RSA *rsa = ctx->pkey->pkey.rsa;
|
||||
|
||||
if (rctx->md) {
|
||||
if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
|
||||
RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_MD_type(rctx->md) == NID_mdc2) {
|
||||
unsigned int sltmp;
|
||||
if (rctx->pad_mode != RSA_PKCS1_PADDING)
|
||||
return -1;
|
||||
ret = RSA_sign_ASN1_OCTET_STRING(0,
|
||||
tbs, tbslen, sig, &sltmp, rsa);
|
||||
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
ret = sltmp;
|
||||
} else if (rctx->pad_mode == RSA_X931_PADDING) {
|
||||
if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) {
|
||||
RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
if (!setup_tbuf(rctx, ctx)) {
|
||||
RSAerr(RSA_F_PKEY_RSA_SIGN, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
memcpy(rctx->tbuf, tbs, tbslen);
|
||||
rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md));
|
||||
ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
|
||||
sig, rsa, RSA_X931_PADDING);
|
||||
} else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
|
||||
unsigned int sltmp;
|
||||
ret = RSA_sign(EVP_MD_type(rctx->md),
|
||||
tbs, tbslen, sig, &sltmp, rsa);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
ret = sltmp;
|
||||
} else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
|
||||
rctx->tbuf, tbs,
|
||||
rctx->md, rctx->mgf1md,
|
||||
rctx->saltlen))
|
||||
return -1;
|
||||
ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
|
||||
sig, rsa, RSA_NO_PADDING);
|
||||
} else
|
||||
return -1;
|
||||
} else
|
||||
ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
|
||||
rctx->pad_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*siglen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
|
||||
unsigned char *rout, size_t *routlen,
|
||||
const unsigned char *sig, size_t siglen)
|
||||
{
|
||||
int ret;
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
|
||||
if (rctx->md) {
|
||||
if (rctx->pad_mode == RSA_X931_PADDING) {
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
ret = RSA_public_decrypt(siglen, sig,
|
||||
rctx->tbuf, ctx->pkey->pkey.rsa,
|
||||
RSA_X931_PADDING);
|
||||
if (ret < 1)
|
||||
return 0;
|
||||
ret--;
|
||||
if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_type(rctx->md))) {
|
||||
RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
|
||||
RSA_R_ALGORITHM_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (ret != EVP_MD_size(rctx->md)) {
|
||||
RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
|
||||
RSA_R_INVALID_DIGEST_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (rout)
|
||||
memcpy(rout, rctx->tbuf, ret);
|
||||
} else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
|
||||
size_t sltmp;
|
||||
ret = int_rsa_verify(EVP_MD_type(rctx->md),
|
||||
NULL, 0, rout, &sltmp,
|
||||
sig, siglen, ctx->pkey->pkey.rsa);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
ret = sltmp;
|
||||
} else
|
||||
return -1;
|
||||
} else
|
||||
ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
|
||||
rctx->pad_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*routlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
|
||||
const unsigned char *sig, size_t siglen,
|
||||
const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
RSA *rsa = ctx->pkey->pkey.rsa;
|
||||
size_t rslen;
|
||||
if (rctx->md) {
|
||||
if (rctx->pad_mode == RSA_PKCS1_PADDING)
|
||||
return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
|
||||
sig, siglen, rsa);
|
||||
if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
|
||||
RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
if (rctx->pad_mode == RSA_X931_PADDING) {
|
||||
if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0)
|
||||
return 0;
|
||||
} else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
|
||||
int ret;
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
ret = RSA_public_decrypt(siglen, sig, rctx->tbuf,
|
||||
rsa, RSA_NO_PADDING);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
|
||||
rctx->md, rctx->mgf1md,
|
||||
rctx->tbuf, rctx->saltlen);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
} else {
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
|
||||
rsa, rctx->pad_mode);
|
||||
if (rslen == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
|
||||
unsigned char *out, size_t *outlen,
|
||||
const unsigned char *in, size_t inlen)
|
||||
{
|
||||
int ret;
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
|
||||
int klen = RSA_size(ctx->pkey->pkey.rsa);
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
|
||||
in, inlen,
|
||||
rctx->oaep_label,
|
||||
rctx->oaep_labellen,
|
||||
rctx->md, rctx->mgf1md))
|
||||
return -1;
|
||||
ret = RSA_public_encrypt(klen, rctx->tbuf, out,
|
||||
ctx->pkey->pkey.rsa, RSA_NO_PADDING);
|
||||
} else
|
||||
ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
|
||||
rctx->pad_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*outlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
|
||||
unsigned char *out, size_t *outlen,
|
||||
const unsigned char *in, size_t inlen)
|
||||
{
|
||||
int ret;
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
ret = RSA_private_decrypt(inlen, in, rctx->tbuf,
|
||||
ctx->pkey->pkey.rsa, RSA_NO_PADDING);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf,
|
||||
ret, ret,
|
||||
rctx->oaep_label,
|
||||
rctx->oaep_labellen,
|
||||
rctx->md, rctx->mgf1md);
|
||||
} else
|
||||
ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
|
||||
rctx->pad_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*outlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_padding_md(const EVP_MD *md, int padding)
|
||||
{
|
||||
int mdnid;
|
||||
if (!md)
|
||||
return 1;
|
||||
|
||||
mdnid = EVP_MD_type(md);
|
||||
|
||||
if (padding == RSA_NO_PADDING) {
|
||||
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_PADDING_MODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
if (RSA_X931_hash_id(mdnid) == -1) {
|
||||
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_X931_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
switch(mdnid) {
|
||||
/* List of all supported RSA digests */
|
||||
case NID_sha1:
|
||||
case NID_sha224:
|
||||
case NID_sha256:
|
||||
case NID_sha384:
|
||||
case NID_sha512:
|
||||
case NID_md5:
|
||||
case NID_md5_sha1:
|
||||
case NID_md2:
|
||||
case NID_md4:
|
||||
case NID_mdc2:
|
||||
case NID_ripemd160:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_DIGEST);
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
switch (type) {
|
||||
case EVP_PKEY_CTRL_RSA_PADDING:
|
||||
if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
|
||||
if (!check_padding_md(rctx->md, p1))
|
||||
return 0;
|
||||
if (p1 == RSA_PKCS1_PSS_PADDING) {
|
||||
if (!(ctx->operation &
|
||||
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
|
||||
goto bad_pad;
|
||||
if (!rctx->md)
|
||||
rctx->md = EVP_sha1();
|
||||
}
|
||||
if (p1 == RSA_PKCS1_OAEP_PADDING) {
|
||||
if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
|
||||
goto bad_pad;
|
||||
if (!rctx->md)
|
||||
rctx->md = EVP_sha1();
|
||||
}
|
||||
rctx->pad_mode = p1;
|
||||
return 1;
|
||||
}
|
||||
bad_pad:
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL,
|
||||
RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
|
||||
return -2;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_RSA_PADDING:
|
||||
*(int *)p2 = rctx->pad_mode;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
|
||||
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
|
||||
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
|
||||
return -2;
|
||||
}
|
||||
if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
|
||||
*(int *)p2 = rctx->saltlen;
|
||||
else {
|
||||
if (p1 < -2)
|
||||
return -2;
|
||||
rctx->saltlen = p1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
|
||||
if (p1 < 512) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -2;
|
||||
}
|
||||
rctx->nbits = p1;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
|
||||
if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE);
|
||||
return -2;
|
||||
}
|
||||
BN_free(rctx->pub_exp);
|
||||
rctx->pub_exp = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_MD:
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
|
||||
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
|
||||
return -2;
|
||||
}
|
||||
if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
|
||||
*(const EVP_MD **)p2 = rctx->md;
|
||||
else
|
||||
rctx->md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
if (!check_padding_md(p2, rctx->pad_mode))
|
||||
return 0;
|
||||
rctx->md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_MD:
|
||||
*(const EVP_MD **)p2 = rctx->md;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_MGF1_MD:
|
||||
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
|
||||
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING
|
||||
&& rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
|
||||
return -2;
|
||||
}
|
||||
if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
|
||||
if (rctx->mgf1md)
|
||||
*(const EVP_MD **)p2 = rctx->mgf1md;
|
||||
else
|
||||
*(const EVP_MD **)p2 = rctx->md;
|
||||
} else
|
||||
rctx->mgf1md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
|
||||
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
|
||||
return -2;
|
||||
}
|
||||
OPENSSL_free(rctx->oaep_label);
|
||||
if (p2 && p1 > 0) {
|
||||
rctx->oaep_label = p2;
|
||||
rctx->oaep_labellen = p1;
|
||||
} else {
|
||||
rctx->oaep_label = NULL;
|
||||
rctx->oaep_labellen = 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
|
||||
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
|
||||
return -2;
|
||||
}
|
||||
*(unsigned char **)p2 = rctx->oaep_label;
|
||||
return rctx->oaep_labellen;
|
||||
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
|
||||
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
||||
return 1;
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case EVP_PKEY_CTRL_CMS_DECRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_ENCRYPT:
|
||||
case EVP_PKEY_CTRL_CMS_SIGN:
|
||||
return 1;
|
||||
#endif
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL,
|
||||
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
||||
return -2;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (!value) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(type, "rsa_padding_mode") == 0) {
|
||||
int pm;
|
||||
if (strcmp(value, "pkcs1") == 0)
|
||||
pm = RSA_PKCS1_PADDING;
|
||||
else if (strcmp(value, "sslv23") == 0)
|
||||
pm = RSA_SSLV23_PADDING;
|
||||
else if (strcmp(value, "none") == 0)
|
||||
pm = RSA_NO_PADDING;
|
||||
else if (strcmp(value, "oeap") == 0)
|
||||
pm = RSA_PKCS1_OAEP_PADDING;
|
||||
else if (strcmp(value, "oaep") == 0)
|
||||
pm = RSA_PKCS1_OAEP_PADDING;
|
||||
else if (strcmp(value, "x931") == 0)
|
||||
pm = RSA_X931_PADDING;
|
||||
else if (strcmp(value, "pss") == 0)
|
||||
pm = RSA_PKCS1_PSS_PADDING;
|
||||
else {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
return -2;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
|
||||
}
|
||||
|
||||
if (strcmp(type, "rsa_pss_saltlen") == 0) {
|
||||
int saltlen;
|
||||
saltlen = atoi(value);
|
||||
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
|
||||
}
|
||||
|
||||
if (strcmp(type, "rsa_keygen_bits") == 0) {
|
||||
int nbits;
|
||||
nbits = atoi(value);
|
||||
return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
|
||||
}
|
||||
|
||||
if (strcmp(type, "rsa_keygen_pubexp") == 0) {
|
||||
int ret;
|
||||
BIGNUM *pubexp = NULL;
|
||||
if (!BN_asc2bn(&pubexp, value))
|
||||
return 0;
|
||||
ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
|
||||
if (ret <= 0)
|
||||
BN_free(pubexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strcmp(type, "rsa_mgf1_md") == 0) {
|
||||
const EVP_MD *md;
|
||||
if ((md = EVP_get_digestbyname(value)) == NULL) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
|
||||
}
|
||||
|
||||
if (strcmp(type, "rsa_oaep_md") == 0) {
|
||||
const EVP_MD *md;
|
||||
if ((md = EVP_get_digestbyname(value)) == NULL) {
|
||||
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md);
|
||||
}
|
||||
if (strcmp(type, "rsa_oaep_label") == 0) {
|
||||
unsigned char *lab;
|
||||
long lablen;
|
||||
int ret;
|
||||
lab = OPENSSL_hexstr2buf(value, &lablen);
|
||||
if (!lab)
|
||||
return 0;
|
||||
ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
|
||||
if (ret <= 0)
|
||||
OPENSSL_free(lab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
RSA *rsa = NULL;
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
BN_GENCB *pcb;
|
||||
int ret;
|
||||
if (rctx->pub_exp == NULL) {
|
||||
rctx->pub_exp = BN_new();
|
||||
if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4))
|
||||
return 0;
|
||||
}
|
||||
rsa = RSA_new();
|
||||
if (rsa == NULL)
|
||||
return 0;
|
||||
if (ctx->pkey_gencb) {
|
||||
pcb = BN_GENCB_new();
|
||||
if (pcb == NULL) {
|
||||
RSA_free(rsa);
|
||||
return 0;
|
||||
}
|
||||
evp_pkey_set_cb_translate(pcb, ctx);
|
||||
} else
|
||||
pcb = NULL;
|
||||
ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
|
||||
BN_GENCB_free(pcb);
|
||||
if (ret > 0)
|
||||
EVP_PKEY_assign_RSA(pkey, rsa);
|
||||
else
|
||||
RSA_free(rsa);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD rsa_pkey_meth = {
|
||||
EVP_PKEY_RSA,
|
||||
EVP_PKEY_FLAG_AUTOARGLEN,
|
||||
pkey_rsa_init,
|
||||
pkey_rsa_copy,
|
||||
pkey_rsa_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_rsa_keygen,
|
||||
|
||||
0,
|
||||
pkey_rsa_sign,
|
||||
|
||||
0,
|
||||
pkey_rsa_verify,
|
||||
|
||||
0,
|
||||
pkey_rsa_verifyrecover,
|
||||
|
||||
0, 0, 0, 0,
|
||||
|
||||
0,
|
||||
pkey_rsa_encrypt,
|
||||
|
||||
0,
|
||||
pkey_rsa_decrypt,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_rsa_ctrl,
|
||||
pkey_rsa_ctrl_str
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int RSA_print_fp(FILE *fp, const RSA *x, int off)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
RSAerr(RSA_F_RSA_PRINT_FP, ERR_R_BUF_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = RSA_print(b, x, off);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
int RSA_print(BIO *bp, const RSA *x, int off)
|
||||
{
|
||||
EVP_PKEY *pk;
|
||||
int ret;
|
||||
pk = EVP_PKEY_new();
|
||||
if (pk == NULL || !EVP_PKEY_set1_RSA(pk, (RSA *)x))
|
||||
return 0;
|
||||
ret = EVP_PKEY_print_private(bp, pk, off, NULL);
|
||||
EVP_PKEY_free(pk);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
#if defined(_MSC_VER) && defined(_ARM_)
|
||||
# pragma optimize("g", off)
|
||||
#endif
|
||||
|
||||
int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
|
||||
const EVP_MD *Hash, const unsigned char *EM,
|
||||
int sLen)
|
||||
{
|
||||
return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
|
||||
}
|
||||
|
||||
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
|
||||
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
|
||||
const unsigned char *EM, int sLen)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
int hLen, maskedDBLen, MSBits, emLen;
|
||||
const unsigned char *H;
|
||||
unsigned char *DB = NULL;
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
unsigned char H_[EVP_MAX_MD_SIZE];
|
||||
|
||||
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
if (mgf1Hash == NULL)
|
||||
mgf1Hash = Hash;
|
||||
|
||||
hLen = EVP_MD_size(Hash);
|
||||
if (hLen < 0)
|
||||
goto err;
|
||||
/*-
|
||||
* Negative sLen has special meanings:
|
||||
* -1 sLen == hLen
|
||||
* -2 salt length is autorecovered from signature
|
||||
* -N reserved
|
||||
*/
|
||||
if (sLen == -1)
|
||||
sLen = hLen;
|
||||
else if (sLen == -2)
|
||||
sLen = -2;
|
||||
else if (sLen < -2) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
|
||||
emLen = RSA_size(rsa);
|
||||
if (EM[0] & (0xFF << MSBits)) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_FIRST_OCTET_INVALID);
|
||||
goto err;
|
||||
}
|
||||
if (MSBits == 0) {
|
||||
EM++;
|
||||
emLen--;
|
||||
}
|
||||
if (emLen < hLen + 2) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (sLen > emLen - hLen - 2) { /* sLen can be small negative */
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_DATA_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (EM[emLen - 1] != 0xbc) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_LAST_OCTET_INVALID);
|
||||
goto err;
|
||||
}
|
||||
maskedDBLen = emLen - hLen - 1;
|
||||
H = EM + maskedDBLen;
|
||||
DB = OPENSSL_malloc(maskedDBLen);
|
||||
if (DB == NULL) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0)
|
||||
goto err;
|
||||
for (i = 0; i < maskedDBLen; i++)
|
||||
DB[i] ^= EM[i];
|
||||
if (MSBits)
|
||||
DB[0] &= 0xFF >> (8 - MSBits);
|
||||
for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++) ;
|
||||
if (DB[i++] != 0x1) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_RECOVERY_FAILED);
|
||||
goto err;
|
||||
}
|
||||
if (sLen >= 0 && (maskedDBLen - i) != sLen) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_DigestInit_ex(ctx, Hash, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes))
|
||||
|| !EVP_DigestUpdate(ctx, mHash, hLen))
|
||||
goto err;
|
||||
if (maskedDBLen - i) {
|
||||
if (!EVP_DigestUpdate(ctx, DB + i, maskedDBLen - i))
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_DigestFinal_ex(ctx, H_, NULL))
|
||||
goto err;
|
||||
if (memcmp(H_, H, hLen)) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, RSA_R_BAD_SIGNATURE);
|
||||
ret = 0;
|
||||
} else
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(DB);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
|
||||
const unsigned char *mHash,
|
||||
const EVP_MD *Hash, int sLen)
|
||||
{
|
||||
return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
|
||||
}
|
||||
|
||||
int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
|
||||
const unsigned char *mHash,
|
||||
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
|
||||
int sLen)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
int hLen, maskedDBLen, MSBits, emLen;
|
||||
unsigned char *H, *salt = NULL, *p;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
|
||||
if (mgf1Hash == NULL)
|
||||
mgf1Hash = Hash;
|
||||
|
||||
hLen = EVP_MD_size(Hash);
|
||||
if (hLen < 0)
|
||||
goto err;
|
||||
/*-
|
||||
* Negative sLen has special meanings:
|
||||
* -1 sLen == hLen
|
||||
* -2 salt length is maximized
|
||||
* -N reserved
|
||||
*/
|
||||
if (sLen == -1)
|
||||
sLen = hLen;
|
||||
else if (sLen == -2)
|
||||
sLen = -2;
|
||||
else if (sLen < -2) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, RSA_R_SLEN_CHECK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
|
||||
emLen = RSA_size(rsa);
|
||||
if (MSBits == 0) {
|
||||
*EM++ = 0;
|
||||
emLen--;
|
||||
}
|
||||
if (emLen < hLen + 2) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
goto err;
|
||||
}
|
||||
if (sLen == -2) {
|
||||
sLen = emLen - hLen - 2;
|
||||
} else if (sLen > emLen - hLen - 2) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
goto err;
|
||||
}
|
||||
if (sLen > 0) {
|
||||
salt = OPENSSL_malloc(sLen);
|
||||
if (salt == NULL) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (RAND_bytes(salt, sLen) <= 0)
|
||||
goto err;
|
||||
}
|
||||
maskedDBLen = emLen - hLen - 1;
|
||||
H = EM + maskedDBLen;
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
if (!EVP_DigestInit_ex(ctx, Hash, NULL)
|
||||
|| !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes))
|
||||
|| !EVP_DigestUpdate(ctx, mHash, hLen))
|
||||
goto err;
|
||||
if (sLen && !EVP_DigestUpdate(ctx, salt, sLen))
|
||||
goto err;
|
||||
if (!EVP_DigestFinal_ex(ctx, H, NULL))
|
||||
goto err;
|
||||
|
||||
/* Generate dbMask in place then perform XOR on it */
|
||||
if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash))
|
||||
goto err;
|
||||
|
||||
p = EM;
|
||||
|
||||
/*
|
||||
* Initial PS XORs with all zeroes which is a NOP so just update pointer.
|
||||
* Note from a test above this value is guaranteed to be non-negative.
|
||||
*/
|
||||
p += emLen - sLen - hLen - 2;
|
||||
*p++ ^= 0x1;
|
||||
if (sLen > 0) {
|
||||
for (i = 0; i < sLen; i++)
|
||||
*p++ ^= salt[i];
|
||||
}
|
||||
if (MSBits)
|
||||
EM[0] &= 0xFF >> (8 - MSBits);
|
||||
|
||||
/* H is already in place so just set final 0xbc */
|
||||
|
||||
EM[emLen - 1] = 0xbc;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
OPENSSL_free(salt);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma optimize("",on)
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
int RSA_sign_ASN1_OCTET_STRING(int type,
|
||||
const unsigned char *m, unsigned int m_len,
|
||||
unsigned char *sigret, unsigned int *siglen,
|
||||
RSA *rsa)
|
||||
{
|
||||
ASN1_OCTET_STRING sig;
|
||||
int i, j, ret = 1;
|
||||
unsigned char *p, *s;
|
||||
|
||||
sig.type = V_ASN1_OCTET_STRING;
|
||||
sig.length = m_len;
|
||||
sig.data = (unsigned char *)m;
|
||||
|
||||
i = i2d_ASN1_OCTET_STRING(&sig, NULL);
|
||||
j = RSA_size(rsa);
|
||||
if (i > (j - RSA_PKCS1_PADDING_SIZE)) {
|
||||
RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING,
|
||||
RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
|
||||
return (0);
|
||||
}
|
||||
s = OPENSSL_malloc((unsigned int)j + 1);
|
||||
if (s == NULL) {
|
||||
RSAerr(RSA_F_RSA_SIGN_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
p = s;
|
||||
i2d_ASN1_OCTET_STRING(&sig, &p);
|
||||
i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING);
|
||||
if (i <= 0)
|
||||
ret = 0;
|
||||
else
|
||||
*siglen = i;
|
||||
|
||||
OPENSSL_clear_free(s, (unsigned int)j + 1);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int RSA_verify_ASN1_OCTET_STRING(int dtype,
|
||||
const unsigned char *m,
|
||||
unsigned int m_len, unsigned char *sigbuf,
|
||||
unsigned int siglen, RSA *rsa)
|
||||
{
|
||||
int i, ret = 0;
|
||||
unsigned char *s;
|
||||
const unsigned char *p;
|
||||
ASN1_OCTET_STRING *sig = NULL;
|
||||
|
||||
if (siglen != (unsigned int)RSA_size(rsa)) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING,
|
||||
RSA_R_WRONG_SIGNATURE_LENGTH);
|
||||
return (0);
|
||||
}
|
||||
|
||||
s = OPENSSL_malloc((unsigned int)siglen);
|
||||
if (s == NULL) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);
|
||||
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
|
||||
p = s;
|
||||
sig = d2i_ASN1_OCTET_STRING(NULL, &p, (long)i);
|
||||
if (sig == NULL)
|
||||
goto err;
|
||||
|
||||
if (((unsigned int)sig->length != m_len) ||
|
||||
(memcmp(m, sig->data, m_len) != 0)) {
|
||||
RSAerr(RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, RSA_R_BAD_SIGNATURE);
|
||||
} else
|
||||
ret = 1;
|
||||
err:
|
||||
ASN1_OCTET_STRING_free(sig);
|
||||
OPENSSL_clear_free(s, (unsigned int)siglen);
|
||||
return (ret);
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/x509.h>
|
||||
#include "internal/x509_int.h"
|
||||
#include "rsa_locl.h"
|
||||
|
||||
/* Size of an SSL signature: MD5+SHA1 */
|
||||
#define SSL_SIG_LENGTH 36
|
||||
|
||||
/*
|
||||
* encode_pkcs1 encodes a DigestInfo prefix of hash |type| and digest |m|, as
|
||||
* described in EMSA-PKCS1-v1_5-ENCODE, RFC 3447 section 9.2 step 2. This
|
||||
* encodes the DigestInfo (T and tLen) but does not add the padding.
|
||||
*
|
||||
* On success, it returns one and sets |*out| to a newly allocated buffer
|
||||
* containing the result and |*out_len| to its length. The caller must free
|
||||
* |*out| with |OPENSSL_free|. Otherwise, it returns zero.
|
||||
*/
|
||||
static int encode_pkcs1(unsigned char **out, int *out_len, int type,
|
||||
const unsigned char *m, unsigned int m_len)
|
||||
{
|
||||
X509_SIG sig;
|
||||
X509_ALGOR algor;
|
||||
ASN1_TYPE parameter;
|
||||
ASN1_OCTET_STRING digest;
|
||||
uint8_t *der = NULL;
|
||||
int len;
|
||||
|
||||
sig.algor = &algor;
|
||||
sig.algor->algorithm = OBJ_nid2obj(type);
|
||||
if (sig.algor->algorithm == NULL) {
|
||||
RSAerr(RSA_F_ENCODE_PKCS1, RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (OBJ_length(sig.algor->algorithm) == 0) {
|
||||
RSAerr(RSA_F_ENCODE_PKCS1,
|
||||
RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
|
||||
return 0;
|
||||
}
|
||||
parameter.type = V_ASN1_NULL;
|
||||
parameter.value.ptr = NULL;
|
||||
sig.algor->parameter = ¶meter;
|
||||
|
||||
sig.digest = &digest;
|
||||
sig.digest->data = (unsigned char *)m;
|
||||
sig.digest->length = m_len;
|
||||
|
||||
len = i2d_X509_SIG(&sig, &der);
|
||||
if (len < 0)
|
||||
return 0;
|
||||
|
||||
*out = der;
|
||||
*out_len = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RSA_sign(int type, const unsigned char *m, unsigned int m_len,
|
||||
unsigned char *sigret, unsigned int *siglen, RSA *rsa)
|
||||
{
|
||||
int encrypt_len, encoded_len = 0, ret = 0;
|
||||
unsigned char *tmps = NULL;
|
||||
const unsigned char *encoded = NULL;
|
||||
|
||||
if (rsa->meth->rsa_sign) {
|
||||
return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
|
||||
}
|
||||
|
||||
/* Compute the encoded digest. */
|
||||
if (type == NID_md5_sha1) {
|
||||
/*
|
||||
* NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and
|
||||
* earlier. It has no DigestInfo wrapper but otherwise is
|
||||
* RSASSA-PKCS1-v1_5.
|
||||
*/
|
||||
if (m_len != SSL_SIG_LENGTH) {
|
||||
RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
encoded_len = SSL_SIG_LENGTH;
|
||||
encoded = m;
|
||||
} else {
|
||||
if (!encode_pkcs1(&tmps, &encoded_len, type, m, m_len))
|
||||
goto err;
|
||||
encoded = tmps;
|
||||
}
|
||||
|
||||
if (encoded_len > RSA_size(rsa) - RSA_PKCS1_PADDING_SIZE) {
|
||||
RSAerr(RSA_F_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
|
||||
goto err;
|
||||
}
|
||||
encrypt_len = RSA_private_encrypt(encoded_len, encoded, sigret, rsa,
|
||||
RSA_PKCS1_PADDING);
|
||||
if (encrypt_len <= 0)
|
||||
goto err;
|
||||
|
||||
*siglen = encrypt_len;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_clear_free(tmps, (size_t)encoded_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* int_rsa_verify verifies an RSA signature in |sigbuf| using |rsa|. It may be
|
||||
* called in two modes. If |rm| is NULL, it verifies the signature for digest
|
||||
* |m|. Otherwise, it recovers the digest from the signature, writing the digest
|
||||
* to |rm| and the length to |*prm_len|. |type| is the NID of the digest
|
||||
* algorithm to use. It returns one on successful verification and zero
|
||||
* otherwise.
|
||||
*/
|
||||
int int_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
|
||||
unsigned char *rm, size_t *prm_len,
|
||||
const unsigned char *sigbuf, size_t siglen, RSA *rsa)
|
||||
{
|
||||
int decrypt_len, ret = 0, encoded_len = 0;
|
||||
unsigned char *decrypt_buf = NULL, *encoded = NULL;
|
||||
|
||||
if (siglen != (size_t)RSA_size(rsa)) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Recover the encoded digest. */
|
||||
decrypt_buf = OPENSSL_malloc(siglen);
|
||||
if (decrypt_buf == NULL) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
decrypt_len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf, rsa,
|
||||
RSA_PKCS1_PADDING);
|
||||
if (decrypt_len <= 0)
|
||||
goto err;
|
||||
|
||||
if (type == NID_md5_sha1) {
|
||||
/*
|
||||
* NID_md5_sha1 corresponds to the MD5/SHA1 combination in TLS 1.1 and
|
||||
* earlier. It has no DigestInfo wrapper but otherwise is
|
||||
* RSASSA-PKCS1-v1_5.
|
||||
*/
|
||||
if (decrypt_len != SSL_SIG_LENGTH) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rm != NULL) {
|
||||
memcpy(rm, decrypt_buf, SSL_SIG_LENGTH);
|
||||
*prm_len = SSL_SIG_LENGTH;
|
||||
} else {
|
||||
if (m_len != SSL_SIG_LENGTH) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(decrypt_buf, m, SSL_SIG_LENGTH) != 0) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else if (type == NID_mdc2 && decrypt_len == 2 + 16
|
||||
&& decrypt_buf[0] == 0x04 && decrypt_buf[1] == 0x10) {
|
||||
/*
|
||||
* Oddball MDC2 case: signature can be OCTET STRING. check for correct
|
||||
* tag and length octets.
|
||||
*/
|
||||
if (rm != NULL) {
|
||||
memcpy(rm, decrypt_buf + 2, 16);
|
||||
*prm_len = 16;
|
||||
} else {
|
||||
if (m_len != 16) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(m, decrypt_buf + 2, 16) != 0) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If recovering the digest, extract a digest-sized output from the end
|
||||
* of |decrypt_buf| for |encode_pkcs1|, then compare the decryption
|
||||
* output as in a standard verification.
|
||||
*/
|
||||
if (rm != NULL) {
|
||||
const EVP_MD *md = EVP_get_digestbynid(type);
|
||||
if (md == NULL) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
m_len = EVP_MD_size(md);
|
||||
if (m_len > (size_t)decrypt_len) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
m = decrypt_buf + decrypt_len - m_len;
|
||||
}
|
||||
|
||||
/* Construct the encoded digest and ensure it matches. */
|
||||
if (!encode_pkcs1(&encoded, &encoded_len, type, m, m_len))
|
||||
goto err;
|
||||
|
||||
if (encoded_len != decrypt_len
|
||||
|| memcmp(encoded, decrypt_buf, encoded_len) != 0) {
|
||||
RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Output the recovered digest. */
|
||||
if (rm != NULL) {
|
||||
memcpy(rm, m, m_len);
|
||||
*prm_len = m_len;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_clear_free(encoded, (size_t)encoded_len);
|
||||
OPENSSL_clear_free(decrypt_buf, siglen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RSA_verify(int type, const unsigned char *m, unsigned int m_len,
|
||||
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
|
||||
{
|
||||
|
||||
if (rsa->meth->rsa_verify) {
|
||||
return rsa->meth->rsa_verify(type, m, m_len, sigbuf, siglen, rsa);
|
||||
}
|
||||
|
||||
return int_rsa_verify(type, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char *p;
|
||||
|
||||
if (flen > (tlen - 11)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_SSLV23,
|
||||
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
p = (unsigned char *)to;
|
||||
|
||||
*(p++) = 0;
|
||||
*(p++) = 2; /* Public Key BT (Block Type) */
|
||||
|
||||
/* pad out with non-zero random data */
|
||||
j = tlen - 3 - 8 - flen;
|
||||
|
||||
if (RAND_bytes(p, j) <= 0)
|
||||
return (0);
|
||||
for (i = 0; i < j; i++) {
|
||||
if (*p == '\0')
|
||||
do {
|
||||
if (RAND_bytes(p, 1) <= 0)
|
||||
return (0);
|
||||
} while (*p == '\0');
|
||||
p++;
|
||||
}
|
||||
|
||||
memset(p, 3, 8);
|
||||
p += 8;
|
||||
*(p++) = '\0';
|
||||
|
||||
memcpy(p, from, (unsigned int)flen);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen, int num)
|
||||
{
|
||||
int i, j, k;
|
||||
const unsigned char *p;
|
||||
|
||||
p = from;
|
||||
if (flen < 10) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
|
||||
return (-1);
|
||||
}
|
||||
if ((num != (flen + 1)) || (*(p++) != 02)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_BLOCK_TYPE_IS_NOT_02);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* scan over padding data */
|
||||
j = flen - 1; /* one for type */
|
||||
for (i = 0; i < j; i++)
|
||||
if (*(p++) == 0)
|
||||
break;
|
||||
|
||||
if ((i == j) || (i < 8)) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23,
|
||||
RSA_R_NULL_BEFORE_BLOCK_MISSING);
|
||||
return (-1);
|
||||
}
|
||||
for (k = -9; k < -1; k++) {
|
||||
if (p[k] != 0x03)
|
||||
break;
|
||||
}
|
||||
if (k == -1) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_SSLV3_ROLLBACK_ATTACK);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
i++; /* Skip over the '\0' */
|
||||
j -= i;
|
||||
if (j > tlen) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_LARGE);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(to, p, (unsigned int)j);
|
||||
|
||||
return (j);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/objects.h>
|
||||
|
||||
int RSA_padding_add_X931(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen)
|
||||
{
|
||||
int j;
|
||||
unsigned char *p;
|
||||
|
||||
/*
|
||||
* Absolute minimum amount of padding is 1 header nibble, 1 padding
|
||||
* nibble and 2 trailer bytes: but 1 hash if is already in 'from'.
|
||||
*/
|
||||
|
||||
j = tlen - flen - 2;
|
||||
|
||||
if (j < 0) {
|
||||
RSAerr(RSA_F_RSA_PADDING_ADD_X931, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = (unsigned char *)to;
|
||||
|
||||
/* If no padding start and end nibbles are in one byte */
|
||||
if (j == 0)
|
||||
*p++ = 0x6A;
|
||||
else {
|
||||
*p++ = 0x6B;
|
||||
if (j > 1) {
|
||||
memset(p, 0xBB, j - 1);
|
||||
p += j - 1;
|
||||
}
|
||||
*p++ = 0xBA;
|
||||
}
|
||||
memcpy(p, from, (unsigned int)flen);
|
||||
p += flen;
|
||||
*p = 0xCC;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int RSA_padding_check_X931(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen, int num)
|
||||
{
|
||||
int i = 0, j;
|
||||
const unsigned char *p;
|
||||
|
||||
p = from;
|
||||
if ((num != flen) || ((*p != 0x6A) && (*p != 0x6B))) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_HEADER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p++ == 0x6B) {
|
||||
j = flen - 3;
|
||||
for (i = 0; i < j; i++) {
|
||||
unsigned char c = *p++;
|
||||
if (c == 0xBA)
|
||||
break;
|
||||
if (c != 0xBB) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_PADDING);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
j -= i;
|
||||
|
||||
if (i == 0) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_PADDING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else
|
||||
j = flen - 2;
|
||||
|
||||
if (p[j] != 0xCC) {
|
||||
RSAerr(RSA_F_RSA_PADDING_CHECK_X931, RSA_R_INVALID_TRAILER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(to, p, (unsigned int)j);
|
||||
|
||||
return (j);
|
||||
}
|
||||
|
||||
/* Translate between X931 hash ids and NIDs */
|
||||
|
||||
int RSA_X931_hash_id(int nid)
|
||||
{
|
||||
switch (nid) {
|
||||
case NID_sha1:
|
||||
return 0x33;
|
||||
|
||||
case NID_sha256:
|
||||
return 0x34;
|
||||
|
||||
case NID_sha384:
|
||||
return 0x36;
|
||||
|
||||
case NID_sha512:
|
||||
return 0x35;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "rsa_locl.h"
|
||||
|
||||
/* X9.31 RSA key derivation and generation */
|
||||
|
||||
int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
|
||||
BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2,
|
||||
const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2,
|
||||
const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL;
|
||||
BN_CTX *ctx = NULL, *ctx2 = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!rsa)
|
||||
goto err;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
r0 = BN_CTX_get(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
r2 = BN_CTX_get(ctx);
|
||||
r3 = BN_CTX_get(ctx);
|
||||
|
||||
if (r3 == NULL)
|
||||
goto err;
|
||||
if (!rsa->e) {
|
||||
rsa->e = BN_dup(e);
|
||||
if (!rsa->e)
|
||||
goto err;
|
||||
} else
|
||||
e = rsa->e;
|
||||
|
||||
/*
|
||||
* If not all parameters present only calculate what we can. This allows
|
||||
* test programs to output selective parameters.
|
||||
*/
|
||||
|
||||
if (Xp && rsa->p == NULL) {
|
||||
rsa->p = BN_new();
|
||||
if (rsa->p == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_X931_derive_prime_ex(rsa->p, p1, p2,
|
||||
Xp, Xp1, Xp2, e, ctx, cb))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (Xq && rsa->q == NULL) {
|
||||
rsa->q = BN_new();
|
||||
if (rsa->q == NULL)
|
||||
goto err;
|
||||
if (!BN_X931_derive_prime_ex(rsa->q, q1, q2,
|
||||
Xq, Xq1, Xq2, e, ctx, cb))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->p == NULL || rsa->q == NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since both primes are set we can now calculate all remaining
|
||||
* components.
|
||||
*/
|
||||
|
||||
/* calculate n */
|
||||
rsa->n = BN_new();
|
||||
if (rsa->n == NULL)
|
||||
goto err;
|
||||
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d */
|
||||
if (!BN_sub(r1, rsa->p, BN_value_one()))
|
||||
goto err; /* p-1 */
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err; /* q-1 */
|
||||
if (!BN_mul(r0, r1, r2, ctx))
|
||||
goto err; /* (p-1)(q-1) */
|
||||
|
||||
if (!BN_gcd(r3, r1, r2, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_div(r0, NULL, r0, r3, ctx))
|
||||
goto err; /* LCM((p-1)(q-1)) */
|
||||
|
||||
ctx2 = BN_CTX_new();
|
||||
if (ctx2 == NULL)
|
||||
goto err;
|
||||
|
||||
rsa->d = BN_mod_inverse(NULL, rsa->e, r0, ctx2); /* d */
|
||||
if (rsa->d == NULL)
|
||||
goto err;
|
||||
|
||||
/* calculate d mod (p-1) */
|
||||
rsa->dmp1 = BN_new();
|
||||
if (rsa->dmp1 == NULL)
|
||||
goto err;
|
||||
if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d mod (q-1) */
|
||||
rsa->dmq1 = BN_new();
|
||||
if (rsa->dmq1 == NULL)
|
||||
goto err;
|
||||
if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate inverse of q mod p */
|
||||
rsa->iqmp = BN_mod_inverse(NULL, rsa->q, rsa->p, ctx2);
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
BN_CTX_free(ctx2);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
int ok = 0;
|
||||
BIGNUM *Xp = NULL, *Xq = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto error;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
Xp = BN_CTX_get(ctx);
|
||||
Xq = BN_CTX_get(ctx);
|
||||
if (Xq == NULL)
|
||||
goto error;
|
||||
if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx))
|
||||
goto error;
|
||||
|
||||
rsa->p = BN_new();
|
||||
rsa->q = BN_new();
|
||||
if (rsa->p == NULL || rsa->q == NULL)
|
||||
goto error;
|
||||
|
||||
/* Generate two primes from Xp, Xq */
|
||||
|
||||
if (!BN_X931_generate_prime_ex(rsa->p, NULL, NULL, NULL, NULL, Xp,
|
||||
e, ctx, cb))
|
||||
goto error;
|
||||
|
||||
if (!BN_X931_generate_prime_ex(rsa->q, NULL, NULL, NULL, NULL, Xq,
|
||||
e, ctx, cb))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Since rsa->p and rsa->q are valid this call will just derive remaining
|
||||
* RSA components.
|
||||
*/
|
||||
|
||||
if (!RSA_X931_derive_ex(rsa, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, e, cb))
|
||||
goto error;
|
||||
|
||||
ok = 1;
|
||||
|
||||
error:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
if (ok)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user