1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78

This commit is contained in:
winlin 2021-03-01 20:47:57 +08:00
parent 8f1c992379
commit 96dbd7bced
1476 changed files with 616554 additions and 4 deletions

View file

@ -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_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 rsa_mp.c

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,121 @@
/*
* Copyright 2000-2017 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,
* and calculate helper products for multi-prime
* RSA keys.
*/
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;
} else if (operation == ASN1_OP_D2I_POST) {
if (((RSA *)*pval)->version != RSA_ASN1_VERSION_MULTI) {
/* not a multi-prime key, skip */
return 1;
}
return (rsa_multip_calc_product((RSA *)*pval) == 1) ? 2 : 0;
}
return 1;
}
/* Based on definitions in RFC 8017 appendix A.1.2 */
ASN1_SEQUENCE(RSA_PRIME_INFO) = {
ASN1_SIMPLE(RSA_PRIME_INFO, r, CBIGNUM),
ASN1_SIMPLE(RSA_PRIME_INFO, d, CBIGNUM),
ASN1_SIMPLE(RSA_PRIME_INFO, t, CBIGNUM),
} ASN1_SEQUENCE_END(RSA_PRIME_INFO)
ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
ASN1_EMBED(RSA, version, INT32),
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_OF_OPT(RSA, prime_infos, RSA_PRIME_INFO)
} 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)
/* Free up maskHash */
static int rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_FREE_PRE) {
RSA_PSS_PARAMS *pss = (RSA_PSS_PARAMS *)*pval;
X509_ALGOR_free(pss->maskHash);
}
return 1;
}
ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = {
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_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS)
IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
/* Free up maskHash */
static int rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_FREE_PRE) {
RSA_OAEP_PARAMS *oaep = (RSA_OAEP_PARAMS *)*pval;
X509_ALGOR_free(oaep->maskHash);
}
return 1;
}
ASN1_SEQUENCE_cb(RSA_OAEP_PARAMS, rsa_oaep_cb) = {
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_cb(RSA_OAEP_PARAMS, 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);
}

View file

@ -0,0 +1,228 @@
/*
* Copyright 1999-2017 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, ex_primes = 0, idx;
RSA_PRIME_INFO *pinfo;
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;
}
/* multi-prime? */
if (key->version == RSA_ASN1_VERSION_MULTI) {
ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos);
if (ex_primes <= 0
|| (ex_primes + 2) > rsa_multip_cap(BN_num_bits(key->n))) {
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_INVALID_MULTI_PRIME_KEY);
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);
}
/* r_i prime? */
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (BN_is_prime_ex(pinfo->r, BN_prime_checks, NULL, cb) != 1) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_R_NOT_PRIME);
}
}
/* n = p*q * r_3...r_i? */
if (!BN_mul(i, key->p, key->q, ctx)) {
ret = -1;
goto err;
}
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (!BN_mul(i, i, pinfo->r, ctx)) {
ret = -1;
goto err;
}
}
if (BN_cmp(i, key->n) != 0) {
ret = 0;
if (ex_primes)
RSAerr(RSA_F_RSA_CHECK_KEY_EX,
RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES);
else
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_N_DOES_NOT_EQUAL_P_Q);
}
/* d*e = 1 mod \lambda(n)? */
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 = \lambda(n) = LCM(i, j, r_3 - 1...) */
if (!BN_mul(l, i, j, ctx)) {
ret = -1;
goto err;
}
if (!BN_gcd(m, i, j, ctx)) {
ret = -1;
goto err;
}
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
if (!BN_sub(k, pinfo->r, BN_value_one())) {
ret = -1;
goto err;
}
if (!BN_mul(l, l, k, ctx)) {
ret = -1;
goto err;
}
if (!BN_gcd(m, m, k, 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);
}
}
for (idx = 0; idx < ex_primes; idx++) {
pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx);
/* d_i = d mod (r_i - 1)? */
if (!BN_sub(i, pinfo->r, BN_value_one())) {
ret = -1;
goto err;
}
if (!BN_mod(j, key->d, i, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(j, pinfo->d) != 0) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D);
}
/* t_i = R_i ^ -1 mod r_i ? */
if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) {
ret = -1;
goto err;
}
if (BN_cmp(i, pinfo->t) != 0) {
ret = 0;
RSAerr(RSA_F_RSA_CHECK_KEY_EX, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R);
}
}
err:
BN_free(i);
BN_free(j);
BN_free(k);
BN_free(l);
BN_free(m);
BN_CTX_free(ctx);
return ret;
}

View file

@ -0,0 +1,169 @@
/*
* Copyright 1995-2017 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 "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;
}
{
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;
}

View file

@ -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

View file

@ -0,0 +1,246 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* 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
*/
#include <openssl/err.h>
#include <openssl/rsaerr.h>
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA RSA_str_functs[] = {
{ERR_PACK(ERR_LIB_RSA, RSA_F_CHECK_PADDING_MD, 0), "check_padding_md"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_ENCODE_PKCS1, 0), "encode_pkcs1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_INT_RSA_VERIFY, 0), "int_rsa_verify"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_OLD_RSA_PRIV_DECODE, 0),
"old_rsa_priv_decode"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_PSS_INIT, 0), "pkey_pss_init"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, 0), "pkey_rsa_ctrl"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL_STR, 0), "pkey_rsa_ctrl_str"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_SIGN, 0), "pkey_rsa_sign"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_VERIFY, 0), "pkey_rsa_verify"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_VERIFYRECOVER, 0),
"pkey_rsa_verifyrecover"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ALGOR_TO_MD, 0), "rsa_algor_to_md"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_BUILTIN_KEYGEN, 0), "rsa_builtin_keygen"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY, 0), "RSA_check_key"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CHECK_KEY_EX, 0), "RSA_check_key_ex"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_DECRYPT, 0), "rsa_cms_decrypt"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_CMS_VERIFY, 0), "rsa_cms_verify"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_ITEM_VERIFY, 0), "rsa_item_verify"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_DUP, 0), "RSA_meth_dup"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_NEW, 0), "RSA_meth_new"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_METH_SET1_NAME, 0), "RSA_meth_set1_name"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_MGF1_TO_MD, 0), ""},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_MULTIP_INFO_NEW, 0),
"rsa_multip_info_new"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NEW_METHOD, 0), "RSA_new_method"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL, 0), ""},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, 0), ""},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_ENCRYPT, 0), ""},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PUBLIC_DECRYPT, 0), ""},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_NULL_PUBLIC_ENCRYPT, 0), ""},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, 0),
"rsa_ossl_private_decrypt"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, 0),
"rsa_ossl_private_encrypt"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_DECRYPT, 0),
"rsa_ossl_public_decrypt"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, 0),
"rsa_ossl_public_encrypt"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_NONE, 0),
"RSA_padding_add_none"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, 0),
"RSA_padding_add_PKCS1_OAEP"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, 0),
"RSA_padding_add_PKCS1_OAEP_mgf1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_PSS, 0),
"RSA_padding_add_PKCS1_PSS"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1, 0),
"RSA_padding_add_PKCS1_PSS_mgf1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1, 0),
"RSA_padding_add_PKCS1_type_1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2, 0),
"RSA_padding_add_PKCS1_type_2"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_SSLV23, 0),
"RSA_padding_add_SSLv23"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_ADD_X931, 0),
"RSA_padding_add_X931"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_NONE, 0),
"RSA_padding_check_none"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, 0),
"RSA_padding_check_PKCS1_OAEP"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, 0),
"RSA_padding_check_PKCS1_OAEP_mgf1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, 0),
"RSA_padding_check_PKCS1_type_1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, 0),
"RSA_padding_check_PKCS1_type_2"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_SSLV23, 0),
"RSA_padding_check_SSLv23"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PADDING_CHECK_X931, 0),
"RSA_padding_check_X931"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PARAM_DECODE, 0), "rsa_param_decode"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT, 0), "RSA_print"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRINT_FP, 0), "RSA_print_fp"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_DECODE, 0), "rsa_priv_decode"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PRIV_ENCODE, 0), "rsa_priv_encode"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_GET_PARAM, 0), "rsa_pss_get_param"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PSS_TO_CTX, 0), "rsa_pss_to_ctx"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_PUB_DECODE, 0), "rsa_pub_decode"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SETUP_BLINDING, 0), "RSA_setup_blinding"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN, 0), "RSA_sign"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_SIGN_ASN1_OCTET_STRING, 0),
"RSA_sign_ASN1_OCTET_STRING"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY, 0), "RSA_verify"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_ASN1_OCTET_STRING, 0),
"RSA_verify_ASN1_OCTET_STRING"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1, 0),
"RSA_verify_PKCS1_PSS_mgf1"},
{ERR_PACK(ERR_LIB_RSA, RSA_F_SETUP_TBUF, 0), "setup_tbuf"},
{0, NULL}
};
static const ERR_STRING_DATA RSA_str_reasons[] = {
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ALGORITHM_MISMATCH), "algorithm mismatch"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_E_VALUE), "bad e value"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_FIXED_HEADER_DECRYPT),
"bad fixed header decrypt"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_PAD_BYTE_COUNT), "bad pad byte count"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BAD_SIGNATURE), "bad signature"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_01),
"block type is not 01"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_BLOCK_TYPE_IS_NOT_02),
"block type is not 02"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_GREATER_THAN_MOD_LEN),
"data greater than mod len"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE), "data too large"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE),
"data too large for key size"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_LARGE_FOR_MODULUS),
"data too large for modulus"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL), "data too small"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE),
"data too small for key size"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_DOES_NOT_MATCH),
"digest does not match"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_NOT_ALLOWED), "digest not allowed"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY),
"digest too big for rsa key"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DMP1_NOT_CONGRUENT_TO_D),
"dmp1 not congruent to d"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_DMQ1_NOT_CONGRUENT_TO_D),
"dmq1 not congruent to d"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_D_E_NOT_CONGRUENT_TO_1),
"d e not congruent to 1"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_FIRST_OCTET_INVALID),
"first octet invalid"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE),
"illegal or unsupported padding mode"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_DIGEST), "invalid digest"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_DIGEST_LENGTH),
"invalid digest length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_HEADER), "invalid header"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_LABEL), "invalid label"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MESSAGE_LENGTH),
"invalid message length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MGF1_MD), "invalid mgf1 md"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_MULTI_PRIME_KEY),
"invalid multi prime key"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_OAEP_PARAMETERS),
"invalid oaep parameters"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PADDING), "invalid padding"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PADDING_MODE),
"invalid padding mode"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PSS_PARAMETERS),
"invalid pss parameters"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_PSS_SALTLEN),
"invalid pss saltlen"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_SALT_LENGTH),
"invalid salt length"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_TRAILER), "invalid trailer"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_INVALID_X931_DIGEST),
"invalid x931 digest"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_IQMP_NOT_INVERSE_OF_Q),
"iqmp not inverse of q"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_PRIME_NUM_INVALID),
"key prime num invalid"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_KEY_SIZE_TOO_SMALL), "key size too small"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_LAST_OCTET_INVALID), "last octet invalid"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MGF1_DIGEST_NOT_ALLOWED),
"mgf1 digest not allowed"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MODULUS_TOO_LARGE), "modulus too large"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R),
"mp coefficient not inverse of r"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D),
"mp exponent not congruent to d"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_MP_R_NOT_PRIME), "mp r not prime"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NO_PUBLIC_EXPONENT), "no public exponent"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_NULL_BEFORE_BLOCK_MISSING),
"null before block missing"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES),
"n does not equal product of primes"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_P_Q),
"n does not equal p q"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OAEP_DECODING_ERROR),
"oaep decoding error"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),
"operation not supported for this keytype"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PADDING_CHECK_FAILED),
"padding check failed"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PKCS_DECODING_ERROR),
"pkcs decoding error"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_PSS_SALTLEN_TOO_SMALL),
"pss saltlen too small"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_P_NOT_PRIME), "p not prime"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_Q_NOT_PRIME), "q not prime"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED),
"rsa operations not supported"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_CHECK_FAILED),
"salt length check failed"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SLEN_RECOVERY_FAILED),
"salt length recovery failed"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_SSLV3_ROLLBACK_ATTACK),
"sslv3 rollback attack"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD),
"the asn1 object identifier is not known for this md"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_ALGORITHM_TYPE),
"unknown algorithm type"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_DIGEST), "unknown digest"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_MASK_DIGEST),
"unknown mask digest"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNKNOWN_PADDING_TYPE),
"unknown padding type"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE),
"unsupported encryption type"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_LABEL_SOURCE),
"unsupported label source"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_MASK_ALGORITHM),
"unsupported mask algorithm"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_MASK_PARAMETER),
"unsupported mask parameter"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_UNSUPPORTED_SIGNATURE_TYPE),
"unsupported signature type"},
{ERR_PACK(ERR_LIB_RSA, 0, RSA_R_VALUE_MISSING), "value missing"},
{ERR_PACK(ERR_LIB_RSA, 0, 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_const(RSA_str_functs);
ERR_load_strings_const(RSA_str_reasons);
}
#endif
return 1;
}

View file

@ -0,0 +1,394 @@
/*
* 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, int primes, 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 != NULL)
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
return RSA_generate_multi_prime_key(rsa, bits, RSA_DEFAULT_PRIME_NUM,
e_value, cb);
}
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
BIGNUM *e_value, BN_GENCB *cb)
{
/* multi-prime is only supported with the builtin key generation */
if (rsa->meth->rsa_multi_prime_keygen != NULL) {
return rsa->meth->rsa_multi_prime_keygen(rsa, bits, primes,
e_value, cb);
} else if (rsa->meth->rsa_keygen != NULL) {
/*
* However, if rsa->meth implements only rsa_keygen, then we
* have to honour it in 2-prime case and assume that it wouldn't
* know what to do with multi-prime key generated by builtin
* subroutine...
*/
if (primes == 2)
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
else
return 0;
}
return rsa_builtin_keygen(rsa, bits, primes, e_value, cb);
}
static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
BN_GENCB *cb)
{
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime;
int ok = -1, n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
RSA_PRIME_INFO *pinfo = NULL;
STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL;
BN_CTX *ctx = NULL;
BN_ULONG bitst = 0;
unsigned long error = 0;
if (bits < RSA_MIN_MODULUS_BITS) {
ok = 0; /* we set our own err */
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
goto err;
}
if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) {
ok = 0; /* we set our own err */
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID);
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);
if (r2 == NULL)
goto err;
/* divide bits into 'primes' pieces evenly */
quo = bits / primes;
rmd = bits % primes;
for (i = 0; i < primes; i++)
bitsr[i] = (i < rmd) ? quo + 1 : quo;
/* 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;
/* initialize multi-prime components */
if (primes > RSA_DEFAULT_PRIME_NUM) {
rsa->version = RSA_ASN1_VERSION_MULTI;
prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, primes - 2);
if (prime_infos == NULL)
goto err;
if (rsa->prime_infos != NULL) {
/* could this happen? */
sk_RSA_PRIME_INFO_pop_free(rsa->prime_infos, rsa_multip_info_free);
}
rsa->prime_infos = prime_infos;
/* prime_info from 2 to |primes| -1 */
for (i = 2; i < primes; i++) {
pinfo = rsa_multip_info_new();
if (pinfo == NULL)
goto err;
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
}
}
if (BN_copy(rsa->e, e_value) == NULL)
goto err;
/* generate p, q and other primes (if any) */
for (i = 0; i < primes; i++) {
adj = 0;
retries = 0;
if (i == 0) {
prime = rsa->p;
} else if (i == 1) {
prime = rsa->q;
} else {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
prime = pinfo->r;
}
BN_set_flags(prime, BN_FLG_CONSTTIME);
for (;;) {
redo:
if (!BN_generate_prime_ex(prime, bitsr[i] + adj, 0, NULL, NULL, cb))
goto err;
/*
* prime should not be equal to p, q, r_3...
* (those primes prior to this one)
*/
{
int j;
for (j = 0; j < i; j++) {
BIGNUM *prev_prime;
if (j == 0)
prev_prime = rsa->p;
else if (j == 1)
prev_prime = rsa->q;
else
prev_prime = sk_RSA_PRIME_INFO_value(prime_infos,
j - 2)->r;
if (!BN_cmp(prime, prev_prime)) {
goto redo;
}
}
}
if (!BN_sub(r2, prime, BN_value_one()))
goto err;
ERR_set_mark();
BN_set_flags(r2, BN_FLG_CONSTTIME);
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;
}
bitse += bitsr[i];
/* calculate n immediately to see if it's sufficient */
if (i == 1) {
/* we get at least 2 primes */
if (!BN_mul(r1, rsa->p, rsa->q, ctx))
goto err;
} else if (i != 0) {
/* modulus n = p * q * r_3 * r_4 ... */
if (!BN_mul(r1, rsa->n, prime, ctx))
goto err;
} else {
/* i == 0, do nothing */
if (!BN_GENCB_call(cb, 3, i))
goto err;
continue;
}
/*
* if |r1|, product of factors so far, is not as long as expected
* (by checking the first 4 bits are less than 0x9 or greater than
* 0xF). If so, re-generate the last prime.
*
* NOTE: This actually can't happen in two-prime case, because of
* the way factors are generated.
*
* Besides, another consideration is, for multi-prime case, even the
* length modulus is as long as expected, the modulus could start at
* 0x8, which could be utilized to distinguish a multi-prime private
* key by using the modulus in a certificate. This is also covered
* by checking the length should not be less than 0x9.
*/
if (!BN_rshift(r2, r1, bitse - 4))
goto err;
bitst = BN_get_word(r2);
if (bitst < 0x9 || bitst > 0xF) {
/*
* For keys with more than 4 primes, we attempt longer factor to
* meet length requirement.
*
* Otherwise, we just re-generate the prime with the same length.
*
* This strategy has the following goals:
*
* 1. 1024-bit factors are effcient when using 3072 and 4096-bit key
* 2. stay the same logic with normal 2-prime key
*/
bitse -= bitsr[i];
if (!BN_GENCB_call(cb, 2, n++))
goto err;
if (primes > 4) {
if (bitst < 0x9)
adj++;
else
adj--;
} else if (retries == 4) {
/*
* re-generate all primes from scratch, mainly used
* in 4 prime case to avoid long loop. Max retry times
* is set to 4.
*/
i = -1;
bitse = 0;
continue;
}
retries++;
goto redo;
}
/* save product of primes for further use, for multi-prime only */
if (i > 1 && BN_copy(pinfo->pp, rsa->n) == NULL)
goto err;
if (BN_copy(rsa->n, r1) == NULL)
goto err;
if (!BN_GENCB_call(cb, 3, i))
goto err;
}
if (BN_cmp(rsa->p, rsa->q) < 0) {
tmp = rsa->p;
rsa->p = rsa->q;
rsa->q = tmp;
}
/* calculate d */
/* p - 1 */
if (!BN_sub(r1, rsa->p, BN_value_one()))
goto err;
/* q - 1 */
if (!BN_sub(r2, rsa->q, BN_value_one()))
goto err;
/* (p - 1)(q - 1) */
if (!BN_mul(r0, r1, r2, ctx))
goto err;
/* multi-prime */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
/* save r_i - 1 to pinfo->d temporarily */
if (!BN_sub(pinfo->d, pinfo->r, BN_value_one()))
goto err;
if (!BN_mul(r0, r0, pinfo->d, ctx))
goto err;
}
{
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);
/* calculate d mod (p-1) and d mod (q - 1) */
if (!BN_mod(rsa->dmp1, d, r1, ctx)
|| !BN_mod(rsa->dmq1, d, r2, ctx)) {
BN_free(d);
goto err;
}
/* calculate CRT exponents */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
/* pinfo->d == r_i - 1 */
if (!BN_mod(pinfo->d, d, pinfo->d, 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;
}
/* calculate CRT coefficient for other primes */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
BN_with_flags(p, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_mod_inverse(pinfo->t, pinfo->pp, 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;
}

View file

@ -0,0 +1,479 @@
/*
* 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
*/
#include <stdio.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include "internal/bn_int.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include "internal/evp_int.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_DOWN_REF(&r->references, &i, r->lock);
REF_PRINT_COUNT("RSA", r);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
if (r->meth != NULL && r->meth->finish != NULL)
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_free(r->n);
BN_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);
RSA_PSS_PARAMS_free(r->pss);
sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free);
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_UP_REF(&r->references, &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)
{
int bits = BN_num_bits(rsa->n);
if (rsa->version == RSA_ASN1_VERSION_MULTI) {
/* This ought to mean that we have private key at hand. */
int ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos);
if (ex_primes <= 0 || (ex_primes + 2) > rsa_multip_cap(bits))
return 0;
}
return BN_security_bits(bits, -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_clear_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_clear_free(r->p);
r->p = p;
}
if (q != NULL) {
BN_clear_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_clear_free(r->dmp1);
r->dmp1 = dmp1;
}
if (dmq1 != NULL) {
BN_clear_free(r->dmq1);
r->dmq1 = dmq1;
}
if (iqmp != NULL) {
BN_clear_free(r->iqmp);
r->iqmp = iqmp;
}
return 1;
}
/*
* Is it better to export RSA_PRIME_INFO structure
* and related functions to let user pass a triplet?
*/
int RSA_set0_multi_prime_params(RSA *r, BIGNUM *primes[], BIGNUM *exps[],
BIGNUM *coeffs[], int pnum)
{
STACK_OF(RSA_PRIME_INFO) *prime_infos, *old = NULL;
RSA_PRIME_INFO *pinfo;
int i;
if (primes == NULL || exps == NULL || coeffs == NULL || pnum == 0)
return 0;
prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, pnum);
if (prime_infos == NULL)
return 0;
if (r->prime_infos != NULL)
old = r->prime_infos;
for (i = 0; i < pnum; i++) {
pinfo = rsa_multip_info_new();
if (pinfo == NULL)
goto err;
if (primes[i] != NULL && exps[i] != NULL && coeffs[i] != NULL) {
BN_free(pinfo->r);
BN_free(pinfo->d);
BN_free(pinfo->t);
pinfo->r = primes[i];
pinfo->d = exps[i];
pinfo->t = coeffs[i];
} else {
rsa_multip_info_free(pinfo);
goto err;
}
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
}
r->prime_infos = prime_infos;
if (!rsa_multip_calc_product(r)) {
r->prime_infos = old;
goto err;
}
if (old != NULL) {
/*
* This is hard to deal with, since the old infos could
* also be set by this function and r, d, t should not
* be freed in that case. So currently, stay consistent
* with other *set0* functions: just free it...
*/
sk_RSA_PRIME_INFO_pop_free(old, rsa_multip_info_free);
}
r->version = RSA_ASN1_VERSION_MULTI;
return 1;
err:
/* r, d, t should not be freed */
sk_RSA_PRIME_INFO_pop_free(prime_infos, rsa_multip_info_free_ex);
return 0;
}
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;
}
int RSA_get_multi_prime_extra_count(const RSA *r)
{
int pnum;
pnum = sk_RSA_PRIME_INFO_num(r->prime_infos);
if (pnum <= 0)
pnum = 0;
return pnum;
}
int RSA_get0_multi_prime_factors(const RSA *r, const BIGNUM *primes[])
{
int pnum, i;
RSA_PRIME_INFO *pinfo;
if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0)
return 0;
/*
* return other primes
* it's caller's responsibility to allocate oth_primes[pnum]
*/
for (i = 0; i < pnum; i++) {
pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
primes[i] = pinfo->r;
}
return 1;
}
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;
}
int RSA_get0_multi_prime_crt_params(const RSA *r, const BIGNUM *exps[],
const BIGNUM *coeffs[])
{
int pnum;
if ((pnum = RSA_get_multi_prime_extra_count(r)) == 0)
return 0;
/* return other primes */
if (exps != NULL || coeffs != NULL) {
RSA_PRIME_INFO *pinfo;
int i;
/* it's the user's job to guarantee the buffer length */
for (i = 0; i < pnum; i++) {
pinfo = sk_RSA_PRIME_INFO_value(r->prime_infos, i);
if (exps != NULL)
exps[i] = pinfo->d;
if (coeffs != NULL)
coeffs[i] = pinfo->t;
}
}
return 1;
}
const BIGNUM *RSA_get0_n(const RSA *r)
{
return r->n;
}
const BIGNUM *RSA_get0_e(const RSA *r)
{
return r->e;
}
const BIGNUM *RSA_get0_d(const RSA *r)
{
return r->d;
}
const BIGNUM *RSA_get0_p(const RSA *r)
{
return r->p;
}
const BIGNUM *RSA_get0_q(const RSA *r)
{
return r->q;
}
const BIGNUM *RSA_get0_dmp1(const RSA *r)
{
return r->dmp1;
}
const BIGNUM *RSA_get0_dmq1(const RSA *r)
{
return r->dmq1;
}
const BIGNUM *RSA_get0_iqmp(const RSA *r)
{
return 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;
}
int RSA_get_version(RSA *r)
{
/* { two-prime(0), multi(1) } */
return r->version;
}
ENGINE *RSA_get0_engine(const RSA *r)
{
return r->engine;
}
int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
{
/* If key type not RSA or RSA-PSS return error */
if (ctx != NULL && ctx->pmeth != NULL
&& ctx->pmeth->pkey_id != EVP_PKEY_RSA
&& ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
return -1;
return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
}

View file

@ -0,0 +1,132 @@
/*
* Copyright 2006-2017 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>
#include "internal/refcount.h"
#define RSA_MAX_PRIME_NUM 5
#define RSA_MIN_MODULUS_BITS 512
typedef struct rsa_prime_info_st {
BIGNUM *r;
BIGNUM *d;
BIGNUM *t;
/* save product of primes prior to this one */
BIGNUM *pp;
BN_MONT_CTX *m;
} RSA_PRIME_INFO;
DECLARE_ASN1_ITEM(RSA_PRIME_INFO)
DEFINE_STACK_OF(RSA_PRIME_INFO)
struct rsa_st {
/*
* The first parameter is used to pickup errors where this is passed
* instead of an EVP_PKEY, it is set to 0
*/
int pad;
int32_t 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;
/* for multi-prime RSA, defined in RFC 8017 */
STACK_OF(RSA_PRIME_INFO) *prime_infos;
/* If a PSS only key this contains the parameter restrictions */
RSA_PSS_PARAMS *pss;
/* be careful using this if the RSA structure is shared */
CRYPTO_EX_DATA ex_data;
CRYPTO_REF_COUNT 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);
int (*rsa_multi_prime_keygen) (RSA *rsa, int bits, int primes,
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);
/* Macros to test if a pkey or ctx is for a PSS key */
#define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
#define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
const EVP_MD *mgf1md, int saltlen);
int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
const EVP_MD **pmgf1md, int *psaltlen);
/* internal function to clear and free multi-prime parameters */
void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo);
void rsa_multip_info_free(RSA_PRIME_INFO *pinfo);
RSA_PRIME_INFO *rsa_multip_info_new(void);
int rsa_multip_calc_product(RSA *rsa);
int rsa_multip_cap(int bits);

View file

@ -0,0 +1,287 @@
/*
* Copyright 2016-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 <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(const 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;
}
int (*RSA_meth_get_multi_prime_keygen(const RSA_METHOD *meth))
(RSA *rsa, int bits, int primes, BIGNUM *e, BN_GENCB *cb)
{
return meth->rsa_multi_prime_keygen;
}
int RSA_meth_set_multi_prime_keygen(RSA_METHOD *meth,
int (*keygen) (RSA *rsa, int bits,
int primes, BIGNUM *e,
BN_GENCB *cb))
{
meth->rsa_multi_prime_keygen = keygen;
return 1;
}

View file

@ -0,0 +1,115 @@
/*
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 BaishanCloud. 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"
void rsa_multip_info_free_ex(RSA_PRIME_INFO *pinfo)
{
/* free pp and pinfo only */
BN_clear_free(pinfo->pp);
OPENSSL_free(pinfo);
}
void rsa_multip_info_free(RSA_PRIME_INFO *pinfo)
{
/* free a RSA_PRIME_INFO structure */
BN_clear_free(pinfo->r);
BN_clear_free(pinfo->d);
BN_clear_free(pinfo->t);
rsa_multip_info_free_ex(pinfo);
}
RSA_PRIME_INFO *rsa_multip_info_new(void)
{
RSA_PRIME_INFO *pinfo;
/* create a RSA_PRIME_INFO structure */
if ((pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO))) == NULL) {
RSAerr(RSA_F_RSA_MULTIP_INFO_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
if ((pinfo->r = BN_secure_new()) == NULL)
goto err;
if ((pinfo->d = BN_secure_new()) == NULL)
goto err;
if ((pinfo->t = BN_secure_new()) == NULL)
goto err;
if ((pinfo->pp = BN_secure_new()) == NULL)
goto err;
return pinfo;
err:
BN_free(pinfo->r);
BN_free(pinfo->d);
BN_free(pinfo->t);
BN_free(pinfo->pp);
OPENSSL_free(pinfo);
return NULL;
}
/* Refill products of primes */
int rsa_multip_calc_product(RSA *rsa)
{
RSA_PRIME_INFO *pinfo;
BIGNUM *p1 = NULL, *p2 = NULL;
BN_CTX *ctx = NULL;
int i, rv = 0, ex_primes;
if ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0) {
/* invalid */
goto err;
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
/* calculate pinfo->pp = p * q for first 'extra' prime */
p1 = rsa->p;
p2 = rsa->q;
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
if (pinfo->pp == NULL) {
pinfo->pp = BN_secure_new();
if (pinfo->pp == NULL)
goto err;
}
if (!BN_mul(pinfo->pp, p1, p2, ctx))
goto err;
/* save previous one */
p1 = pinfo->pp;
p2 = pinfo->r;
}
rv = 1;
err:
BN_CTX_free(ctx);
return rv;
}
int rsa_multip_cap(int bits)
{
int cap = 5;
if (bits < 1024)
cap = 2;
else if (bits < 4096)
cap = 3;
else if (bits < 8192)
cap = 4;
if (cap > RSA_MAX_PRIME_NUM)
cap = RSA_MAX_PRIME_NUM;
return cap;
}

View file

@ -0,0 +1,43 @@
/*
* Copyright 1995-2017 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;
}

View file

@ -0,0 +1,313 @@
/*
* Copyright 1999-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
*/
/* 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 rv = 0;
int i, emlen = tlen - 1;
unsigned char *db, *seed;
unsigned char *dbmask = NULL;
unsigned char seedmask[EVP_MAX_MD_SIZE];
int mdlen, dbmask_len = 0;
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))
goto err;
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)
goto err;
dbmask_len = emlen - mdlen;
dbmask = OPENSSL_malloc(dbmask_len);
if (dbmask == NULL) {
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0)
goto err;
for (i = 0; i < dbmask_len; i++)
db[i] ^= dbmask[i];
if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0)
goto err;
for (i = 0; i < mdlen; i++)
seed[i] ^= seedmask[i];
rv = 1;
err:
OPENSSL_cleanse(seedmask, sizeof(seedmask));
OPENSSL_clear_free(dbmask, dbmask_len);
return rv;
}
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 = 0, found_one_byte, mask;
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) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
RSA_R_OAEP_DECODING_ERROR);
return -1;
}
dblen = num - mdlen - 1;
db = OPENSSL_malloc(dblen);
if (db == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
goto cleanup;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
ERR_R_MALLOC_FAILURE);
goto cleanup;
}
/*
* Caller is encouraged to pass zero-padded message created with
* BN_bn2binpad. Trouble is that since we can't read out of |from|'s
* bounds, it's impossible to have an invariant memory access pattern
* in case |from| was not zero-padded in advance.
*/
for (from += flen, em += num, i = 0; i < num; i++) {
mask = ~constant_time_is_zero(flen);
flen -= 1 & mask;
from -= 1 & mask;
*--em = *from & mask;
}
from = em;
/*
* 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(from[0]);
maskedseed = from + 1;
maskeddb = from + 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.
*/
msg_index = one_index + 1;
mlen = dblen - msg_index;
/*
* For good measure, do this check in constant tine as well.
*/
good &= constant_time_ge(tlen, mlen);
/*
* Even though we can't fake result's length, we can pretend copying
* |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |dblen|
* bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
* where |mlen'| is "saturated" |mlen| value. Deducing information
* about failure or |mlen| would take attacker's ability to observe
* memory access pattern with byte granularity *as it occurs*. It
* should be noted that failure is indistinguishable from normal
* operation if |tlen| is fixed by protocol.
*/
tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen);
msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
mlen = dblen - msg_index;
for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) {
unsigned int equals = constant_time_eq(i, mlen);
from -= dblen & equals; /* if (i == dblen) rewind */
mask &= mask ^ equals; /* if (i == dblen) mask = 0 */
to[i] = constant_time_select_8(mask, from[i], to[i]);
}
/*
* 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);
err_clear_last_constant_time(1 & good);
cleanup:
OPENSSL_cleanse(seed, sizeof(seed));
OPENSSL_clear_free(db, dblen);
OPENSSL_clear_free(em, num);
return constant_time_select_int(good, mlen, -1);
}
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:
OPENSSL_cleanse(md, sizeof(md));
EVP_MD_CTX_free(c);
return rv;
}

View file

@ -0,0 +1,970 @@
/*
* 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
*/
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "rsa_locl.h"
#include "internal/constant_time_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 */
NULL /* rsa_multi_prime_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;
}
const RSA_METHOD *RSA_null_method(void)
{
return NULL;
}
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int i, 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 (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;
/*
* BN_bn2binpad puts in leading 0 bytes if the number is less than
* the length of the modulus.
*/
r = BN_bn2binpad(ret, to, 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, 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 (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_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
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->version == RSA_ASN1_VERSION_MULTI) ||
((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->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) {
if (!BN_sub(f, rsa->n, ret))
goto err;
if (BN_cmp(ret, f) > 0)
res = f;
else
res = ret;
} else {
res = ret;
}
/*
* BN_bn2binpad puts in leading 0 bytes if the number is less than
* the length of the modulus.
*/
r = BN_bn2binpad(res, to, 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 *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 (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->version == RSA_ASN1_VERSION_MULTI) ||
((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;
j = BN_bn2binpad(ret, buf, num);
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:
memcpy(to, buf, (r = j));
break;
default:
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
err_clear_last_constant_time(r >= 0);
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 *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 (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;
i = BN_bn2binpad(ret, buf, num);
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:
memcpy(to, buf, (r = i));
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, *r2, *m[RSA_MAX_PRIME_NUM - 2];
int ret = 0, i, ex_primes = 0, smooth = 0;
RSA_PRIME_INFO *pinfo;
BN_CTX_start(ctx);
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
if (vrfy == NULL)
goto err;
if (rsa->version == RSA_ASN1_VERSION_MULTI
&& ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0
|| ex_primes > RSA_MAX_PRIME_NUM - 2))
goto err;
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
BIGNUM *factor = BN_new();
if (factor == NULL)
goto err;
/*
* Make sure BN_mod_inverse in Montgomery initialization uses the
* BN_FLG_CONSTTIME flag
*/
if (!(BN_with_flags(factor, rsa->p, BN_FLG_CONSTTIME),
BN_MONT_CTX_set_locked(&rsa->_method_mod_p, rsa->lock,
factor, ctx))
|| !(BN_with_flags(factor, rsa->q, BN_FLG_CONSTTIME),
BN_MONT_CTX_set_locked(&rsa->_method_mod_q, rsa->lock,
factor, ctx))) {
BN_free(factor);
goto err;
}
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, factor, ctx)) {
BN_free(factor);
goto err;
}
}
/*
* We MUST free |factor| before any further use of the prime factors
*/
BN_free(factor);
smooth = (ex_primes == 0)
&& (rsa->meth->bn_mod_exp == BN_mod_exp_mont)
&& (BN_num_bits(rsa->q) == BN_num_bits(rsa->p));
}
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 (smooth) {
/*
* Conversion from Montgomery domain, a.k.a. Montgomery reduction,
* accepts values in [0-m*2^w) range. w is m's bit width rounded up
* to limb width. So that at the very least if |I| is fully reduced,
* i.e. less than p*q, we can count on from-to round to perform
* below modulo operations on |I|. Unlike BN_mod it's constant time.
*/
if (/* m1 = I moq q */
!bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx)
|| !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx)
/* m1 = m1^dmq1 mod q */
|| !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx,
rsa->_method_mod_q)
/* r1 = I mod p */
|| !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx)
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
/* r1 = r1^dmp1 mod p */
|| !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx,
rsa->_method_mod_p)
/* r1 = (r1 - m1) mod p */
/*
* bn_mod_sub_fixed_top is not regular modular subtraction,
* it can tolerate subtrahend to be larger than modulus, but
* not bit-wise wider. This makes up for uncommon q>p case,
* when |m1| can be larger than |rsa->p|.
*/
|| !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p)
/* r1 = r1 * iqmp mod p */
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
|| !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p,
ctx)
/* r0 = r1 * q + m1 */
|| !bn_mul_fixed_top(r0, r1, rsa->q, ctx)
|| !bn_mod_add_fixed_top(r0, r0, m1, rsa->n))
goto err;
goto tail;
}
/* 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);
}
/*
* calculate m_i in multi-prime case
*
* TODO:
* 1. squash the following two loops and calculate |m_i| there.
* 2. remove cc and reuse |c|.
* 3. remove |dmq1| and |dmp1| in previous block and use |di|.
*
* If these things are done, the code will be more readable.
*/
if (ex_primes > 0) {
BIGNUM *di = BN_new(), *cc = BN_new();
if (cc == NULL || di == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
for (i = 0; i < ex_primes; i++) {
/* prepare m_i */
if ((m[i] = BN_CTX_get(ctx)) == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
/* prepare c and d_i */
BN_with_flags(cc, I, BN_FLG_CONSTTIME);
BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME);
if (!BN_mod(r1, cc, pinfo->r, ctx)) {
BN_free(cc);
BN_free(di);
goto err;
}
/* compute r1 ^ d_i mod r_i */
if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) {
BN_free(cc);
BN_free(di);
goto err;
}
}
BN_free(cc);
BN_free(di);
}
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;
/* add m_i to m in multi-prime case */
if (ex_primes > 0) {
BIGNUM *pr2 = BN_new();
if (pr2 == NULL)
goto err;
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
if (!BN_sub(r1, m[i], r0)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r2, r1, pinfo->t, ctx)) {
BN_free(pr2);
goto err;
}
BN_with_flags(pr2, r2, BN_FLG_CONSTTIME);
if (!BN_mod(r1, pr2, pinfo->r, ctx)) {
BN_free(pr2);
goto err;
}
if (BN_is_negative(r1))
if (!BN_add(r1, r1, pinfo->r)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r1, r1, pinfo->pp, ctx)) {
BN_free(pr2);
goto err;
}
if (!BN_add(r0, r0, r1)) {
BN_free(pr2);
goto err;
}
}
BN_free(pr2);
}
tail:
if (rsa->e && rsa->n) {
if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) {
if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
} else {
bn_correct_top(r0);
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_is_zero(vrfy)) {
bn_correct_top(r0);
ret = 1;
goto err; /* not actually error */
}
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);
}
}
/*
* It's unfortunate that we have to bn_correct_top(r0). What hopefully
* saves the day is that correction is highly unlike, and private key
* operations are customarily performed on blinded message. Which means
* that attacker won't observe correlation with chosen plaintext.
* Secondly, remaining code would still handle it in same computational
* time and even conceal memory access pattern around corrected top.
*/
bn_correct_top(r0);
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)
{
int i;
RSA_PRIME_INFO *pinfo;
BN_MONT_CTX_free(rsa->_method_mod_n);
BN_MONT_CTX_free(rsa->_method_mod_p);
BN_MONT_CTX_free(rsa->_method_mod_q);
for (i = 0; i < sk_RSA_PRIME_INFO_num(rsa->prime_infos); i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_MONT_CTX_free(pinfo->m);
}
return 1;
}

View file

@ -0,0 +1,255 @@
/*
* 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
*/
#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, mask;
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 || num < 11) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,
RSA_R_PKCS_DECODING_ERROR);
return -1;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
return -1;
}
/*
* Caller is encouraged to pass zero-padded message created with
* BN_bn2binpad. Trouble is that since we can't read out of |from|'s
* bounds, it's impossible to have an invariant memory access pattern
* in case |from| was not zero-padded in advance.
*/
for (from += flen, em += num, i = 0; i < num; i++) {
mask = ~constant_time_is_zero(flen);
flen -= 1 & mask;
from -= 1 & mask;
*--em = *from & mask;
}
from = em;
good = constant_time_is_zero(from[0]);
good &= constant_time_eq(from[1], 2);
/* scan over padding data */
found_zero_byte = 0;
for (i = 2; i < num; i++) {
unsigned int equals0 = constant_time_is_zero(from[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 |from|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
good &= constant_time_ge(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.
*/
good &= constant_time_ge(tlen, mlen);
/*
* Even though we can't fake result's length, we can pretend copying
* |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
* bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
* where |mlen'| is "saturated" |mlen| value. Deducing information
* about failure or |mlen| would take attacker's ability to observe
* memory access pattern with byte granularity *as it occurs*. It
* should be noted that failure is indistinguishable from normal
* operation if |tlen| is fixed by protocol.
*/
tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
msg_index = constant_time_select_int(good, msg_index, num - tlen);
mlen = num - msg_index;
for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
unsigned int equals = constant_time_eq(i, mlen);
from -= tlen & equals; /* if (i == mlen) rewind */
mask &= mask ^ equals; /* if (i == mlen) mask = 0 */
to[i] = constant_time_select_8(mask, from[i], to[i]);
}
OPENSSL_clear_free(em, num);
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, RSA_R_PKCS_DECODING_ERROR);
err_clear_last_constant_time(1 & good);
return constant_time_select_int(good, mlen, -1);
}

View file

@ -0,0 +1,860 @@
/*
* 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/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;
int primes;
/* 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;
/* Minimum salt length or -1 if no PSS parameter restriction */
int min_saltlen;
/* Temp buffer */
unsigned char *tbuf;
/* OAEP label */
unsigned char *oaep_label;
size_t oaep_labellen;
} RSA_PKEY_CTX;
/* True if PSS parameters are restricted */
#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1)
static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
{
RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
if (rctx == NULL)
return 0;
rctx->nbits = 1024;
rctx->primes = RSA_DEFAULT_PRIME_NUM;
if (pkey_ctx_is_pss(ctx))
rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
else
rctx->pad_mode = RSA_PKCS1_PADDING;
/* Maximum for sign, auto for verify */
rctx->saltlen = RSA_PSS_SALTLEN_AUTO;
rctx->min_saltlen = -1;
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 != NULL)
return 1;
if ((ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey))) == NULL) {
RSAerr(RSA_F_SETUP_TBUF, ERR_R_MALLOC_FAILURE);
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:
case NID_sha3_224:
case NID_sha3_256:
case NID_sha3_384:
case NID_sha3_512:
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();
} else if (pkey_ctx_is_pss(ctx)) {
goto bad_pad;
}
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 < RSA_PSS_SALTLEN_MAX)
return -2;
if (rsa_pss_restricted(rctx)) {
if (p1 == RSA_PSS_SALTLEN_AUTO
&& ctx->operation == EVP_PKEY_OP_VERIFY) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
return -2;
}
if ((p1 == RSA_PSS_SALTLEN_DIGEST
&& rctx->min_saltlen > EVP_MD_size(rctx->md))
|| (p1 >= 0 && p1 < rctx->min_saltlen)) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_PSS_SALTLEN_TOO_SMALL);
return 0;
}
}
rctx->saltlen = p1;
}
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
if (p1 < RSA_MIN_MODULUS_BITS) {
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_KEYGEN_PRIMES:
if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_PRIME_NUM_INVALID);
return -2;
}
rctx->primes = p1;
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;
if (rsa_pss_restricted(rctx)) {
if (EVP_MD_type(rctx->md) == EVP_MD_type(p2))
return 1;
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_DIGEST_NOT_ALLOWED);
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 {
if (rsa_pss_restricted(rctx)) {
if (EVP_MD_type(rctx->mgf1md) == EVP_MD_type(p2))
return 1;
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
return 0;
}
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_SIGN:
#ifndef OPENSSL_NO_CMS
case EVP_PKEY_CTRL_CMS_SIGN:
#endif
return 1;
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
#ifndef OPENSSL_NO_CMS
case EVP_PKEY_CTRL_CMS_DECRYPT:
case EVP_PKEY_CTRL_CMS_ENCRYPT:
#endif
if (!pkey_ctx_is_pss(ctx))
return 1;
/* fall through */
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 == NULL) {
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;
if (!strcmp(value, "digest"))
saltlen = RSA_PSS_SALTLEN_DIGEST;
else if (!strcmp(value, "max"))
saltlen = RSA_PSS_SALTLEN_MAX;
else if (!strcmp(value, "auto"))
saltlen = RSA_PSS_SALTLEN_AUTO;
else
saltlen = atoi(value);
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
}
if (strcmp(type, "rsa_keygen_bits") == 0) {
int 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_keygen_primes") == 0) {
int nprimes = atoi(value);
return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes);
}
if (strcmp(type, "rsa_mgf1_md") == 0)
return EVP_PKEY_CTX_md(ctx,
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_MGF1_MD, value);
if (pkey_ctx_is_pss(ctx)) {
if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_RSA_MGF1_MD, value);
if (strcmp(type, "rsa_pss_keygen_md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_MD, value);
if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
int saltlen = atoi(value);
return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen);
}
}
if (strcmp(type, "rsa_oaep_md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_OAEP_MD, value);
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;
}
/* Set PSS parameters when generating a key, if necessary */
static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
{
RSA_PKEY_CTX *rctx = ctx->data;
if (!pkey_ctx_is_pss(ctx))
return 1;
/* If all parameters are default values don't set pss */
if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2)
return 1;
rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md,
rctx->saltlen == -2 ? 0 : rctx->saltlen);
if (rsa->pss == NULL)
return 0;
return 1;
}
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_multi_prime_key(rsa, rctx->nbits, rctx->primes,
rctx->pub_exp, pcb);
BN_GENCB_free(pcb);
if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
RSA_free(rsa);
return 0;
}
if (ret > 0)
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, 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
};
/*
* Called for PSS sign or verify initialisation: checks PSS parameter
* sanity and sets any restrictions on key usage.
*/
static int pkey_pss_init(EVP_PKEY_CTX *ctx)
{
RSA *rsa;
RSA_PKEY_CTX *rctx = ctx->data;
const EVP_MD *md;
const EVP_MD *mgf1md;
int min_saltlen, max_saltlen;
/* Should never happen */
if (!pkey_ctx_is_pss(ctx))
return 0;
rsa = ctx->pkey->pkey.rsa;
/* If no restrictions just return */
if (rsa->pss == NULL)
return 1;
/* Get and check parameters */
if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
return 0;
/* See if minimum salt length exceeds maximum possible */
max_saltlen = RSA_size(rsa) - EVP_MD_size(md);
if ((RSA_bits(rsa) & 0x7) == 1)
max_saltlen--;
if (min_saltlen > max_saltlen) {
RSAerr(RSA_F_PKEY_PSS_INIT, RSA_R_INVALID_SALT_LENGTH);
return 0;
}
rctx->min_saltlen = min_saltlen;
/*
* Set PSS restrictions as defaults: we can then block any attempt to
* use invalid values in pkey_rsa_ctrl
*/
rctx->md = md;
rctx->mgf1md = mgf1md;
rctx->saltlen = min_saltlen;
return 1;
}
const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
EVP_PKEY_RSA_PSS,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_rsa_init,
pkey_rsa_copy,
pkey_rsa_cleanup,
0, 0,
0,
pkey_rsa_keygen,
pkey_pss_init,
pkey_rsa_sign,
pkey_pss_init,
pkey_rsa_verify,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_rsa_ctrl,
pkey_rsa_ctrl_str
};

View file

@ -0,0 +1,42 @@
/*
* Copyright 2006-2017 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;
}

View file

@ -0,0 +1,255 @@
/*
* Copyright 2005-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/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
* -3 salt length is maximized
* -N reserved
*/
if (sLen == RSA_PSS_SALTLEN_DIGEST) {
sLen = hLen;
} else if (sLen < RSA_PSS_SALTLEN_MAX) {
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 == RSA_PSS_SALTLEN_MAX) {
sLen = emLen - hLen - 2;
} else 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 != RSA_PSS_SALTLEN_AUTO && (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
* -3 same as above (on signing)
* -N reserved
*/
if (sLen == RSA_PSS_SALTLEN_DIGEST) {
sLen = hLen;
} else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) {
sLen = RSA_PSS_SALTLEN_MAX;
} else if (sLen < RSA_PSS_SALTLEN_MAX) {
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 == RSA_PSS_SALTLEN_MAX) {
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_clear_free(salt, (size_t)sLen); /* salt != NULL implies sLen > 0 */
return ret;
}
#if defined(_MSC_VER)
# pragma optimize("",on)
#endif

View file

@ -0,0 +1,95 @@
/*
* Copyright 1995-2017 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;
}

View file

@ -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 = &parameter;
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);
}

View file

@ -0,0 +1,167 @@
/*
* 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
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include "internal/constant_time_locl.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;
}
/*
* Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding
* if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also
* preserves error code reporting for backward compatibility.
*/
int RSA_padding_check_SSLv23(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, mask, threes_in_row;
int zero_index = 0, msg_index, mlen = -1, err;
if (flen < 10) {
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
return -1;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, ERR_R_MALLOC_FAILURE);
return -1;
}
/*
* Caller is encouraged to pass zero-padded message created with
* BN_bn2binpad. Trouble is that since we can't read out of |from|'s
* bounds, it's impossible to have an invariant memory access pattern
* in case |from| was not zero-padded in advance.
*/
for (from += flen, em += num, i = 0; i < num; i++) {
mask = ~constant_time_is_zero(flen);
flen -= 1 & mask;
from -= 1 & mask;
*--em = *from & mask;
}
from = em;
good = constant_time_is_zero(from[0]);
good &= constant_time_eq(from[1], 2);
err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02);
mask = ~good;
/* scan over padding data */
found_zero_byte = 0;
threes_in_row = 0;
for (i = 2; i < num; i++) {
unsigned int equals0 = constant_time_is_zero(from[i]);
zero_index = constant_time_select_int(~found_zero_byte & equals0,
i, zero_index);
found_zero_byte |= equals0;
threes_in_row += 1 & ~found_zero_byte;
threes_in_row &= found_zero_byte | constant_time_eq(from[i], 3);
}
/*
* PS must be at least 8 bytes long, and it starts two bytes into |from|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
good &= constant_time_ge(zero_index, 2 + 8);
err = constant_time_select_int(mask | good, err,
RSA_R_NULL_BEFORE_BLOCK_MISSING);
mask = ~good;
good &= constant_time_lt(threes_in_row, 8);
err = constant_time_select_int(mask | good, err,
RSA_R_SSLV3_ROLLBACK_ATTACK);
mask = ~good;
/*
* 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.
*/
good &= constant_time_ge(tlen, mlen);
err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE);
/*
* Even though we can't fake result's length, we can pretend copying
* |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
* bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
* where |mlen'| is "saturated" |mlen| value. Deducing information
* about failure or |mlen| would take attacker's ability to observe
* memory access pattern with byte granularity *as it occurs*. It
* should be noted that failure is indistinguishable from normal
* operation if |tlen| is fixed by protocol.
*/
tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
msg_index = constant_time_select_int(good, msg_index, num - tlen);
mlen = num - msg_index;
for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
unsigned int equals = constant_time_eq(i, mlen);
from -= tlen & equals; /* if (i == mlen) rewind */
mask &= mask ^ equals; /* if (i == mlen) mask = 0 */
to[i] = constant_time_select_8(mask, from[i], to[i]);
}
OPENSSL_clear_free(em, num);
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, err);
err_clear_last_constant_time(1 & good);
return constant_time_select_int(good, mlen, -1);
}

View file

@ -0,0 +1,117 @@
/*
* Copyright 2005-2017 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;
}

View file

@ -0,0 +1,200 @@
/*
* Copyright 1995-2017 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);
if (rsa->iqmp == NULL)
goto err;
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;
}