check in v3.8.1 source
This commit is contained in:
1143
crypto/rsa/rsa_ameth.c
Normal file
1143
crypto/rsa/rsa_ameth.c
Normal file
File diff suppressed because it is too large
Load Diff
422
crypto/rsa/rsa_asn1.c
Normal file
422
crypto/rsa/rsa_asn1.c
Normal file
@@ -0,0 +1,422 @@
|
||||
/* $OpenBSD: rsa_asn1.c,v 1.17 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2000.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "rsa_local.h"
|
||||
|
||||
/* Override the default free and new methods */
|
||||
static int
|
||||
rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
|
||||
{
|
||||
if (operation == ASN1_OP_NEW_PRE) {
|
||||
*pval = (ASN1_VALUE *)RSA_new();
|
||||
if (*pval)
|
||||
return 2;
|
||||
return 0;
|
||||
} else if (operation == ASN1_OP_FREE_PRE) {
|
||||
RSA_free((RSA *)*pval);
|
||||
*pval = NULL;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const ASN1_AUX RSAPrivateKey_aux = {
|
||||
.app_data = NULL,
|
||||
.flags = 0,
|
||||
.ref_offset = 0,
|
||||
.ref_lock = 0,
|
||||
.asn1_cb = rsa_cb,
|
||||
.enc_offset = 0,
|
||||
};
|
||||
static const ASN1_TEMPLATE RSAPrivateKey_seq_tt[] = {
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, version),
|
||||
.field_name = "version",
|
||||
.item = &LONG_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, n),
|
||||
.field_name = "n",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, e),
|
||||
.field_name = "e",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, d),
|
||||
.field_name = "d",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, p),
|
||||
.field_name = "p",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, q),
|
||||
.field_name = "q",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, dmp1),
|
||||
.field_name = "dmp1",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, dmq1),
|
||||
.field_name = "dmq1",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, iqmp),
|
||||
.field_name = "iqmp",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
};
|
||||
|
||||
const ASN1_ITEM RSAPrivateKey_it = {
|
||||
.itype = ASN1_ITYPE_SEQUENCE,
|
||||
.utype = V_ASN1_SEQUENCE,
|
||||
.templates = RSAPrivateKey_seq_tt,
|
||||
.tcount = sizeof(RSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE),
|
||||
.funcs = &RSAPrivateKey_aux,
|
||||
.size = sizeof(RSA),
|
||||
.sname = "RSA",
|
||||
};
|
||||
|
||||
|
||||
static const ASN1_AUX RSAPublicKey_aux = {
|
||||
.app_data = NULL,
|
||||
.flags = 0,
|
||||
.ref_offset = 0,
|
||||
.ref_lock = 0,
|
||||
.asn1_cb = rsa_cb,
|
||||
.enc_offset = 0,
|
||||
};
|
||||
static const ASN1_TEMPLATE RSAPublicKey_seq_tt[] = {
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, n),
|
||||
.field_name = "n",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA, e),
|
||||
.field_name = "e",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
};
|
||||
|
||||
const ASN1_ITEM RSAPublicKey_it = {
|
||||
.itype = ASN1_ITYPE_SEQUENCE,
|
||||
.utype = V_ASN1_SEQUENCE,
|
||||
.templates = RSAPublicKey_seq_tt,
|
||||
.tcount = sizeof(RSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE),
|
||||
.funcs = &RSAPublicKey_aux,
|
||||
.size = sizeof(RSA),
|
||||
.sname = "RSA",
|
||||
};
|
||||
|
||||
static int
|
||||
rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
|
||||
{
|
||||
/* Free up maskHash */
|
||||
if (operation == ASN1_OP_FREE_PRE) {
|
||||
RSA_PSS_PARAMS *pss = (RSA_PSS_PARAMS *)*pval;
|
||||
X509_ALGOR_free(pss->maskHash);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const ASN1_AUX RSA_PSS_PARAMS_aux = {
|
||||
.app_data = NULL,
|
||||
.flags = 0,
|
||||
.ref_offset = 0,
|
||||
.ref_lock = 0,
|
||||
.asn1_cb = rsa_pss_cb,
|
||||
.enc_offset = 0,
|
||||
};
|
||||
|
||||
static const ASN1_TEMPLATE RSA_PSS_PARAMS_seq_tt[] = {
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA_PSS_PARAMS, hashAlgorithm),
|
||||
.field_name = "hashAlgorithm",
|
||||
.item = &X509_ALGOR_it,
|
||||
},
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 1,
|
||||
.offset = offsetof(RSA_PSS_PARAMS, maskGenAlgorithm),
|
||||
.field_name = "maskGenAlgorithm",
|
||||
.item = &X509_ALGOR_it,
|
||||
},
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 2,
|
||||
.offset = offsetof(RSA_PSS_PARAMS, saltLength),
|
||||
.field_name = "saltLength",
|
||||
.item = &ASN1_INTEGER_it,
|
||||
},
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 3,
|
||||
.offset = offsetof(RSA_PSS_PARAMS, trailerField),
|
||||
.field_name = "trailerField",
|
||||
.item = &ASN1_INTEGER_it,
|
||||
},
|
||||
};
|
||||
|
||||
const ASN1_ITEM RSA_PSS_PARAMS_it = {
|
||||
.itype = ASN1_ITYPE_SEQUENCE,
|
||||
.utype = V_ASN1_SEQUENCE,
|
||||
.templates = RSA_PSS_PARAMS_seq_tt,
|
||||
.tcount = sizeof(RSA_PSS_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
|
||||
.funcs = &RSA_PSS_PARAMS_aux,
|
||||
.size = sizeof(RSA_PSS_PARAMS),
|
||||
.sname = "RSA_PSS_PARAMS",
|
||||
};
|
||||
|
||||
RSA_PSS_PARAMS *
|
||||
d2i_RSA_PSS_PARAMS(RSA_PSS_PARAMS **a, const unsigned char **in, long len)
|
||||
{
|
||||
return (RSA_PSS_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
|
||||
&RSA_PSS_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_RSA_PSS_PARAMS);
|
||||
|
||||
int
|
||||
i2d_RSA_PSS_PARAMS(RSA_PSS_PARAMS *a, unsigned char **out)
|
||||
{
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSA_PSS_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_RSA_PSS_PARAMS);
|
||||
|
||||
RSA_PSS_PARAMS *
|
||||
RSA_PSS_PARAMS_new(void)
|
||||
{
|
||||
return (RSA_PSS_PARAMS *)ASN1_item_new(&RSA_PSS_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_PSS_PARAMS_new);
|
||||
|
||||
void
|
||||
RSA_PSS_PARAMS_free(RSA_PSS_PARAMS *a)
|
||||
{
|
||||
ASN1_item_free((ASN1_VALUE *)a, &RSA_PSS_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_PSS_PARAMS_free);
|
||||
|
||||
static int
|
||||
rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
|
||||
{
|
||||
/* Free up maskHash */
|
||||
if (operation == ASN1_OP_FREE_PRE) {
|
||||
RSA_OAEP_PARAMS *oaep = (RSA_OAEP_PARAMS *)*pval;
|
||||
X509_ALGOR_free(oaep->maskHash);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const ASN1_AUX RSA_OAEP_PARAMS_aux = {
|
||||
.app_data = NULL,
|
||||
.flags = 0,
|
||||
.ref_offset = 0,
|
||||
.ref_lock = 0,
|
||||
.asn1_cb = rsa_oaep_cb,
|
||||
.enc_offset = 0,
|
||||
};
|
||||
|
||||
static const ASN1_TEMPLATE RSA_OAEP_PARAMS_seq_tt[] = {
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 0,
|
||||
.offset = offsetof(RSA_OAEP_PARAMS, hashFunc),
|
||||
.field_name = "hashFunc",
|
||||
.item = &X509_ALGOR_it,
|
||||
},
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 1,
|
||||
.offset = offsetof(RSA_OAEP_PARAMS, maskGenFunc),
|
||||
.field_name = "maskGenFunc",
|
||||
.item = &X509_ALGOR_it,
|
||||
},
|
||||
{
|
||||
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
|
||||
.tag = 2,
|
||||
.offset = offsetof(RSA_OAEP_PARAMS, pSourceFunc),
|
||||
.field_name = "pSourceFunc",
|
||||
.item = &X509_ALGOR_it,
|
||||
},
|
||||
};
|
||||
|
||||
const ASN1_ITEM RSA_OAEP_PARAMS_it = {
|
||||
.itype = ASN1_ITYPE_SEQUENCE,
|
||||
.utype = V_ASN1_SEQUENCE,
|
||||
.templates = RSA_OAEP_PARAMS_seq_tt,
|
||||
.tcount = sizeof(RSA_OAEP_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
|
||||
.funcs = &RSA_OAEP_PARAMS_aux,
|
||||
.size = sizeof(RSA_OAEP_PARAMS),
|
||||
.sname = "RSA_OAEP_PARAMS",
|
||||
};
|
||||
|
||||
|
||||
RSA_OAEP_PARAMS *
|
||||
d2i_RSA_OAEP_PARAMS(RSA_OAEP_PARAMS **a, const unsigned char **in, long len)
|
||||
{
|
||||
return (RSA_OAEP_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
|
||||
&RSA_OAEP_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_RSA_OAEP_PARAMS);
|
||||
|
||||
int
|
||||
i2d_RSA_OAEP_PARAMS(RSA_OAEP_PARAMS *a, unsigned char **out)
|
||||
{
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSA_OAEP_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_RSA_OAEP_PARAMS);
|
||||
|
||||
RSA_OAEP_PARAMS *
|
||||
RSA_OAEP_PARAMS_new(void)
|
||||
{
|
||||
return (RSA_OAEP_PARAMS *)ASN1_item_new(&RSA_OAEP_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_OAEP_PARAMS_new);
|
||||
|
||||
void
|
||||
RSA_OAEP_PARAMS_free(RSA_OAEP_PARAMS *a)
|
||||
{
|
||||
ASN1_item_free((ASN1_VALUE *)a, &RSA_OAEP_PARAMS_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_OAEP_PARAMS_free);
|
||||
|
||||
RSA *
|
||||
d2i_RSAPrivateKey(RSA **a, const unsigned char **in, long len)
|
||||
{
|
||||
return (RSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
|
||||
&RSAPrivateKey_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_RSAPrivateKey);
|
||||
|
||||
int
|
||||
i2d_RSAPrivateKey(const RSA *a, unsigned char **out)
|
||||
{
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSAPrivateKey_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_RSAPrivateKey);
|
||||
|
||||
|
||||
RSA *
|
||||
d2i_RSAPublicKey(RSA **a, const unsigned char **in, long len)
|
||||
{
|
||||
return (RSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
|
||||
&RSAPublicKey_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_RSAPublicKey);
|
||||
|
||||
int
|
||||
i2d_RSAPublicKey(const RSA *a, unsigned char **out)
|
||||
{
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSAPublicKey_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_RSAPublicKey);
|
||||
|
||||
RSA *
|
||||
RSAPublicKey_dup(RSA *rsa)
|
||||
{
|
||||
return ASN1_item_dup(&RSAPublicKey_it, rsa);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSAPublicKey_dup);
|
||||
|
||||
RSA *
|
||||
RSAPrivateKey_dup(RSA *rsa)
|
||||
{
|
||||
return ASN1_item_dup(&RSAPrivateKey_it, rsa);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSAPrivateKey_dup);
|
361
crypto/rsa/rsa_blinding.c
Normal file
361
crypto/rsa/rsa_blinding.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/* $OpenBSD: rsa_blinding.c,v 1.3 2023/08/09 12:09:06 tb Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
#define BN_BLINDING_COUNTER 32
|
||||
|
||||
struct bn_blinding_st {
|
||||
BIGNUM *A;
|
||||
BIGNUM *Ai;
|
||||
BIGNUM *e;
|
||||
BIGNUM *mod;
|
||||
pthread_t tid;
|
||||
int counter;
|
||||
BN_MONT_CTX *m_ctx;
|
||||
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
};
|
||||
|
||||
BN_BLINDING *
|
||||
BN_BLINDING_new(const BIGNUM *e, const BIGNUM *mod, BN_CTX *ctx,
|
||||
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx)
|
||||
{
|
||||
BN_BLINDING *ret = NULL;
|
||||
|
||||
if ((ret = calloc(1, sizeof(BN_BLINDING))) == NULL) {
|
||||
BNerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if ((ret->A = BN_new()) == NULL)
|
||||
goto err;
|
||||
if ((ret->Ai = BN_new()) == NULL)
|
||||
goto err;
|
||||
if ((ret->e = BN_dup(e)) == NULL)
|
||||
goto err;
|
||||
if ((ret->mod = BN_dup(mod)) == NULL)
|
||||
goto err;
|
||||
if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
|
||||
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
|
||||
|
||||
/* Update on first use. */
|
||||
ret->counter = BN_BLINDING_COUNTER - 1;
|
||||
ret->tid = pthread_self();
|
||||
|
||||
if (bn_mod_exp != NULL)
|
||||
ret->bn_mod_exp = bn_mod_exp;
|
||||
if (m_ctx != NULL)
|
||||
ret->m_ctx = m_ctx;
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
BN_BLINDING_free(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
BN_BLINDING_free(BN_BLINDING *r)
|
||||
{
|
||||
if (r == NULL)
|
||||
return;
|
||||
|
||||
BN_free(r->A);
|
||||
BN_free(r->Ai);
|
||||
BN_free(r->e);
|
||||
BN_free(r->mod);
|
||||
free(r);
|
||||
}
|
||||
|
||||
static int
|
||||
BN_BLINDING_setup(BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
if (!bn_rand_interval(b->A, 1, b->mod))
|
||||
return 0;
|
||||
if (BN_mod_inverse_ct(b->Ai, b->A, b->mod, ctx) == NULL)
|
||||
return 0;
|
||||
|
||||
if (b->bn_mod_exp != NULL && b->m_ctx != NULL) {
|
||||
if (!b->bn_mod_exp(b->A, b->A, b->e, b->mod, ctx, b->m_ctx))
|
||||
return 0;
|
||||
} else {
|
||||
if (!BN_mod_exp_ct(b->A, b->A, b->e, b->mod, ctx))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (++b->counter >= BN_BLINDING_COUNTER) {
|
||||
if (!BN_BLINDING_setup(b, ctx))
|
||||
goto err;
|
||||
b->counter = 0;
|
||||
} else {
|
||||
if (!BN_mod_sqr(b->A, b->A, b->mod, ctx))
|
||||
goto err;
|
||||
if (!BN_mod_sqr(b->Ai, b->Ai, b->mod, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
BN_BLINDING_convert(BIGNUM *n, BIGNUM *inv, BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!BN_BLINDING_update(b, ctx))
|
||||
goto err;
|
||||
|
||||
if (inv != NULL) {
|
||||
if (!bn_copy(inv, b->Ai))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = BN_mod_mul(n, n, b->A, b->mod, ctx);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
BN_BLINDING_invert(BIGNUM *n, const BIGNUM *inv, BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
if (inv == NULL)
|
||||
inv = b->Ai;
|
||||
|
||||
return BN_mod_mul(n, n, inv, b->mod, ctx);
|
||||
}
|
||||
|
||||
int
|
||||
BN_BLINDING_is_local(BN_BLINDING *b)
|
||||
{
|
||||
return pthread_equal(pthread_self(), b->tid) != 0;
|
||||
}
|
||||
|
||||
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);
|
||||
if ((r0 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((r1 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((r2 = BN_CTX_get(ctx)) == 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_ct(NULL, d, r0, ctx);
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_BLINDING *
|
||||
RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
|
||||
{
|
||||
BIGNUM *e = NULL;
|
||||
BIGNUM n;
|
||||
BN_CTX *ctx = NULL;
|
||||
BN_BLINDING *ret = NULL;
|
||||
|
||||
if ((ctx = in_ctx) == NULL)
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
if ((e = rsa->e) == NULL)
|
||||
e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
|
||||
if (e == NULL) {
|
||||
RSAerror(RSA_R_NO_PUBLIC_EXPONENT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_init(&n);
|
||||
BN_with_flags(&n, rsa->n, BN_FLG_CONSTTIME);
|
||||
|
||||
if ((ret = BN_BLINDING_new(e, &n, ctx, rsa->meth->bn_mod_exp,
|
||||
rsa->_method_mod_n)) == NULL) {
|
||||
RSAerror(ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (ctx != in_ctx)
|
||||
BN_CTX_free(ctx);
|
||||
if (e != rsa->e)
|
||||
BN_free(e);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
RSA_blinding_off(RSA *rsa)
|
||||
{
|
||||
BN_BLINDING_free(rsa->blinding);
|
||||
rsa->blinding = NULL;
|
||||
rsa->flags |= RSA_FLAG_NO_BLINDING;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_blinding_off);
|
||||
|
||||
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_NO_BLINDING;
|
||||
ret = 1;
|
||||
err:
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_blinding_on);
|
223
crypto/rsa/rsa_chk.c
Normal file
223
crypto/rsa/rsa_chk.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/* $OpenBSD: rsa_chk.c,v 1.18 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
int
|
||||
RSA_check_key(const RSA *key)
|
||||
{
|
||||
BIGNUM *i, *j, *k, *l, *m;
|
||||
BN_CTX *ctx;
|
||||
int r;
|
||||
int ret = 1;
|
||||
|
||||
if (!key->p || !key->q || !key->n || !key->e || !key->d) {
|
||||
RSAerror(RSA_R_VALUE_MISSING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = BN_new();
|
||||
j = BN_new();
|
||||
k = BN_new();
|
||||
l = BN_new();
|
||||
m = BN_new();
|
||||
ctx = BN_CTX_new();
|
||||
if (i == NULL || j == NULL || k == NULL || l == NULL || m == NULL ||
|
||||
ctx == NULL) {
|
||||
ret = -1;
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_is_one(key->e)) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_BAD_E_VALUE);
|
||||
}
|
||||
if (!BN_is_odd(key->e)) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_BAD_E_VALUE);
|
||||
}
|
||||
|
||||
/* p prime? */
|
||||
r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL);
|
||||
if (r != 1) {
|
||||
ret = r;
|
||||
if (r != 0)
|
||||
goto err;
|
||||
RSAerror(RSA_R_P_NOT_PRIME);
|
||||
}
|
||||
|
||||
/* q prime? */
|
||||
r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL);
|
||||
if (r != 1) {
|
||||
ret = r;
|
||||
if (r != 0)
|
||||
goto err;
|
||||
RSAerror(RSA_R_Q_NOT_PRIME);
|
||||
}
|
||||
|
||||
/* n = p*q? */
|
||||
r = BN_mul(i, key->p, key->q, ctx);
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_cmp(i, key->n) != 0) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_N_DOES_NOT_EQUAL_P_Q);
|
||||
}
|
||||
|
||||
/* d*e = 1 mod lcm(p-1,q-1)? */
|
||||
|
||||
r = BN_sub(i, key->p, BN_value_one());
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
r = BN_sub(j, key->q, BN_value_one());
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* now compute k = lcm(i,j) */
|
||||
r = BN_mul(l, i, j, ctx);
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
r = BN_gcd_ct(m, i, j, ctx);
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
r = BN_div_ct(k, NULL, l, m, ctx); /* remainder is 0 */
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = BN_mod_mul(i, key->d, key->e, k, ctx);
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_is_one(i)) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_D_E_NOT_CONGRUENT_TO_1);
|
||||
}
|
||||
|
||||
if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
|
||||
/* dmp1 = d mod (p-1)? */
|
||||
r = BN_sub(i, key->p, BN_value_one());
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = BN_mod_ct(j, key->d, i, ctx);
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_cmp(j, key->dmp1) != 0) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_DMP1_NOT_CONGRUENT_TO_D);
|
||||
}
|
||||
|
||||
/* dmq1 = d mod (q-1)? */
|
||||
r = BN_sub(i, key->q, BN_value_one());
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = BN_mod_ct(j, key->d, i, ctx);
|
||||
if (!r) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_cmp(j, key->dmq1) != 0) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
|
||||
}
|
||||
|
||||
/* iqmp = q^-1 mod p? */
|
||||
if (BN_mod_inverse_ct(i, key->q, key->p, ctx) == NULL) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_cmp(i, key->iqmp) != 0) {
|
||||
ret = 0;
|
||||
RSAerror(RSA_R_IQMP_NOT_INVERSE_OF_Q);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
BN_free(i);
|
||||
BN_free(j);
|
||||
BN_free(k);
|
||||
BN_free(l);
|
||||
BN_free(m);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_check_key);
|
902
crypto/rsa/rsa_eay.c
Normal file
902
crypto/rsa/rsa_eay.c
Normal file
@@ -0,0 +1,902 @@
|
||||
/* $OpenBSD: rsa_eay.c,v 1.65 2023/08/09 12:09:06 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
static int
|
||||
rsa_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||
RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
|
||||
RSAerror(RSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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 = malloc(num);
|
||||
|
||||
if (f == NULL || ret == NULL || buf == NULL) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
|
||||
break;
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
|
||||
break;
|
||||
#endif
|
||||
case RSA_NO_PADDING:
|
||||
i = RSA_padding_add_none(buf, num, from, flen);
|
||||
break;
|
||||
default:
|
||||
RSAerror(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 */
|
||||
RSAerror(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,
|
||||
CRYPTO_LOCK_RSA, rsa->n, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
|
||||
/* put in leading 0 bytes if the number is less than the
|
||||
* length of the modulus */
|
||||
j = BN_num_bytes(ret);
|
||||
i = BN_bn2bin(ret, &(to[num - j]));
|
||||
for (k = 0; k < num - i; k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
freezero(buf, num);
|
||||
return r;
|
||||
}
|
||||
|
||||
static BN_BLINDING *
|
||||
rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
|
||||
{
|
||||
BN_BLINDING *ret;
|
||||
int got_write_lock = 0;
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_RSA);
|
||||
|
||||
if (rsa->blinding == NULL) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
||||
got_write_lock = 1;
|
||||
|
||||
if (rsa->blinding == NULL)
|
||||
rsa->blinding = RSA_setup_blinding(rsa, ctx);
|
||||
}
|
||||
|
||||
if ((ret = rsa->blinding) == NULL)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* We need a shared blinding. Accesses require locks and a copy of the
|
||||
* blinding factor needs to be retained on use.
|
||||
*/
|
||||
if ((*local = BN_BLINDING_is_local(ret)) == 0) {
|
||||
if (rsa->mt_blinding == NULL) {
|
||||
if (!got_write_lock) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
||||
got_write_lock = 1;
|
||||
}
|
||||
|
||||
if (rsa->mt_blinding == NULL)
|
||||
rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
|
||||
}
|
||||
ret = rsa->mt_blinding;
|
||||
}
|
||||
|
||||
err:
|
||||
if (got_write_lock)
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
||||
else
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
|
||||
|
||||
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(f, NULL, b, ctx);
|
||||
else {
|
||||
/*
|
||||
* Shared blinding: store the unblinding factor
|
||||
* outside BN_BLINDING.
|
||||
*/
|
||||
int ret;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
|
||||
ret = BN_BLINDING_convert(f, unblind, b, ctx);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
|
||||
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()
|
||||
* will use the unblinding factor stored in BN_BLINDING.
|
||||
* If BN_BLINDING is shared between threads, unblind must be non-null:
|
||||
* BN_BLINDING_invert() 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(f, unblind, b, ctx);
|
||||
}
|
||||
|
||||
/* signing */
|
||||
static int
|
||||
rsa_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||
RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret, *res;
|
||||
int i, j, k, num = 0, r = -1;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
/*
|
||||
* Used only if the blinding structure is shared. A non-NULL unblind
|
||||
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
|
||||
* the unblinding factor outside the blinding structure.
|
||||
*/
|
||||
BIGNUM *unblind = NULL;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = malloc(num);
|
||||
|
||||
if (f == NULL || ret == NULL || buf == NULL) {
|
||||
RSAerror(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;
|
||||
default:
|
||||
RSAerror(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 */
|
||||
RSAerror(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,
|
||||
CRYPTO_LOCK_RSA, rsa->n, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
|
||||
if (blinding == NULL) {
|
||||
RSAerror(ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding != NULL) {
|
||||
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
(rsa->p != NULL && rsa->q != NULL && rsa->dmp1 != NULL &&
|
||||
rsa->dmq1 != NULL && rsa->iqmp != NULL)) {
|
||||
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
BIGNUM d;
|
||||
|
||||
BN_init(&d);
|
||||
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)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* put in leading 0 bytes if the number is less than the
|
||||
* length of the modulus */
|
||||
j = BN_num_bytes(res);
|
||||
i = BN_bn2bin(res, &(to[num - j]));
|
||||
for (k = 0; k < num - i; k++)
|
||||
to[k] = 0;
|
||||
|
||||
r = num;
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
freezero(buf, num);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||
RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int j, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
int local_blinding = 0;
|
||||
/*
|
||||
* Used only if the blinding structure is shared. A non-NULL unblind
|
||||
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
|
||||
* the unblinding factor outside the blinding structure.
|
||||
*/
|
||||
BIGNUM *unblind = NULL;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
f = BN_CTX_get(ctx);
|
||||
ret = BN_CTX_get(ctx);
|
||||
num = BN_num_bytes(rsa->n);
|
||||
buf = malloc(num);
|
||||
|
||||
if (!f || !ret || !buf) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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,
|
||||
CRYPTO_LOCK_RSA, rsa->n, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
|
||||
if (blinding == NULL) {
|
||||
RSAerror(ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding != NULL) {
|
||||
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* do the decrypt */
|
||||
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
(rsa->p != NULL && rsa->q != NULL && rsa->dmp1 != NULL &&
|
||||
rsa->dmq1 != NULL && rsa->iqmp != NULL)) {
|
||||
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
BIGNUM d;
|
||||
|
||||
BN_init(&d);
|
||||
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)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blinding)
|
||||
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
j = BN_bn2bin(ret, p); /* j is only used with no-padding mode */
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
|
||||
break;
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
|
||||
break;
|
||||
#endif
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, j, num);
|
||||
break;
|
||||
default:
|
||||
RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (r < 0)
|
||||
RSAerror(RSA_R_PADDING_CHECK_FAILED);
|
||||
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
freezero(buf, num);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* signature verification */
|
||||
static int
|
||||
rsa_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
||||
RSA *rsa, int padding)
|
||||
{
|
||||
BIGNUM *f, *ret;
|
||||
int i, num = 0, r = -1;
|
||||
unsigned char *p;
|
||||
unsigned char *buf = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
|
||||
RSAerror(RSA_R_MODULUS_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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 = malloc(num);
|
||||
|
||||
if (!f || !ret || !buf) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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,
|
||||
CRYPTO_LOCK_RSA, 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 && (ret->d[0] & 0xf) != 12)
|
||||
if (!BN_sub(ret, rsa->n, ret))
|
||||
goto err;
|
||||
|
||||
p = buf;
|
||||
i = BN_bn2bin(ret, p);
|
||||
|
||||
switch (padding) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_X931_PADDING:
|
||||
r = RSA_padding_check_X931(to, num, buf, i, num);
|
||||
break;
|
||||
case RSA_NO_PADDING:
|
||||
r = RSA_padding_check_none(to, num, buf, i, num);
|
||||
break;
|
||||
default:
|
||||
RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if (r < 0)
|
||||
RSAerror(RSA_R_PADDING_CHECK_FAILED);
|
||||
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
freezero(buf, num);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *r1, *m1, *vrfy;
|
||||
BIGNUM dmp1, dmq1, c, pr1;
|
||||
int ret = 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
r1 = BN_CTX_get(ctx);
|
||||
m1 = BN_CTX_get(ctx);
|
||||
vrfy = BN_CTX_get(ctx);
|
||||
if (r1 == NULL || m1 == NULL || vrfy == NULL) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
{
|
||||
BIGNUM p, q;
|
||||
|
||||
/*
|
||||
* Make sure BN_mod_inverse in Montgomery initialization uses the
|
||||
* BN_FLG_CONSTTIME flag
|
||||
*/
|
||||
BN_init(&p);
|
||||
BN_init(&q);
|
||||
BN_with_flags(&p, rsa->p, BN_FLG_CONSTTIME);
|
||||
BN_with_flags(&q, rsa->q, BN_FLG_CONSTTIME);
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
|
||||
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p,
|
||||
CRYPTO_LOCK_RSA, &p, ctx) ||
|
||||
!BN_MONT_CTX_set_locked(&rsa->_method_mod_q,
|
||||
CRYPTO_LOCK_RSA, &q, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
|
||||
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n,
|
||||
CRYPTO_LOCK_RSA, rsa->n, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* compute I mod q */
|
||||
BN_init(&c);
|
||||
BN_with_flags(&c, I, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!BN_mod_ct(r1, &c, rsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* compute r1^dmq1 mod q */
|
||||
BN_init(&dmq1);
|
||||
BN_with_flags(&dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(m1, r1, &dmq1, rsa->q, ctx,
|
||||
rsa->_method_mod_q))
|
||||
goto err;
|
||||
|
||||
/* compute I mod p */
|
||||
BN_init(&c);
|
||||
BN_with_flags(&c, I, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!BN_mod_ct(r1, &c, rsa->p, ctx))
|
||||
goto err;
|
||||
|
||||
/* compute r1^dmp1 mod p */
|
||||
BN_init(&dmp1);
|
||||
BN_with_flags(&dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!rsa->meth->bn_mod_exp(r0, r1, &dmp1, rsa->p, ctx,
|
||||
rsa->_method_mod_p))
|
||||
goto err;
|
||||
|
||||
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;
|
||||
|
||||
/* Turn BN_FLG_CONSTTIME flag on before division operation */
|
||||
BN_init(&pr1);
|
||||
BN_with_flags(&pr1, r1, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!BN_mod_ct(r0, &pr1, rsa->p, ctx))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* If p < q it is occasionally possible for the correction of
|
||||
* adding 'p' if r0 is negative above to leave the result still
|
||||
* negative. This can break the private key operations: the following
|
||||
* second correction should *always* correct this rare occurrence.
|
||||
* This will *never* happen with OpenSSL generated keys because
|
||||
* they ensure p > q [steve]
|
||||
*/
|
||||
if (BN_is_negative(r0))
|
||||
if (!BN_add(r0, r0, rsa->p))
|
||||
goto err;
|
||||
if (!BN_mul(r1, r0, rsa->q, ctx))
|
||||
goto err;
|
||||
if (!BN_add(r0, r1, m1))
|
||||
goto err;
|
||||
|
||||
if (rsa->e && rsa->n) {
|
||||
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
|
||||
rsa->_method_mod_n))
|
||||
goto err;
|
||||
/*
|
||||
* If 'I' was greater than (or equal to) rsa->n, the operation
|
||||
* will be equivalent to using 'I mod n'. However, the result of
|
||||
* the verify will *always* be less than 'n' so we don't check
|
||||
* for absolute equality, just congruency.
|
||||
*/
|
||||
if (!BN_sub(vrfy, vrfy, I))
|
||||
goto err;
|
||||
if (!BN_mod_ct(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_init(&d);
|
||||
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)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
rsa_init(RSA *rsa)
|
||||
{
|
||||
rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
rsa_finish(RSA *rsa)
|
||||
{
|
||||
BN_MONT_CTX_free(rsa->_method_mod_n);
|
||||
BN_MONT_CTX_free(rsa->_method_mod_p);
|
||||
BN_MONT_CTX_free(rsa->_method_mod_q);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const RSA_METHOD rsa_pkcs1_meth = {
|
||||
.name = "OpenSSL PKCS#1 RSA",
|
||||
.rsa_pub_enc = rsa_public_encrypt,
|
||||
.rsa_pub_dec = rsa_public_decrypt, /* signature verification */
|
||||
.rsa_priv_enc = rsa_private_encrypt, /* signing */
|
||||
.rsa_priv_dec = rsa_private_decrypt,
|
||||
.rsa_mod_exp = rsa_mod_exp,
|
||||
.bn_mod_exp = BN_mod_exp_mont_ct, /* XXX probably we should not use Montgomery if e == 3 */
|
||||
.init = rsa_init,
|
||||
.finish = rsa_finish,
|
||||
};
|
||||
|
||||
const RSA_METHOD *
|
||||
RSA_PKCS1_OpenSSL(void)
|
||||
{
|
||||
return &rsa_pkcs1_meth;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_PKCS1_OpenSSL);
|
||||
|
||||
const RSA_METHOD *
|
||||
RSA_PKCS1_SSLeay(void)
|
||||
{
|
||||
return RSA_PKCS1_OpenSSL();
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_PKCS1_SSLeay);
|
||||
|
||||
int
|
||||
RSA_bits(const RSA *r)
|
||||
{
|
||||
return BN_num_bits(r->n);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_bits);
|
||||
|
||||
int
|
||||
RSA_size(const RSA *r)
|
||||
{
|
||||
return BN_num_bytes(r->n);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_size);
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_public_encrypt);
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_private_encrypt);
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_private_decrypt);
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_public_decrypt);
|
||||
|
||||
int
|
||||
RSA_flags(const RSA *r)
|
||||
{
|
||||
return r == NULL ? 0 : r->meth->flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_flags);
|
158
crypto/rsa/rsa_err.c
Normal file
158
crypto/rsa/rsa_err.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/* $OpenBSD: rsa_err.c,v 1.22 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
#define ERR_FUNC(func) ERR_PACK(ERR_LIB_RSA,func,0)
|
||||
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_RSA,0,reason)
|
||||
|
||||
static ERR_STRING_DATA RSA_str_functs[] = {
|
||||
{ERR_FUNC(0xfff), "CRYPTO_internal"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA RSA_str_reasons[] = {
|
||||
{ERR_REASON(RSA_R_ALGORITHM_MISMATCH) , "algorithm mismatch"},
|
||||
{ERR_REASON(RSA_R_BAD_E_VALUE) , "bad e value"},
|
||||
{ERR_REASON(RSA_R_BAD_FIXED_HEADER_DECRYPT), "bad fixed header decrypt"},
|
||||
{ERR_REASON(RSA_R_BAD_PAD_BYTE_COUNT) , "bad pad byte count"},
|
||||
{ERR_REASON(RSA_R_BAD_SIGNATURE) , "bad signature"},
|
||||
{ERR_REASON(RSA_R_BLOCK_TYPE_IS_NOT_01) , "block type is not 01"},
|
||||
{ERR_REASON(RSA_R_BLOCK_TYPE_IS_NOT_02) , "block type is not 02"},
|
||||
{ERR_REASON(RSA_R_DATA_GREATER_THAN_MOD_LEN), "data greater than mod len"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_LARGE) , "data too large"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE), "data too large for key size"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_LARGE_FOR_MODULUS), "data too large for modulus"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_SMALL) , "data too small"},
|
||||
{ERR_REASON(RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE), "data too small for key size"},
|
||||
{ERR_REASON(RSA_R_DIGEST_DOES_NOT_MATCH) , "digest does not match"},
|
||||
{ERR_REASON(RSA_R_DIGEST_NOT_ALLOWED) , "digest not allowed"},
|
||||
{ERR_REASON(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY), "digest too big for rsa key"},
|
||||
{ERR_REASON(RSA_R_DMP1_NOT_CONGRUENT_TO_D), "dmp1 not congruent to d"},
|
||||
{ERR_REASON(RSA_R_DMQ1_NOT_CONGRUENT_TO_D), "dmq1 not congruent to d"},
|
||||
{ERR_REASON(RSA_R_D_E_NOT_CONGRUENT_TO_1), "d e not congruent to 1"},
|
||||
{ERR_REASON(RSA_R_FIRST_OCTET_INVALID) , "first octet invalid"},
|
||||
{ERR_REASON(RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "illegal or unsupported padding mode"},
|
||||
{ERR_REASON(RSA_R_INVALID_DIGEST) , "invalid digest"},
|
||||
{ERR_REASON(RSA_R_INVALID_DIGEST_LENGTH) , "invalid digest length"},
|
||||
{ERR_REASON(RSA_R_INVALID_HEADER) , "invalid header"},
|
||||
{ERR_REASON(RSA_R_INVALID_LABEL) , "invalid label"},
|
||||
{ERR_REASON(RSA_R_INVALID_KEYBITS) , "invalid keybits"},
|
||||
{ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH), "invalid message length"},
|
||||
{ERR_REASON(RSA_R_INVALID_MGF1_MD) , "invalid mgf1 md"},
|
||||
{ERR_REASON(RSA_R_INVALID_OAEP_PARAMETERS), "invalid oaep parameters"},
|
||||
{ERR_REASON(RSA_R_INVALID_PADDING) , "invalid padding"},
|
||||
{ERR_REASON(RSA_R_INVALID_PADDING_MODE) , "invalid padding mode"},
|
||||
{ERR_REASON(RSA_R_INVALID_PSS_PARAMETERS), "invalid pss parameters"},
|
||||
{ERR_REASON(RSA_R_INVALID_PSS_SALTLEN) , "invalid pss saltlen"},
|
||||
{ERR_REASON(RSA_R_INVALID_SALT_LENGTH) , "invalid salt length"},
|
||||
{ERR_REASON(RSA_R_INVALID_TRAILER) , "invalid trailer"},
|
||||
{ERR_REASON(RSA_R_INVALID_X931_DIGEST) , "invalid x931 digest"},
|
||||
{ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) , "iqmp not inverse of q"},
|
||||
{ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL) , "key size too small"},
|
||||
{ERR_REASON(RSA_R_LAST_OCTET_INVALID) , "last octet invalid"},
|
||||
{ERR_REASON(RSA_R_MGF1_DIGEST_NOT_ALLOWED), "mgf1 digest not allowed"},
|
||||
{ERR_REASON(RSA_R_MODULUS_TOO_LARGE) , "modulus too large"},
|
||||
{ERR_REASON(RSA_R_NON_FIPS_RSA_METHOD) , "non fips rsa method"},
|
||||
{ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT) , "no public exponent"},
|
||||
{ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING), "null before block missing"},
|
||||
{ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q) , "n does not equal p q"},
|
||||
{ERR_REASON(RSA_R_OAEP_DECODING_ERROR) , "oaep decoding error"},
|
||||
{ERR_REASON(RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE), "operation not allowed in fips mode"},
|
||||
{ERR_REASON(RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), "operation not supported for this keytype"},
|
||||
{ERR_REASON(RSA_R_PADDING_CHECK_FAILED) , "padding check failed"},
|
||||
{ERR_REASON(RSA_R_PSS_SALTLEN_TOO_SMALL) , "pss saltlen too small"},
|
||||
{ERR_REASON(RSA_R_P_NOT_PRIME) , "p not prime"},
|
||||
{ERR_REASON(RSA_R_Q_NOT_PRIME) , "q not prime"},
|
||||
{ERR_REASON(RSA_R_RSA_OPERATIONS_NOT_SUPPORTED), "rsa operations not supported"},
|
||||
{ERR_REASON(RSA_R_SLEN_CHECK_FAILED) , "salt length check failed"},
|
||||
{ERR_REASON(RSA_R_SLEN_RECOVERY_FAILED) , "salt length recovery failed"},
|
||||
{ERR_REASON(RSA_R_SSLV3_ROLLBACK_ATTACK) , "sslv3 rollback attack"},
|
||||
{ERR_REASON(RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "the asn1 object identifier is not known for this md"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_ALGORITHM_TYPE), "unknown algorithm type"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_DIGEST) , "unknown digest"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_MASK_DIGEST) , "unknown mask digest"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_PADDING_TYPE) , "unknown padding type"},
|
||||
{ERR_REASON(RSA_R_UNKNOWN_PSS_DIGEST) , "unknown pss digest"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_ENCRYPTION_TYPE), "unsupported encryption type"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_LABEL_SOURCE), "unsupported label source"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_MASK_ALGORITHM), "unsupported mask algorithm"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_MASK_PARAMETER), "unsupported mask parameter"},
|
||||
{ERR_REASON(RSA_R_UNSUPPORTED_SIGNATURE_TYPE), "unsupported signature type"},
|
||||
{ERR_REASON(RSA_R_VALUE_MISSING) , "value missing"},
|
||||
{ERR_REASON(RSA_R_WRONG_SIGNATURE_LENGTH), "wrong signature length"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ERR_load_RSA_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(RSA_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings(0, RSA_str_functs);
|
||||
ERR_load_strings(0, RSA_str_reasons);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LCRYPTO_ALIAS(ERR_load_RSA_strings);
|
257
crypto/rsa/rsa_gen.c
Normal file
257
crypto/rsa/rsa_gen.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/* $OpenBSD: rsa_gen.c,v 1.30 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
|
||||
|
||||
int
|
||||
RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
|
||||
{
|
||||
if (rsa->meth->rsa_keygen)
|
||||
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
|
||||
return rsa_builtin_keygen(rsa, bits, e_value, cb);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_generate_key_ex);
|
||||
|
||||
static int
|
||||
rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
|
||||
BIGNUM pr0, d, p;
|
||||
int bitsp, bitsq, ok = -1, n = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
if ((r0 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((r1 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((r2 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((r3 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
bitsp = (bits + 1) / 2;
|
||||
bitsq = bits - bitsp;
|
||||
|
||||
/* We need the RSA components non-NULL */
|
||||
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->d && ((rsa->d = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->p && ((rsa->p = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->q && ((rsa->q = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
|
||||
goto err;
|
||||
|
||||
if (!bn_copy(rsa->e, e_value))
|
||||
goto err;
|
||||
|
||||
/* generate p and q */
|
||||
for (;;) {
|
||||
if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
|
||||
goto err;
|
||||
if (!BN_sub(r2, rsa->p, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_gcd_ct(r1, r2, rsa->e, ctx))
|
||||
goto err;
|
||||
if (BN_is_one(r1))
|
||||
break;
|
||||
if (!BN_GENCB_call(cb, 2, n++))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
for (;;) {
|
||||
/*
|
||||
* When generating ridiculously small keys, we can get stuck
|
||||
* continually regenerating the same prime values. Check for
|
||||
* this and bail if it happens 3 times.
|
||||
*/
|
||||
unsigned int degenerate = 0;
|
||||
do {
|
||||
if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL,
|
||||
cb))
|
||||
goto err;
|
||||
} while (BN_cmp(rsa->p, rsa->q) == 0 &&
|
||||
++degenerate < 3);
|
||||
if (degenerate == 3) {
|
||||
ok = 0; /* we set our own err */
|
||||
RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one()))
|
||||
goto err;
|
||||
if (!BN_gcd_ct(r1, r2, rsa->e, ctx))
|
||||
goto err;
|
||||
if (BN_is_one(r1))
|
||||
break;
|
||||
if (!BN_GENCB_call(cb, 2, n++))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 3, 1))
|
||||
goto err;
|
||||
if (BN_cmp(rsa->p, rsa->q) < 0) {
|
||||
tmp = rsa->p;
|
||||
rsa->p = rsa->q;
|
||||
rsa->q = tmp;
|
||||
}
|
||||
|
||||
/* calculate n */
|
||||
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d */
|
||||
if (!BN_sub(r1, rsa->p, BN_value_one())) /* p-1 */
|
||||
goto err;
|
||||
if (!BN_sub(r2, rsa->q, BN_value_one())) /* q-1 */
|
||||
goto err;
|
||||
if (!BN_mul(r0, r1, r2, ctx)) /* (p-1)(q-1) */
|
||||
goto err;
|
||||
|
||||
BN_init(&pr0);
|
||||
BN_with_flags(&pr0, r0, BN_FLG_CONSTTIME);
|
||||
|
||||
if (BN_mod_inverse_ct(rsa->d, rsa->e, &pr0, ctx) == NULL) /* d */
|
||||
goto err;
|
||||
|
||||
/* set up d for correct BN_FLG_CONSTTIME flag */
|
||||
BN_init(&d);
|
||||
BN_with_flags(&d, rsa->d, BN_FLG_CONSTTIME);
|
||||
|
||||
/* calculate d mod (p-1) */
|
||||
if (!BN_mod_ct(rsa->dmp1, &d, r1, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate d mod (q-1) */
|
||||
if (!BN_mod_ct(rsa->dmq1, &d, r2, ctx))
|
||||
goto err;
|
||||
|
||||
/* calculate inverse of q mod p */
|
||||
BN_init(&p);
|
||||
BN_with_flags(&p, rsa->p, BN_FLG_CONSTTIME);
|
||||
if (BN_mod_inverse_ct(rsa->iqmp, rsa->q, &p, ctx) == NULL)
|
||||
goto err;
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
RSAerror(ERR_LIB_BN);
|
||||
ok = 0;
|
||||
}
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
RSA *
|
||||
RSA_generate_key(int bits, unsigned long e_value,
|
||||
void (*callback)(int, int, void *), void *cb_arg)
|
||||
{
|
||||
BN_GENCB cb;
|
||||
int i;
|
||||
RSA *rsa = RSA_new();
|
||||
BIGNUM *e = BN_new();
|
||||
|
||||
if (!rsa || !e)
|
||||
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);
|
||||
return rsa;
|
||||
}
|
||||
err:
|
||||
BN_free(e);
|
||||
RSA_free(rsa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_generate_key);
|
460
crypto/rsa/rsa_lib.c
Normal file
460
crypto/rsa/rsa_lib.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/* $OpenBSD: rsa_lib.c,v 1.48 2023/07/28 10:05:16 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/lhash.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "evp_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
static const RSA_METHOD *default_RSA_meth = NULL;
|
||||
|
||||
RSA *
|
||||
RSA_new(void)
|
||||
{
|
||||
RSA *r = RSA_new_method(NULL);
|
||||
|
||||
return r;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_new);
|
||||
|
||||
void
|
||||
RSA_set_default_method(const RSA_METHOD *meth)
|
||||
{
|
||||
default_RSA_meth = meth;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set_default_method);
|
||||
|
||||
const RSA_METHOD *
|
||||
RSA_get_default_method(void)
|
||||
{
|
||||
if (default_RSA_meth == NULL)
|
||||
default_RSA_meth = RSA_PKCS1_SSLeay();
|
||||
|
||||
return default_RSA_meth;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get_default_method);
|
||||
|
||||
const RSA_METHOD *
|
||||
RSA_get_method(const RSA *rsa)
|
||||
{
|
||||
return rsa->meth;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get_method);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set_method);
|
||||
|
||||
RSA *
|
||||
RSA_new_method(ENGINE *engine)
|
||||
{
|
||||
RSA *ret;
|
||||
|
||||
if ((ret = calloc(1, sizeof(RSA))) == NULL) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->meth = RSA_get_default_method();
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
if (engine != NULL) {
|
||||
if (!ENGINE_init(engine)) {
|
||||
RSAerror(ERR_R_ENGINE_LIB);
|
||||
goto err;
|
||||
}
|
||||
ret->engine = engine;
|
||||
} else {
|
||||
ret->engine = ENGINE_get_default_RSA();
|
||||
}
|
||||
|
||||
if (ret->engine != NULL) {
|
||||
if ((ret->meth = ENGINE_get_RSA(ret->engine)) == NULL) {
|
||||
RSAerror(ERR_R_ENGINE_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ret->references = 1;
|
||||
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)) {
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(ret->engine);
|
||||
#endif
|
||||
free(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_new_method);
|
||||
|
||||
void
|
||||
RSA_free(RSA *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (r == NULL)
|
||||
return;
|
||||
|
||||
i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_RSA);
|
||||
if (i > 0)
|
||||
return;
|
||||
|
||||
if (r->meth->finish)
|
||||
r->meth->finish(r);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(r->engine);
|
||||
#endif
|
||||
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
|
||||
|
||||
BN_free(r->n);
|
||||
BN_free(r->e);
|
||||
BN_free(r->d);
|
||||
BN_free(r->p);
|
||||
BN_free(r->q);
|
||||
BN_free(r->dmp1);
|
||||
BN_free(r->dmq1);
|
||||
BN_free(r->iqmp);
|
||||
BN_BLINDING_free(r->blinding);
|
||||
BN_BLINDING_free(r->mt_blinding);
|
||||
RSA_PSS_PARAMS_free(r->pss);
|
||||
free(r);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_free);
|
||||
|
||||
int
|
||||
RSA_up_ref(RSA *r)
|
||||
{
|
||||
int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_RSA);
|
||||
return i > 1 ? 1 : 0;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_up_ref);
|
||||
|
||||
int
|
||||
RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
|
||||
{
|
||||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
|
||||
new_func, dup_func, free_func);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get_ex_new_index);
|
||||
|
||||
int
|
||||
RSA_set_ex_data(RSA *r, int idx, void *arg)
|
||||
{
|
||||
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set_ex_data);
|
||||
|
||||
void *
|
||||
RSA_get_ex_data(const RSA *r, int idx)
|
||||
{
|
||||
return CRYPTO_get_ex_data(&r->ex_data, idx);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get_ex_data);
|
||||
|
||||
int
|
||||
RSA_security_bits(const RSA *rsa)
|
||||
{
|
||||
return BN_security_bits(RSA_bits(rsa), -1);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_security_bits);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_key);
|
||||
|
||||
int
|
||||
RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
|
||||
{
|
||||
if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL))
|
||||
return 0;
|
||||
|
||||
if (n != NULL) {
|
||||
BN_free(r->n);
|
||||
r->n = n;
|
||||
}
|
||||
if (e != NULL) {
|
||||
BN_free(r->e);
|
||||
r->e = e;
|
||||
}
|
||||
if (d != NULL) {
|
||||
BN_free(r->d);
|
||||
r->d = d;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set0_key);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_crt_params);
|
||||
|
||||
int
|
||||
RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
|
||||
{
|
||||
if ((r->dmp1 == NULL && dmp1 == NULL) ||
|
||||
(r->dmq1 == NULL && dmq1 == NULL) ||
|
||||
(r->iqmp == NULL && iqmp == NULL))
|
||||
return 0;
|
||||
|
||||
if (dmp1 != NULL) {
|
||||
BN_free(r->dmp1);
|
||||
r->dmp1 = dmp1;
|
||||
}
|
||||
if (dmq1 != NULL) {
|
||||
BN_free(r->dmq1);
|
||||
r->dmq1 = dmq1;
|
||||
}
|
||||
if (iqmp != NULL) {
|
||||
BN_free(r->iqmp);
|
||||
r->iqmp = iqmp;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set0_crt_params);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_factors);
|
||||
|
||||
int
|
||||
RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
|
||||
{
|
||||
if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL))
|
||||
return 0;
|
||||
|
||||
if (p != NULL) {
|
||||
BN_free(r->p);
|
||||
r->p = p;
|
||||
}
|
||||
if (q != NULL) {
|
||||
BN_free(r->q);
|
||||
r->q = q;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set0_factors);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_n(const RSA *r)
|
||||
{
|
||||
return r->n;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_n);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_e(const RSA *r)
|
||||
{
|
||||
return r->e;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_e);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_d(const RSA *r)
|
||||
{
|
||||
return r->d;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_d);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_p(const RSA *r)
|
||||
{
|
||||
return r->p;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_p);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_q(const RSA *r)
|
||||
{
|
||||
return r->q;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_q);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_dmp1(const RSA *r)
|
||||
{
|
||||
return r->dmp1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_dmp1);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_dmq1(const RSA *r)
|
||||
{
|
||||
return r->dmq1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_dmq1);
|
||||
|
||||
const BIGNUM *
|
||||
RSA_get0_iqmp(const RSA *r)
|
||||
{
|
||||
return r->iqmp;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_iqmp);
|
||||
|
||||
const RSA_PSS_PARAMS *
|
||||
RSA_get0_pss_params(const RSA *r)
|
||||
{
|
||||
return r->pss;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_get0_pss_params);
|
||||
|
||||
void
|
||||
RSA_clear_flags(RSA *r, int flags)
|
||||
{
|
||||
r->flags &= ~flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_clear_flags);
|
||||
|
||||
int
|
||||
RSA_test_flags(const RSA *r, int flags)
|
||||
{
|
||||
return r->flags & flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_test_flags);
|
||||
|
||||
void
|
||||
RSA_set_flags(RSA *r, int flags)
|
||||
{
|
||||
r->flags |= flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_set_flags);
|
||||
|
||||
int
|
||||
RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
|
||||
{
|
||||
/* Return an error if the key type is not RSA or RSA-PSS. */
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_pkey_ctx_ctrl);
|
165
crypto/rsa/rsa_local.h
Normal file
165
crypto/rsa/rsa_local.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/* $OpenBSD: rsa_local.h,v 1.6 2023/08/09 12:09:06 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
__BEGIN_HIDDEN_DECLS
|
||||
|
||||
#define RSA_MIN_MODULUS_BITS 512
|
||||
|
||||
/* 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)
|
||||
|
||||
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);
|
||||
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); /* Can be null */
|
||||
int (*init)(RSA *rsa); /* called at new */
|
||||
int (*finish)(RSA *rsa); /* called at free */
|
||||
int flags; /* RSA_METHOD_FLAG_* things */
|
||||
char *app_data; /* may be needed! */
|
||||
/* 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. Note: for backwards
|
||||
* compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER
|
||||
* option is set in 'flags'.
|
||||
*/
|
||||
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);
|
||||
};
|
||||
|
||||
struct rsa_st {
|
||||
/* The first parameter is used to pickup errors where
|
||||
* this is passed instead of aEVP_PKEY, it is set to 0 */
|
||||
int pad;
|
||||
long version;
|
||||
const RSA_METHOD *meth;
|
||||
|
||||
/* functional reference if 'meth' is ENGINE-provided */
|
||||
ENGINE *engine;
|
||||
BIGNUM *n;
|
||||
BIGNUM *e;
|
||||
BIGNUM *d;
|
||||
BIGNUM *p;
|
||||
BIGNUM *q;
|
||||
BIGNUM *dmp1;
|
||||
BIGNUM *dmq1;
|
||||
BIGNUM *iqmp;
|
||||
|
||||
/* Parameter restrictions for PSS only keys. */
|
||||
RSA_PSS_PARAMS *pss;
|
||||
|
||||
/* be careful using this if the RSA structure is shared */
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
int references;
|
||||
int flags;
|
||||
|
||||
/* Used to cache montgomery values */
|
||||
BN_MONT_CTX *_method_mod_n;
|
||||
BN_MONT_CTX *_method_mod_p;
|
||||
BN_MONT_CTX *_method_mod_q;
|
||||
|
||||
/* all BIGNUM values are actually in the following data, if it is not
|
||||
* NULL */
|
||||
BN_BLINDING *blinding;
|
||||
BN_BLINDING *mt_blinding;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
int RSA_padding_add_X931(unsigned char *to, int tlen,
|
||||
const unsigned char *f, int fl);
|
||||
int RSA_padding_check_X931(unsigned char *to, int tlen,
|
||||
const unsigned char *f, int fl, int rsa_len);
|
||||
int RSA_X931_hash_id(int nid);
|
||||
|
||||
BN_BLINDING *BN_BLINDING_new(const BIGNUM *e, const BIGNUM *mod, BN_CTX *ctx,
|
||||
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx);
|
||||
void BN_BLINDING_free(BN_BLINDING *b);
|
||||
int BN_BLINDING_convert(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
|
||||
int BN_BLINDING_invert(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
|
||||
int BN_BLINDING_is_local(BN_BLINDING *b);
|
||||
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
|
||||
|
||||
__END_HIDDEN_DECLS
|
309
crypto/rsa/rsa_meth.c
Normal file
309
crypto/rsa/rsa_meth.c
Normal file
@@ -0,0 +1,309 @@
|
||||
/* $OpenBSD: rsa_meth.c,v 1.7 2023/07/08 12:26:45 beck Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "rsa_local.h"
|
||||
|
||||
RSA_METHOD *
|
||||
RSA_meth_new(const char *name, int flags)
|
||||
{
|
||||
RSA_METHOD *meth;
|
||||
|
||||
if ((meth = calloc(1, sizeof(*meth))) == NULL)
|
||||
return NULL;
|
||||
if ((meth->name = strdup(name)) == NULL) {
|
||||
free(meth);
|
||||
return NULL;
|
||||
}
|
||||
meth->flags = flags;
|
||||
|
||||
return meth;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_new);
|
||||
|
||||
void
|
||||
RSA_meth_free(RSA_METHOD *meth)
|
||||
{
|
||||
if (meth == NULL)
|
||||
return;
|
||||
|
||||
free(meth->name);
|
||||
free(meth);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_free);
|
||||
|
||||
RSA_METHOD *
|
||||
RSA_meth_dup(const RSA_METHOD *meth)
|
||||
{
|
||||
RSA_METHOD *copy;
|
||||
|
||||
if ((copy = calloc(1, sizeof(*copy))) == NULL)
|
||||
return NULL;
|
||||
memcpy(copy, meth, sizeof(*copy));
|
||||
if ((copy->name = strdup(meth->name)) == NULL) {
|
||||
free(copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_dup);
|
||||
|
||||
int
|
||||
RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
|
||||
{
|
||||
char *new_name;
|
||||
|
||||
if ((new_name = strdup(name)) == NULL)
|
||||
return 0;
|
||||
free(meth->name);
|
||||
meth->name = new_name;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set1_name);
|
||||
|
||||
int
|
||||
(*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa)
|
||||
{
|
||||
return meth->finish;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_finish);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_priv_enc);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_priv_dec);
|
||||
|
||||
int
|
||||
RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa))
|
||||
{
|
||||
meth->finish = finish;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_finish);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_pub_enc);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_pub_dec);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_bn_mod_exp);
|
||||
|
||||
int
|
||||
RSA_meth_set_init(RSA_METHOD *meth, int (*init)(RSA *rsa))
|
||||
{
|
||||
meth->init = init;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_init);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_keygen);
|
||||
|
||||
int
|
||||
RSA_meth_set_flags(RSA_METHOD *meth, int flags)
|
||||
{
|
||||
meth->flags = flags;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_flags);
|
||||
|
||||
int
|
||||
RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
|
||||
{
|
||||
meth->app_data = app_data;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set0_app_data);
|
||||
|
||||
const char *
|
||||
RSA_meth_get0_name(const RSA_METHOD *meth)
|
||||
{
|
||||
return meth->name;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get0_name);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_pub_enc);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_pub_dec);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_priv_enc);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_priv_dec);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_mod_exp);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_bn_mod_exp);
|
||||
|
||||
int
|
||||
(*RSA_meth_get_init(const RSA_METHOD *meth))(RSA *rsa)
|
||||
{
|
||||
return meth->init;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_init);
|
||||
|
||||
int
|
||||
(*RSA_meth_get_keygen(const RSA_METHOD *meth))(RSA *rsa, int bits, BIGNUM *e,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
return meth->rsa_keygen;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_keygen);
|
||||
|
||||
int
|
||||
RSA_meth_get_flags(const RSA_METHOD *meth)
|
||||
{
|
||||
return meth->flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_flags);
|
||||
|
||||
void *
|
||||
RSA_meth_get0_app_data(const RSA_METHOD *meth)
|
||||
{
|
||||
return meth->app_data;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get0_app_data);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_sign);
|
||||
|
||||
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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_get_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;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_meth_set_verify);
|
98
crypto/rsa/rsa_none.c
Normal file
98
crypto/rsa/rsa_none.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* $OpenBSD: rsa_none.c,v 1.12 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
int
|
||||
RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *from,
|
||||
int flen)
|
||||
{
|
||||
if (flen > tlen) {
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flen < tlen) {
|
||||
RSAerror(RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(to, from, flen);
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_none);
|
||||
|
||||
int
|
||||
RSA_padding_check_none(unsigned char *to, int tlen, const unsigned char *from,
|
||||
int flen, int num)
|
||||
{
|
||||
if (flen > tlen) {
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(to, 0, tlen - flen);
|
||||
memcpy(to + tlen - flen, from, flen);
|
||||
return tlen;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_check_none);
|
363
crypto/rsa/rsa_oaep.c
Normal file
363
crypto/rsa/rsa_oaep.c
Normal file
@@ -0,0 +1,363 @@
|
||||
/* $OpenBSD: rsa_oaep.c,v 1.37 2023/07/08 12:26:45 beck Exp $ */
|
||||
/*
|
||||
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "constant_time.h"
|
||||
#include "evp_local.h"
|
||||
#include "rsa_local.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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_PKCS1_OAEP);
|
||||
|
||||
int
|
||||
RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen, const unsigned char *param, int plen,
|
||||
const EVP_MD *md, const EVP_MD *mgf1md)
|
||||
{
|
||||
int i, emlen = tlen - 1;
|
||||
unsigned char *db, *seed;
|
||||
unsigned char *dbmask = NULL;
|
||||
unsigned char seedmask[EVP_MAX_MD_SIZE];
|
||||
int mdlen, dbmask_len = 0;
|
||||
int rv = 0;
|
||||
|
||||
if (md == NULL)
|
||||
md = EVP_sha1();
|
||||
if (mgf1md == NULL)
|
||||
mgf1md = md;
|
||||
|
||||
if ((mdlen = EVP_MD_size(md)) <= 0)
|
||||
goto err;
|
||||
|
||||
if (flen > emlen - 2 * mdlen - 1) {
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (emlen < 2 * mdlen + 1) {
|
||||
RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
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, flen);
|
||||
arc4random_buf(seed, mdlen);
|
||||
|
||||
dbmask_len = emlen - mdlen;
|
||||
if ((dbmask = malloc(dbmask_len)) == NULL) {
|
||||
RSAerror(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:
|
||||
explicit_bzero(seedmask, sizeof(seedmask));
|
||||
freezero(dbmask, dbmask_len);
|
||||
|
||||
return rv;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_PKCS1_OAEP_mgf1);
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_check_PKCS1_OAEP);
|
||||
|
||||
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;
|
||||
unsigned char seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
|
||||
unsigned char *db = NULL, *em = NULL;
|
||||
int mdlen;
|
||||
|
||||
if (md == NULL)
|
||||
md = EVP_sha1();
|
||||
if (mgf1md == NULL)
|
||||
mgf1md = md;
|
||||
|
||||
if ((mdlen = EVP_MD_size(md)) <= 0)
|
||||
return -1;
|
||||
|
||||
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) {
|
||||
RSAerror(RSA_R_OAEP_DECODING_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dblen = num - mdlen - 1;
|
||||
if ((db = malloc(dblen)) == NULL) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto cleanup;
|
||||
}
|
||||
if ((em = malloc(num)) == NULL) {
|
||||
RSAerror(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;
|
||||
}
|
||||
|
||||
/*
|
||||
* The first byte must be zero, however we must not leak if this is
|
||||
* true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
|
||||
* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
|
||||
*/
|
||||
good = constant_time_is_zero(em[0]);
|
||||
|
||||
maskedseed = em + 1;
|
||||
maskeddb = em + 1 + mdlen;
|
||||
|
||||
if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
|
||||
goto cleanup;
|
||||
for (i = 0; i < mdlen; i++)
|
||||
seed[i] ^= maskedseed[i];
|
||||
|
||||
if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md))
|
||||
goto cleanup;
|
||||
for (i = 0; i < dblen; i++)
|
||||
db[i] ^= maskeddb[i];
|
||||
|
||||
if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL))
|
||||
goto cleanup;
|
||||
|
||||
good &= constant_time_is_zero(timingsafe_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 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. The last |tlen| of
|
||||
* |dblen| bytes are viewed as a circular buffer starting at |tlen|-|mlen'|,
|
||||
* where |mlen'| is the "saturated" |mlen| value. Deducing information
|
||||
* about failure or |mlen| would require an attacker to observe
|
||||
* memory access patterns 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 - mdlen - 1, tlen),
|
||||
dblen - mdlen - 1, tlen);
|
||||
msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
|
||||
mlen = dblen - msg_index;
|
||||
for (mask = good, i = 0; i < tlen; i++) {
|
||||
unsigned int equals = constant_time_eq(msg_index, dblen);
|
||||
|
||||
msg_index -= tlen & equals; /* rewind at EOF */
|
||||
mask &= ~equals; /* mask = 0 at EOF */
|
||||
to[i] = constant_time_select_8(mask, db[msg_index++], to[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid chosen ciphertext attacks, the error message should not
|
||||
* reveal which kind of decoding error happened.
|
||||
*/
|
||||
RSAerror(RSA_R_OAEP_DECODING_ERROR);
|
||||
err_clear_last_constant_time(1 & good);
|
||||
|
||||
cleanup:
|
||||
explicit_bzero(seed, sizeof(seed));
|
||||
freezero(db, dblen);
|
||||
freezero(em, num);
|
||||
|
||||
return constant_time_select_int(good, mlen, -1);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_check_PKCS1_OAEP_mgf1);
|
||||
|
||||
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;
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
int mdlen;
|
||||
int rv = -1;
|
||||
|
||||
EVP_MD_CTX_init(&c);
|
||||
mdlen = EVP_MD_size(dgst);
|
||||
if (mdlen < 0)
|
||||
goto err;
|
||||
for (i = 0; outlen < len; i++) {
|
||||
cnt[0] = (unsigned char)((i >> 24) & 255);
|
||||
cnt[1] = (unsigned char)((i >> 16) & 255);
|
||||
cnt[2] = (unsigned char)((i >> 8)) & 255;
|
||||
cnt[3] = (unsigned char)(i & 255);
|
||||
if (!EVP_DigestInit_ex(&c, dgst, NULL) ||
|
||||
!EVP_DigestUpdate(&c, seed, seedlen) ||
|
||||
!EVP_DigestUpdate(&c, cnt, 4))
|
||||
goto err;
|
||||
if (outlen + mdlen <= len) {
|
||||
if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL))
|
||||
goto err;
|
||||
outlen += mdlen;
|
||||
} else {
|
||||
if (!EVP_DigestFinal_ex(&c, md, NULL))
|
||||
goto err;
|
||||
memcpy(mask + outlen, md, len - outlen);
|
||||
outlen = len;
|
||||
}
|
||||
}
|
||||
rv = 0;
|
||||
err:
|
||||
EVP_MD_CTX_cleanup(&c);
|
||||
return rv;
|
||||
}
|
||||
LCRYPTO_ALIAS(PKCS1_MGF1);
|
217
crypto/rsa/rsa_pk1.c
Normal file
217
crypto/rsa/rsa_pk1.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/* $OpenBSD: rsa_pk1.c,v 1.16 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.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)) {
|
||||
RSAerror(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, flen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_PKCS1_type_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;
|
||||
if (num != flen + 1 || *(p++) != 01) {
|
||||
RSAerror(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 {
|
||||
RSAerror(RSA_R_BAD_FIXED_HEADER_DECRYPT);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (i == j) {
|
||||
RSAerror(RSA_R_NULL_BEFORE_BLOCK_MISSING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i < 8) {
|
||||
RSAerror(RSA_R_BAD_PAD_BYTE_COUNT);
|
||||
return -1;
|
||||
}
|
||||
i++; /* Skip over the '\0' */
|
||||
j -= i;
|
||||
if (j > tlen) {
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
memcpy(to, p, j);
|
||||
|
||||
return j;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_check_PKCS1_type_1);
|
||||
|
||||
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) {
|
||||
RSAerror(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;
|
||||
|
||||
arc4random_buf(p, j);
|
||||
for (i = 0; i < j; i++) {
|
||||
while (*p == '\0')
|
||||
arc4random_buf(p, 1);
|
||||
p++;
|
||||
}
|
||||
|
||||
*(p++) = '\0';
|
||||
|
||||
memcpy(p, from, flen);
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_PKCS1_type_2);
|
||||
|
||||
int
|
||||
RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
|
||||
const unsigned char *from, int flen, int num)
|
||||
{
|
||||
int i, j;
|
||||
const unsigned char *p;
|
||||
|
||||
p = from;
|
||||
if (num != flen + 1 || *(p++) != 02) {
|
||||
RSAerror(RSA_R_BLOCK_TYPE_IS_NOT_02);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* scan over padding data */
|
||||
j = flen - 1; /* one for type. */
|
||||
for (i = 0; i < j; i++)
|
||||
if (*(p++) == 0)
|
||||
break;
|
||||
|
||||
if (i == j) {
|
||||
RSAerror(RSA_R_NULL_BEFORE_BLOCK_MISSING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i < 8) {
|
||||
RSAerror(RSA_R_BAD_PAD_BYTE_COUNT);
|
||||
return -1;
|
||||
}
|
||||
i++; /* Skip over the '\0' */
|
||||
j -= i;
|
||||
if (j > tlen) {
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE);
|
||||
return -1;
|
||||
}
|
||||
memcpy(to, p, j);
|
||||
|
||||
return j;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_check_PKCS1_type_2);
|
879
crypto/rsa/rsa_pmeth.c
Normal file
879
crypto/rsa/rsa_pmeth.c
Normal file
@@ -0,0 +1,879 @@
|
||||
/* $OpenBSD: rsa_pmeth.c,v 1.39 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "evp_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
/* RSA pkey context structure */
|
||||
|
||||
typedef struct {
|
||||
/* Key gen parameters */
|
||||
int nbits;
|
||||
BIGNUM *pub_exp;
|
||||
/* Keygen callback info */
|
||||
int gentmp[2];
|
||||
/* RSA padding mode */
|
||||
int pad_mode;
|
||||
/* message digest */
|
||||
const EVP_MD *md;
|
||||
/* message digest for MGF1 */
|
||||
const EVP_MD *mgf1md;
|
||||
/* PSS salt length */
|
||||
int saltlen;
|
||||
/* 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;
|
||||
|
||||
if ((rctx = calloc(1, sizeof(RSA_PKEY_CTX))) == NULL)
|
||||
return 0;
|
||||
|
||||
rctx->nbits = 2048;
|
||||
|
||||
if (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
|
||||
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 != NULL) {
|
||||
BN_free(dctx->pub_exp);
|
||||
if ((dctx->pub_exp = BN_dup(sctx->pub_exp)) == NULL)
|
||||
return 0;
|
||||
}
|
||||
dctx->pad_mode = sctx->pad_mode;
|
||||
dctx->md = sctx->md;
|
||||
dctx->mgf1md = sctx->mgf1md;
|
||||
if (sctx->oaep_label != NULL) {
|
||||
free(dctx->oaep_label);
|
||||
if ((dctx->oaep_label = calloc(1, sctx->oaep_labellen)) == NULL)
|
||||
return 0;
|
||||
memcpy(dctx->oaep_label, sctx->oaep_label, sctx->oaep_labellen);
|
||||
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 = calloc(1, EVP_PKEY_size(pk->pkey))) == NULL) {
|
||||
RSAerror(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);
|
||||
free(rctx->tbuf);
|
||||
free(rctx->oaep_label);
|
||||
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)) {
|
||||
RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rctx->pad_mode == RSA_X931_PADDING) {
|
||||
if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) {
|
||||
RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
if (!setup_tbuf(rctx, ctx)) {
|
||||
RSAerror(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))) {
|
||||
RSAerror(RSA_R_ALGORITHM_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (ret != EVP_MD_size(rctx->md)) {
|
||||
RSAerror(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)) {
|
||||
RSAerror(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 {
|
||||
int ret;
|
||||
|
||||
if (!setup_tbuf(rctx, ctx))
|
||||
return -1;
|
||||
|
||||
if ((ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa,
|
||||
rctx->pad_mode)) <= 0)
|
||||
return 0;
|
||||
|
||||
rslen = ret;
|
||||
}
|
||||
|
||||
if (rslen != tbslen || timingsafe_bcmp(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)
|
||||
{
|
||||
RSA_PKEY_CTX *rctx = ctx->data;
|
||||
int ret;
|
||||
|
||||
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)
|
||||
{
|
||||
if (md == NULL)
|
||||
return 1;
|
||||
|
||||
if (padding == RSA_NO_PADDING) {
|
||||
RSAerror(RSA_R_INVALID_PADDING_MODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
if (RSA_X931_hash_id(EVP_MD_type(md)) == -1) {
|
||||
RSAerror(RSA_R_INVALID_X931_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* List of all supported RSA digests. */
|
||||
/* RFC 8017 and NIST CSOR. */
|
||||
switch(EVP_MD_type(md)) {
|
||||
case NID_sha1:
|
||||
case NID_sha224:
|
||||
case NID_sha256:
|
||||
case NID_sha384:
|
||||
case NID_sha512:
|
||||
case NID_sha512_224:
|
||||
case NID_sha512_256:
|
||||
case NID_sha3_224:
|
||||
case NID_sha3_256:
|
||||
case NID_sha3_384:
|
||||
case NID_sha3_512:
|
||||
case NID_md5:
|
||||
case NID_md5_sha1:
|
||||
case NID_md4:
|
||||
case NID_ripemd160:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
RSAerror(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 (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) {
|
||||
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:
|
||||
RSAerror(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) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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)) {
|
||||
RSAerror(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) {
|
||||
RSAerror(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)) {
|
||||
RSAerror(RSA_R_BAD_E_VALUE);
|
||||
return -2;
|
||||
}
|
||||
BN_free(rctx->pub_exp);
|
||||
rctx->pub_exp = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_RSA_OAEP_MD:
|
||||
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
|
||||
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
|
||||
RSAerror(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;
|
||||
RSAerror(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) {
|
||||
RSAerror(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;
|
||||
RSAerror(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) {
|
||||
RSAerror(RSA_R_INVALID_PADDING_MODE);
|
||||
return -2;
|
||||
}
|
||||
free(rctx->oaep_label);
|
||||
if (p2 != NULL && 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) {
|
||||
RSAerror(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 (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
|
||||
return 1;
|
||||
|
||||
/* fall through */
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
RSAerror(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) {
|
||||
RSAerror(RSA_R_VALUE_MISSING);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(type, "rsa_padding_mode")) {
|
||||
int pm;
|
||||
if (!strcmp(value, "pkcs1"))
|
||||
pm = RSA_PKCS1_PADDING;
|
||||
else if (!strcmp(value, "none"))
|
||||
pm = RSA_NO_PADDING;
|
||||
else if (!strcmp(value, "oeap"))
|
||||
pm = RSA_PKCS1_OAEP_PADDING;
|
||||
else if (!strcmp(value, "oaep"))
|
||||
pm = RSA_PKCS1_OAEP_PADDING;
|
||||
else if (!strcmp(value, "x931"))
|
||||
pm = RSA_X931_PADDING;
|
||||
else if (!strcmp(value, "pss"))
|
||||
pm = RSA_PKCS1_PSS_PADDING;
|
||||
else {
|
||||
RSAerror(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) {
|
||||
BIGNUM *pubexp = NULL;
|
||||
int ret;
|
||||
|
||||
if (!BN_asc2bn(&pubexp, value))
|
||||
return 0;
|
||||
ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
|
||||
if (ret <= 0)
|
||||
BN_free(pubexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strcmp(type, "rsa_mgf1_md") == 0)
|
||||
return EVP_PKEY_CTX_md(ctx,
|
||||
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
|
||||
EVP_PKEY_CTRL_RSA_MGF1_MD, value);
|
||||
|
||||
if (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) {
|
||||
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;
|
||||
|
||||
if ((lab = string_to_hex(value, &lablen)) == NULL)
|
||||
return 0;
|
||||
ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
|
||||
if (ret <= 0)
|
||||
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 (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
|
||||
return 1;
|
||||
|
||||
/* If all parameters are default values then do not set PSS. */
|
||||
if (rctx->md == NULL && rctx->mgf1md == NULL &&
|
||||
rctx->saltlen == RSA_PSS_SALTLEN_AUTO)
|
||||
return 1;
|
||||
|
||||
rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md,
|
||||
rctx->saltlen == RSA_PSS_SALTLEN_AUTO ? 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, cb;
|
||||
int ret;
|
||||
|
||||
if (rctx->pub_exp == NULL) {
|
||||
if ((rctx->pub_exp = BN_new()) == NULL)
|
||||
return 0;
|
||||
if (!BN_set_word(rctx->pub_exp, RSA_F4))
|
||||
return 0;
|
||||
}
|
||||
if ((rsa = RSA_new()) == NULL)
|
||||
return 0;
|
||||
if (ctx->pkey_gencb != NULL) {
|
||||
pcb = &cb;
|
||||
evp_pkey_set_cb_translate(pcb, ctx);
|
||||
} else {
|
||||
pcb = NULL;
|
||||
}
|
||||
ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, 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 = {
|
||||
.pkey_id = EVP_PKEY_RSA,
|
||||
.flags = EVP_PKEY_FLAG_AUTOARGLEN,
|
||||
|
||||
.init = pkey_rsa_init,
|
||||
.copy = pkey_rsa_copy,
|
||||
.cleanup = pkey_rsa_cleanup,
|
||||
|
||||
.keygen = pkey_rsa_keygen,
|
||||
|
||||
.sign = pkey_rsa_sign,
|
||||
|
||||
.verify = pkey_rsa_verify,
|
||||
|
||||
.verify_recover = pkey_rsa_verifyrecover,
|
||||
|
||||
.encrypt = pkey_rsa_encrypt,
|
||||
|
||||
.decrypt = pkey_rsa_decrypt,
|
||||
|
||||
.ctrl = pkey_rsa_ctrl,
|
||||
.ctrl_str = 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 (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
|
||||
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) {
|
||||
RSAerror(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 = {
|
||||
.pkey_id = EVP_PKEY_RSA_PSS,
|
||||
.flags = EVP_PKEY_FLAG_AUTOARGLEN,
|
||||
|
||||
.init = pkey_rsa_init,
|
||||
.copy = pkey_rsa_copy,
|
||||
.cleanup = pkey_rsa_cleanup,
|
||||
|
||||
.keygen = pkey_rsa_keygen,
|
||||
|
||||
.sign_init = pkey_pss_init,
|
||||
.sign = pkey_rsa_sign,
|
||||
|
||||
.verify_init = pkey_pss_init,
|
||||
.verify = pkey_rsa_verify,
|
||||
|
||||
.ctrl = pkey_rsa_ctrl,
|
||||
.ctrl_str = pkey_rsa_ctrl_str
|
||||
};
|
99
crypto/rsa/rsa_prn.c
Normal file
99
crypto/rsa/rsa_prn.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* $OpenBSD: rsa_prn.c,v 1.10 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
int
|
||||
RSA_print_fp(FILE *fp, const RSA *x, int off)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
RSAerror(ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = RSA_print(b, x, off);
|
||||
BIO_free(b);
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_print_fp);
|
||||
|
||||
int
|
||||
RSA_print(BIO *bp, const RSA *x, int off)
|
||||
{
|
||||
EVP_PKEY *pk;
|
||||
int ret = 0;
|
||||
|
||||
if ((pk = EVP_PKEY_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EVP_PKEY_set1_RSA(pk, (RSA *)x))
|
||||
goto err;
|
||||
|
||||
ret = EVP_PKEY_print_private(bp, pk, off, NULL);
|
||||
err:
|
||||
EVP_PKEY_free(pk);
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_print);
|
288
crypto/rsa/rsa_pss.c
Normal file
288
crypto/rsa/rsa_pss.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/* $OpenBSD: rsa_pss.c,v 1.17 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "evp_local.h"
|
||||
#include "rsa_local.h"
|
||||
|
||||
static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_verify_PKCS1_PSS);
|
||||
|
||||
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;
|
||||
unsigned char H_[EVP_MAX_MD_SIZE];
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
if (mgf1Hash == NULL)
|
||||
mgf1Hash = Hash;
|
||||
|
||||
hLen = EVP_MD_size(Hash);
|
||||
if (hLen < 0)
|
||||
goto err;
|
||||
/*
|
||||
* Negative sLen has special meanings:
|
||||
* -1 sLen == hLen
|
||||
* -2 salt length is autorecovered from signature
|
||||
* -N reserved
|
||||
*/
|
||||
if (sLen == -1)
|
||||
sLen = hLen;
|
||||
else if (sLen == -2)
|
||||
sLen = -2;
|
||||
else if (sLen < -2) {
|
||||
RSAerror(RSA_R_SLEN_CHECK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
|
||||
emLen = RSA_size(rsa);
|
||||
if (EM[0] & (0xFF << MSBits)) {
|
||||
RSAerror(RSA_R_FIRST_OCTET_INVALID);
|
||||
goto err;
|
||||
}
|
||||
if (MSBits == 0) {
|
||||
EM++;
|
||||
emLen--;
|
||||
}
|
||||
if (emLen < (hLen + sLen + 2)) {
|
||||
/* sLen can be small negative */
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
if (EM[emLen - 1] != 0xbc) {
|
||||
RSAerror(RSA_R_LAST_OCTET_INVALID);
|
||||
goto err;
|
||||
}
|
||||
maskedDBLen = emLen - hLen - 1;
|
||||
H = EM + maskedDBLen;
|
||||
DB = malloc(maskedDBLen);
|
||||
if (!DB) {
|
||||
RSAerror(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) {
|
||||
RSAerror(RSA_R_SLEN_RECOVERY_FAILED);
|
||||
goto err;
|
||||
}
|
||||
if (sLen >= 0 && (maskedDBLen - i) != sLen) {
|
||||
RSAerror(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 (timingsafe_bcmp(H_, H, hLen)) {
|
||||
RSAerror(RSA_R_BAD_SIGNATURE);
|
||||
ret = 0;
|
||||
} else
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
free(DB);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_verify_PKCS1_PSS_mgf1);
|
||||
|
||||
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);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_PKCS1_PSS);
|
||||
|
||||
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;
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
|
||||
if (mgf1Hash == NULL)
|
||||
mgf1Hash = Hash;
|
||||
|
||||
hLen = EVP_MD_size(Hash);
|
||||
if (hLen < 0)
|
||||
goto err;
|
||||
/*
|
||||
* Negative sLen has special meanings:
|
||||
* -1 sLen == hLen
|
||||
* -2 salt length is maximized
|
||||
* -N reserved
|
||||
*/
|
||||
if (sLen == -1)
|
||||
sLen = hLen;
|
||||
else if (sLen == -2)
|
||||
sLen = -2;
|
||||
else if (sLen < -2) {
|
||||
RSAerror(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 (sLen == -2)
|
||||
sLen = emLen - hLen - 2;
|
||||
else if (emLen < (hLen + sLen + 2)) {
|
||||
RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
|
||||
goto err;
|
||||
}
|
||||
if (sLen > 0) {
|
||||
salt = malloc(sLen);
|
||||
if (!salt) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
arc4random_buf(salt, sLen);
|
||||
}
|
||||
maskedDBLen = emLen - hLen - 1;
|
||||
H = EM + maskedDBLen;
|
||||
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:
|
||||
free(salt);
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_padding_add_PKCS1_PSS_mgf1);
|
143
crypto/rsa/rsa_saos.c
Normal file
143
crypto/rsa/rsa_saos.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/* $OpenBSD: rsa_saos.c,v 1.25 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/rsa.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)) {
|
||||
RSAerror(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
|
||||
return 0;
|
||||
}
|
||||
s = malloc(j + 1);
|
||||
if (s == NULL) {
|
||||
RSAerror(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;
|
||||
|
||||
freezero(s, (unsigned int)j + 1);
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_sign_ASN1_OCTET_STRING);
|
||||
|
||||
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)) {
|
||||
RSAerror(RSA_R_WRONG_SIGNATURE_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = malloc(siglen);
|
||||
if (s == NULL) {
|
||||
RSAerror(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 ||
|
||||
timingsafe_bcmp(m, sig->data, m_len) != 0) {
|
||||
RSAerror(RSA_R_BAD_SIGNATURE);
|
||||
} else
|
||||
ret = 1;
|
||||
err:
|
||||
ASN1_OCTET_STRING_free(sig);
|
||||
freezero(s, (unsigned int)siglen);
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_verify_ASN1_OCTET_STRING);
|
280
crypto/rsa/rsa_sign.c
Normal file
280
crypto/rsa/rsa_sign.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/* $OpenBSD: rsa_sign.c,v 1.36 2023/07/08 12:26:45 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "asn1_local.h"
|
||||
#include "rsa_local.h"
|
||||
#include "x509_local.h"
|
||||
|
||||
/* Size of an SSL signature: MD5+SHA1 */
|
||||
#define SSL_SIG_LENGTH 36
|
||||
|
||||
static int encode_pkcs1(unsigned char **, int *, int , const unsigned char *,
|
||||
unsigned int);
|
||||
|
||||
/*
|
||||
* encode_pkcs1 encodes a DigestInfo prefix of hash `type' and digest `m', as
|
||||
* described in EMSA-PKCS-v1_5-ENCODE, RFC 8017 section 9. 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. Freeing `*out' is
|
||||
* the caller's responsibility. Failure is indicated by 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;
|
||||
if ((sig.algor->algorithm = OBJ_nid2obj(type)) == NULL) {
|
||||
RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (sig.algor->algorithm->length == 0) {
|
||||
RSAerror(
|
||||
RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
|
||||
return 0;
|
||||
}
|
||||
parameter.type = V_ASN1_NULL;
|
||||
parameter.value.ptr = NULL;
|
||||
sig.algor->parameter = ¶meter;
|
||||
|
||||
sig.digest = &digest;
|
||||
sig.digest->data = (unsigned char *)m; /* TMP UGLY CAST */
|
||||
sig.digest->length = m_len;
|
||||
|
||||
if ((len = i2d_X509_SIG(&sig, &der)) < 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)
|
||||
{
|
||||
const unsigned char *encoded = NULL;
|
||||
unsigned char *tmps = NULL;
|
||||
int encrypt_len, encoded_len = 0, ret = 0;
|
||||
|
||||
if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign != NULL)
|
||||
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-PKCS-v1.5.
|
||||
*/
|
||||
if (m_len != SSL_SIG_LENGTH) {
|
||||
RSAerror(RSA_R_INVALID_DIGEST_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) {
|
||||
RSAerror(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
|
||||
goto err;
|
||||
}
|
||||
if ((encrypt_len = RSA_private_encrypt(encoded_len, encoded, sigret,
|
||||
rsa, RSA_PKCS1_PADDING)) <= 0)
|
||||
goto err;
|
||||
|
||||
*siglen = encrypt_len;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
freezero(tmps, (size_t)encoded_len);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_sign);
|
||||
|
||||
/*
|
||||
* 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 the
|
||||
* 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)
|
||||
{
|
||||
unsigned char *decrypt_buf, *encoded = NULL;
|
||||
int decrypt_len, encoded_len = 0, ret = 0;
|
||||
|
||||
if (siglen != (size_t)RSA_size(rsa)) {
|
||||
RSAerror(RSA_R_WRONG_SIGNATURE_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Recover the encoded digest. */
|
||||
if ((decrypt_buf = malloc(siglen)) == NULL) {
|
||||
RSAerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if ((decrypt_len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf,
|
||||
rsa, RSA_PKCS1_PADDING)) <= 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) {
|
||||
RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rm != NULL) {
|
||||
memcpy(rm, decrypt_buf, SSL_SIG_LENGTH);
|
||||
*prm_len = SSL_SIG_LENGTH;
|
||||
} else {
|
||||
if (m_len != SSL_SIG_LENGTH) {
|
||||
RSAerror(RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
if (timingsafe_bcmp(decrypt_buf,
|
||||
m, SSL_SIG_LENGTH) != 0) {
|
||||
RSAerror(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;
|
||||
|
||||
if ((md = EVP_get_digestbynid(type)) == NULL) {
|
||||
RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE);
|
||||
goto err;
|
||||
}
|
||||
if ((m_len = EVP_MD_size(md)) > (size_t)decrypt_len) {
|
||||
RSAerror(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 ||
|
||||
timingsafe_bcmp(encoded, decrypt_buf, encoded_len) != 0) {
|
||||
RSAerror(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:
|
||||
freezero(encoded, (size_t)encoded_len);
|
||||
freezero(decrypt_buf, siglen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
|
||||
const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
|
||||
{
|
||||
if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify)
|
||||
return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen,
|
||||
rsa);
|
||||
|
||||
return int_rsa_verify(dtype, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
|
||||
}
|
||||
LCRYPTO_ALIAS(RSA_verify);
|
164
crypto/rsa/rsa_x931.c
Normal file
164
crypto/rsa/rsa_x931.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* $OpenBSD: rsa_x931.c,v 1.12 2023/05/05 12:19:37 tb Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/rsa.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) {
|
||||
RSAerror(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, 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 = from;
|
||||
|
||||
if (num != flen || (*p != 0x6A && *p != 0x6B)) {
|
||||
RSAerror(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) {
|
||||
RSAerror(RSA_R_INVALID_PADDING);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
RSAerror(RSA_R_INVALID_PADDING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
j -= i;
|
||||
} else
|
||||
j = flen - 2;
|
||||
|
||||
if (j < 0 || p[j] != 0xCC) {
|
||||
RSAerror(RSA_R_INVALID_TRAILER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(to, p, 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;
|
||||
}
|
Reference in New Issue
Block a user