Latest update.
This commit is contained in:
@@ -50,6 +50,7 @@ int ERR_load_PROV_strings(void);
|
||||
* PROV reason codes.
|
||||
*/
|
||||
# define PROV_R_AES_KEY_SETUP_FAILED 101
|
||||
# define PROV_R_ALGORITHM_MISMATCH 173
|
||||
# define PROV_R_BAD_DECRYPT 100
|
||||
# define PROV_R_BAD_ENCODING 141
|
||||
# define PROV_R_BAD_LENGTH 142
|
||||
@@ -57,17 +58,20 @@ int ERR_load_PROV_strings(void);
|
||||
# define PROV_R_BN_ERROR 160
|
||||
# define PROV_R_BOTH_MODE_AND_MODE_INT 127
|
||||
# define PROV_R_CIPHER_OPERATION_FAILED 102
|
||||
# define PROV_R_DIGEST_NOT_ALLOWED 174
|
||||
# define PROV_R_FAILED_DURING_DERIVATION 164
|
||||
# define PROV_R_FAILED_TO_DECRYPT 162
|
||||
# define PROV_R_FAILED_TO_GENERATE_KEY 121
|
||||
# define PROV_R_FAILED_TO_GET_PARAMETER 103
|
||||
# define PROV_R_FAILED_TO_SET_PARAMETER 104
|
||||
# define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165
|
||||
# define PROV_R_INAVLID_UKM_LENGTH 146
|
||||
# define PROV_R_INVALID_AAD 108
|
||||
# define PROV_R_INVALID_CONSTANT_LENGTH 157
|
||||
# define PROV_R_INVALID_CUSTOM_LENGTH 111
|
||||
# define PROV_R_INVALID_DATA 115
|
||||
# define PROV_R_INVALID_DIGEST 122
|
||||
# define PROV_R_INVALID_DIGEST_LENGTH 166
|
||||
# define PROV_R_INVALID_ITERATION_COUNT 123
|
||||
# define PROV_R_INVALID_IVLEN 116
|
||||
# define PROV_R_INVALID_IV_LENGTH 109
|
||||
@@ -76,12 +80,17 @@ int ERR_load_PROV_strings(void);
|
||||
# define PROV_R_INVALID_KEY_LEN 124
|
||||
# define PROV_R_INVALID_KEY_LENGTH 105
|
||||
# define PROV_R_INVALID_MAC 151
|
||||
# define PROV_R_INVALID_MGF1_MD 167
|
||||
# define PROV_R_INVALID_MODE 125
|
||||
# define PROV_R_INVALID_MODE_INT 126
|
||||
# define PROV_R_INVALID_PADDING_MODE 168
|
||||
# define PROV_R_INVALID_PSS_SALTLEN 169
|
||||
# define PROV_R_INVALID_SALT_LENGTH 112
|
||||
# define PROV_R_INVALID_SEED_LENGTH 154
|
||||
# define PROV_R_INVALID_TAG 110
|
||||
# define PROV_R_INVALID_TAGLEN 118
|
||||
# define PROV_R_INVALID_X931_DIGEST 170
|
||||
# define PROV_R_KEY_SIZE_TOO_SMALL 171
|
||||
# define PROV_R_MISSING_CEK_ALG 144
|
||||
# define PROV_R_MISSING_CIPHER 155
|
||||
# define PROV_R_MISSING_CONSTANT 156
|
||||
@@ -99,6 +108,7 @@ int ERR_load_PROV_strings(void);
|
||||
# define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113
|
||||
# define PROV_R_NO_KEY_SET 114
|
||||
# define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106
|
||||
# define PROV_R_PSS_SALTLEN_TOO_SMALL 172
|
||||
# define PROV_R_READ_KEY 159
|
||||
# define PROV_R_TAG_NOTSET 119
|
||||
# define PROV_R_TAG_NOT_NEEDED 120
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_AES_KEY_SETUP_FAILED),
|
||||
"aes key setup failed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ALGORITHM_MISMATCH),
|
||||
"algorithm mismatch"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_ENCODING), "bad encoding"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_LENGTH), "bad length"},
|
||||
@@ -26,6 +28,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
"both mode and mode int"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED),
|
||||
"cipher operation failed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DIGEST_NOT_ALLOWED),
|
||||
"digest not allowed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_DURING_DERIVATION),
|
||||
"failed during derivation"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_DECRYPT), "failed to decrypt"},
|
||||
@@ -35,6 +39,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
"failed to get parameter"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER),
|
||||
"failed to set parameter"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE),
|
||||
"illegal or unsupported padding mode"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INAVLID_UKM_LENGTH),
|
||||
"inavlid ukm length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"},
|
||||
@@ -44,6 +50,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
"invalid custom length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_LENGTH),
|
||||
"invalid digest length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
|
||||
"invalid iteration count"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IVLEN), "invalid ivlen"},
|
||||
@@ -54,14 +62,23 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH),
|
||||
"invalid key length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MAC), "invalid mac"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MGF1_MD), "invalid mgf1 md"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE), "invalid mode"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE_INT), "invalid mode int"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PADDING_MODE),
|
||||
"invalid padding mode"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PSS_SALTLEN),
|
||||
"invalid pss saltlen"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH),
|
||||
"invalid salt length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SEED_LENGTH),
|
||||
"invalid seed length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAGLEN), "invalid taglen"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_X931_DIGEST),
|
||||
"invalid x931 digest"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL),
|
||||
"key size too small"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CIPHER), "missing cipher"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONSTANT), "missing constant"},
|
||||
@@ -83,6 +100,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL),
|
||||
"output buffer too small"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PSS_SALTLEN_TOO_SMALL),
|
||||
"pss saltlen too small"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_READ_KEY), "read key"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOTSET), "tag notset"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"},
|
||||
|
||||
+110
-74
@@ -20,7 +20,7 @@
|
||||
#include "prov/provider_util.h"
|
||||
#include "internal/nelem.h"
|
||||
|
||||
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "default=yes", FUNC }, CHECK }
|
||||
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "provider=default", FUNC }, CHECK }
|
||||
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
|
||||
|
||||
/* Functions provided by the core */
|
||||
@@ -86,32 +86,32 @@ static int deflt_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
|
||||
*/
|
||||
static const OSSL_ALGORITHM deflt_digests[] = {
|
||||
/* Our primary name:NIST name[:our older names] */
|
||||
{ "SHA1:SHA-1", "default=yes", sha1_functions },
|
||||
{ "SHA2-224:SHA-224:SHA224", "default=yes", sha224_functions },
|
||||
{ "SHA2-256:SHA-256:SHA256", "default=yes", sha256_functions },
|
||||
{ "SHA2-384:SHA-384:SHA384", "default=yes", sha384_functions },
|
||||
{ "SHA2-512:SHA-512:SHA512", "default=yes", sha512_functions },
|
||||
{ "SHA2-512/224:SHA-512/224:SHA512-224", "default=yes",
|
||||
{ "SHA1:SHA-1", "provider=default", sha1_functions },
|
||||
{ "SHA2-224:SHA-224:SHA224", "provider=default", sha224_functions },
|
||||
{ "SHA2-256:SHA-256:SHA256", "provider=default", sha256_functions },
|
||||
{ "SHA2-384:SHA-384:SHA384", "provider=default", sha384_functions },
|
||||
{ "SHA2-512:SHA-512:SHA512", "provider=default", sha512_functions },
|
||||
{ "SHA2-512/224:SHA-512/224:SHA512-224", "provider=default",
|
||||
sha512_224_functions },
|
||||
{ "SHA2-512/256:SHA-512/256:SHA512-256", "default=yes",
|
||||
{ "SHA2-512/256:SHA-512/256:SHA512-256", "provider=default",
|
||||
sha512_256_functions },
|
||||
|
||||
/* We agree with NIST here, so one name only */
|
||||
{ "SHA3-224", "default=yes", sha3_224_functions },
|
||||
{ "SHA3-256", "default=yes", sha3_256_functions },
|
||||
{ "SHA3-384", "default=yes", sha3_384_functions },
|
||||
{ "SHA3-512", "default=yes", sha3_512_functions },
|
||||
{ "SHA3-224", "provider=default", sha3_224_functions },
|
||||
{ "SHA3-256", "provider=default", sha3_256_functions },
|
||||
{ "SHA3-384", "provider=default", sha3_384_functions },
|
||||
{ "SHA3-512", "provider=default", sha3_512_functions },
|
||||
|
||||
/*
|
||||
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
|
||||
* the KMAC-128 and KMAC-256.
|
||||
*/
|
||||
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "default=yes", keccak_kmac_128_functions },
|
||||
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "default=yes", keccak_kmac_256_functions },
|
||||
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "provider=default", keccak_kmac_128_functions },
|
||||
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "provider=default", keccak_kmac_256_functions },
|
||||
|
||||
/* Our primary name:NIST name */
|
||||
{ "SHAKE-128:SHAKE128", "default=yes", shake_128_functions },
|
||||
{ "SHAKE-256:SHAKE256", "default=yes", shake_256_functions },
|
||||
{ "SHAKE-128:SHAKE128", "provider=default", shake_128_functions },
|
||||
{ "SHAKE-256:SHAKE256", "provider=default", shake_256_functions },
|
||||
|
||||
#ifndef OPENSSL_NO_BLAKE2
|
||||
/*
|
||||
@@ -121,17 +121,17 @@ static const OSSL_ALGORITHM deflt_digests[] = {
|
||||
* If we assume that "2b" and "2s" are versions, that pattern
|
||||
* fits with ours. We also add our historical names.
|
||||
*/
|
||||
{ "BLAKE2S-256:BLAKE2s256", "default=yes", blake2s256_functions },
|
||||
{ "BLAKE2B-512:BLAKE2b512", "default=yes", blake2b512_functions },
|
||||
{ "BLAKE2S-256:BLAKE2s256", "provider=default", blake2s256_functions },
|
||||
{ "BLAKE2B-512:BLAKE2b512", "provider=default", blake2b512_functions },
|
||||
#endif /* OPENSSL_NO_BLAKE2 */
|
||||
|
||||
#ifndef OPENSSL_NO_SM3
|
||||
{ "SM3", "default=yes", sm3_functions },
|
||||
{ "SM3", "provider=default", sm3_functions },
|
||||
#endif /* OPENSSL_NO_SM3 */
|
||||
|
||||
#ifndef OPENSSL_NO_MD5
|
||||
{ "MD5", "default=yes", md5_functions },
|
||||
{ "MD5-SHA1", "default=yes", md5_sha1_functions },
|
||||
{ "MD5", "provider=default", md5_functions },
|
||||
{ "MD5-SHA1", "provider=default", md5_sha1_functions },
|
||||
#endif /* OPENSSL_NO_MD5 */
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
@@ -331,137 +331,173 @@ static OSSL_ALGORITHM exported_ciphers[OSSL_NELEM(deflt_ciphers)];
|
||||
|
||||
static const OSSL_ALGORITHM deflt_macs[] = {
|
||||
#ifndef OPENSSL_NO_BLAKE2
|
||||
{ "BLAKE2BMAC", "default=yes", blake2bmac_functions },
|
||||
{ "BLAKE2SMAC", "default=yes", blake2smac_functions },
|
||||
{ "BLAKE2BMAC", "provider=default", blake2bmac_functions },
|
||||
{ "BLAKE2SMAC", "provider=default", blake2smac_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
{ "CMAC", "default=yes", cmac_functions },
|
||||
{ "CMAC", "provider=default", cmac_functions },
|
||||
#endif
|
||||
{ "GMAC", "default=yes", gmac_functions },
|
||||
{ "HMAC", "default=yes", hmac_functions },
|
||||
{ "KMAC-128:KMAC128", "default=yes", kmac128_functions },
|
||||
{ "KMAC-256:KMAC256", "default=yes", kmac256_functions },
|
||||
{ "GMAC", "provider=default", gmac_functions },
|
||||
{ "HMAC", "provider=default", hmac_functions },
|
||||
{ "KMAC-128:KMAC128", "provider=default", kmac128_functions },
|
||||
{ "KMAC-256:KMAC256", "provider=default", kmac256_functions },
|
||||
#ifndef OPENSSL_NO_SIPHASH
|
||||
{ "SIPHASH", "default=yes", siphash_functions },
|
||||
{ "SIPHASH", "provider=default", siphash_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_POLY1305
|
||||
{ "POLY1305", "default=yes", poly1305_functions },
|
||||
{ "POLY1305", "provider=default", poly1305_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_kdfs[] = {
|
||||
{ "HKDF", "default=yes", kdf_hkdf_functions },
|
||||
{ "SSKDF", "default=yes", kdf_sskdf_functions },
|
||||
{ "PBKDF2", "default=yes", kdf_pbkdf2_functions },
|
||||
{ "SSHKDF", "default=yes", kdf_sshkdf_functions },
|
||||
{ "X963KDF", "default=yes", kdf_x963_kdf_functions },
|
||||
{ "TLS1-PRF", "default=yes", kdf_tls1_prf_functions },
|
||||
{ "KBKDF", "default=yes", kdf_kbkdf_functions },
|
||||
{ "HKDF", "provider=default", kdf_hkdf_functions },
|
||||
{ "SSKDF", "provider=default", kdf_sskdf_functions },
|
||||
{ "PBKDF2", "provider=default", kdf_pbkdf2_functions },
|
||||
{ "SSHKDF", "provider=default", kdf_sshkdf_functions },
|
||||
{ "X963KDF", "provider=default", kdf_x963_kdf_functions },
|
||||
{ "TLS1-PRF", "provider=default", kdf_tls1_prf_functions },
|
||||
{ "KBKDF", "provider=default", kdf_kbkdf_functions },
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
{ "X942KDF", "default=yes", kdf_x942_kdf_functions },
|
||||
{ "X942KDF", "provider=default", kdf_x942_kdf_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SCRYPT
|
||||
{ "SCRYPT:id-scrypt", "default=yes", kdf_scrypt_functions },
|
||||
{ "SCRYPT:id-scrypt", "provider=default", kdf_scrypt_functions },
|
||||
#endif
|
||||
{ "KRB5KDF", "default=yes", kdf_krb5kdf_functions },
|
||||
{ "KRB5KDF", "provider=default", kdf_krb5kdf_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_keyexch[] = {
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "DH:dhKeyAgreement", "default=yes", dh_keyexch_functions },
|
||||
{ "DH:dhKeyAgreement", "provider=default", dh_keyexch_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
{ "X25519", "default=yes", x25519_keyexch_functions },
|
||||
{ "X448", "default=yes", x448_keyexch_functions },
|
||||
{ "ECDH:id-ecPublicKey", "provider=default", ecdh_keyexch_functions },
|
||||
{ "X25519", "provider=default", x25519_keyexch_functions },
|
||||
{ "X448", "provider=default", x448_keyexch_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_signature[] = {
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
{ "DSA:dsaEncryption", "default=yes", dsa_signature_functions },
|
||||
{ "DSA:dsaEncryption", "provider=default", dsa_signature_functions },
|
||||
#endif
|
||||
{ "RSA:rsaEncryption", "provider=default", rsa_signature_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_asym_cipher[] = {
|
||||
{ "RSA:rsaEncryption", "default=yes", rsa_asym_cipher_functions },
|
||||
{ "RSA:rsaEncryption", "provider=default", rsa_asym_cipher_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_keymgmt[] = {
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "DH:dhKeyAgreement", "default=yes", dh_keymgmt_functions },
|
||||
{ "DH:dhKeyAgreement", "provider=default", dh_keymgmt_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
{ "DSA:dsaEncryption", "default=yes", dsa_keymgmt_functions },
|
||||
{ "DSA:dsaEncryption", "provider=default", dsa_keymgmt_functions },
|
||||
#endif
|
||||
{ "RSA:rsaEncryption", "default=yes", rsa_keymgmt_functions },
|
||||
{ "RSA:rsaEncryption", "provider=default", rsa_keymgmt_functions },
|
||||
#ifndef OPENSSL_NO_EC
|
||||
{ "X25519", "default=yes", x25519_keymgmt_functions },
|
||||
{ "X448", "default=yes", x448_keymgmt_functions },
|
||||
{ "EC:id-ecPublicKey", "provider=default", ec_keymgmt_functions },
|
||||
{ "X25519", "provider=default", x25519_keymgmt_functions },
|
||||
{ "X448", "provider=default", x448_keymgmt_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* Unlike most algorithms in the default provider, the serializers are allowed
|
||||
* for use in FIPS mode because they are not FIPS relevant, and therefore have
|
||||
* the "fips=yes" property.
|
||||
*/
|
||||
static const OSSL_ALGORITHM deflt_serializer[] = {
|
||||
{ "RSA", "default=yes,format=text,type=private",
|
||||
{ "RSA", "provider=default,fips=yes,format=text,type=private",
|
||||
rsa_priv_text_serializer_functions },
|
||||
{ "RSA", "default=yes,format=text,type=public",
|
||||
{ "RSA", "provider=default,fips=yes,format=text,type=public",
|
||||
rsa_pub_text_serializer_functions },
|
||||
{ "RSA", "default=yes,format=der,type=private",
|
||||
{ "RSA", "provider=default,fips=yes,format=der,type=private",
|
||||
rsa_priv_der_serializer_functions },
|
||||
{ "RSA", "default=yes,format=der,type=public",
|
||||
{ "RSA", "provider=default,fips=yes,format=der,type=public",
|
||||
rsa_pub_der_serializer_functions },
|
||||
{ "RSA", "default=yes,format=pem,type=private",
|
||||
{ "RSA", "provider=default,fips=yes,format=pem,type=private",
|
||||
rsa_priv_pem_serializer_functions },
|
||||
{ "RSA", "default=yes,format=pem,type=public",
|
||||
{ "RSA", "provider=default,fips=yes,format=pem,type=public",
|
||||
rsa_pub_pem_serializer_functions },
|
||||
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "DH", "default=yes,format=text,type=private",
|
||||
{ "DH", "provider=default,fips=yes,format=text,type=private",
|
||||
dh_priv_text_serializer_functions },
|
||||
{ "DH", "default=yes,format=text,type=public",
|
||||
{ "DH", "provider=default,fips=yes,format=text,type=public",
|
||||
dh_pub_text_serializer_functions },
|
||||
{ "DH", "default=yes,format=text,type=parameters",
|
||||
{ "DH", "provider=default,fips=yes,format=text,type=parameters",
|
||||
dh_param_text_serializer_functions },
|
||||
{ "DH", "default=yes,format=der,type=private",
|
||||
{ "DH", "provider=default,fips=yes,format=der,type=private",
|
||||
dh_priv_der_serializer_functions },
|
||||
{ "DH", "default=yes,format=der,type=public",
|
||||
{ "DH", "provider=default,fips=yes,format=der,type=public",
|
||||
dh_pub_der_serializer_functions },
|
||||
{ "DH", "default=yes,format=der,type=parameters",
|
||||
{ "DH", "provider=default,fips=yes,format=der,type=parameters",
|
||||
dh_param_der_serializer_functions },
|
||||
{ "DH", "default=yes,format=pem,type=private",
|
||||
{ "DH", "provider=default,fips=yes,format=pem,type=private",
|
||||
dh_priv_pem_serializer_functions },
|
||||
{ "DH", "default=yes,format=pem,type=public",
|
||||
{ "DH", "provider=default,fips=yes,format=pem,type=public",
|
||||
dh_pub_pem_serializer_functions },
|
||||
{ "DH", "default=yes,format=pem,type=parameters",
|
||||
{ "DH", "provider=default,fips=yes,format=pem,type=parameters",
|
||||
dh_param_pem_serializer_functions },
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
{ "DSA", "default=yes,format=text,type=private",
|
||||
{ "DSA", "provider=default,fips=yes,format=text,type=private",
|
||||
dsa_priv_text_serializer_functions },
|
||||
{ "DSA", "default=yes,format=text,type=public",
|
||||
{ "DSA", "provider=default,fips=yes,format=text,type=public",
|
||||
dsa_pub_text_serializer_functions },
|
||||
{ "DSA", "default=yes,format=text,type=parameters",
|
||||
{ "DSA", "provider=default,fips=yes,format=text,type=parameters",
|
||||
dsa_param_text_serializer_functions },
|
||||
{ "DSA", "default=yes,format=der,type=private",
|
||||
{ "DSA", "provider=default,fips=yes,format=der,type=private",
|
||||
dsa_priv_der_serializer_functions },
|
||||
{ "DSA", "default=yes,format=der,type=public",
|
||||
{ "DSA", "provider=default,fips=yes,format=der,type=public",
|
||||
dsa_pub_der_serializer_functions },
|
||||
{ "DSA", "default=yes,format=der,type=parameters",
|
||||
{ "DSA", "provider=default,fips=yes,format=der,type=parameters",
|
||||
dsa_param_der_serializer_functions },
|
||||
{ "DSA", "default=yes,format=pem,type=private",
|
||||
{ "DSA", "provider=default,fips=yes,format=pem,type=private",
|
||||
dsa_priv_pem_serializer_functions },
|
||||
{ "DSA", "default=yes,format=pem,type=public",
|
||||
{ "DSA", "provider=default,fips=yes,format=pem,type=public",
|
||||
dsa_pub_pem_serializer_functions },
|
||||
{ "DSA", "default=yes,format=pem,type=parameters",
|
||||
{ "DSA", "provider=default,fips=yes,format=pem,type=parameters",
|
||||
dsa_param_pem_serializer_functions },
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
{ "X25519", "provider=default,format=text,type=private",
|
||||
x25519_priv_print_serializer_functions },
|
||||
{ "X25519", "provider=default,format=text,type=public",
|
||||
x25519_pub_print_serializer_functions },
|
||||
{ "X25519", "provider=default,format=der,type=private",
|
||||
x25519_priv_der_serializer_functions },
|
||||
{ "X25519", "provider=default,format=der,type=public",
|
||||
x25519_pub_der_serializer_functions },
|
||||
{ "X25519", "provider=default,format=pem,type=private",
|
||||
x25519_priv_pem_serializer_functions },
|
||||
{ "X25519", "provider=default,format=pem,type=public",
|
||||
x25519_pub_pem_serializer_functions },
|
||||
|
||||
{ "X448", "provider=default,format=text,type=private",
|
||||
x448_priv_print_serializer_functions },
|
||||
{ "X448", "provider=default,format=text,type=public",
|
||||
x448_pub_print_serializer_functions },
|
||||
{ "X448", "provider=default,format=der,type=private",
|
||||
x448_priv_der_serializer_functions },
|
||||
{ "X448", "provider=default,format=der,type=public",
|
||||
x448_pub_der_serializer_functions },
|
||||
{ "X448", "provider=default,format=pem,type=private",
|
||||
x448_priv_pem_serializer_functions },
|
||||
{ "X448", "provider=default,format=pem,type=public",
|
||||
x448_pub_pem_serializer_functions },
|
||||
#endif
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c self_test_event.c
|
||||
SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c
|
||||
INCLUDE[../fips]=../implementations/include ../common/include ../..
|
||||
+34
-34
@@ -34,7 +34,7 @@
|
||||
#include "prov/provider_util.h"
|
||||
#include "self_test.h"
|
||||
|
||||
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "fips=yes", FUNC }, CHECK }
|
||||
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "provider=fips,fips=yes", FUNC }, CHECK }
|
||||
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
|
||||
|
||||
extern OSSL_core_thread_start_fn *c_thread_start;
|
||||
@@ -702,27 +702,27 @@ const char *ossl_prov_util_nid_to_name(int nid)
|
||||
*/
|
||||
static const OSSL_ALGORITHM fips_digests[] = {
|
||||
/* Our primary name:NiST name[:our older names] */
|
||||
{ "SHA1:SHA-1", "fips=yes", sha1_functions },
|
||||
{ "SHA2-224:SHA-224:SHA224", "fips=yes", sha224_functions },
|
||||
{ "SHA2-256:SHA-256:SHA256", "fips=yes", sha256_functions },
|
||||
{ "SHA2-384:SHA-384:SHA384", "fips=yes", sha384_functions },
|
||||
{ "SHA2-512:SHA-512:SHA512", "fips=yes", sha512_functions },
|
||||
{ "SHA2-512/224:SHA-512/224:SHA512-224", "fips=yes",
|
||||
{ "SHA1:SHA-1", "provider=fips,fips=yes", sha1_functions },
|
||||
{ "SHA2-224:SHA-224:SHA224", "provider=fips,fips=yes", sha224_functions },
|
||||
{ "SHA2-256:SHA-256:SHA256", "provider=fips,fips=yes", sha256_functions },
|
||||
{ "SHA2-384:SHA-384:SHA384", "provider=fips,fips=yes", sha384_functions },
|
||||
{ "SHA2-512:SHA-512:SHA512", "provider=fips,fips=yes", sha512_functions },
|
||||
{ "SHA2-512/224:SHA-512/224:SHA512-224", "provider=fips,fips=yes",
|
||||
sha512_224_functions },
|
||||
{ "SHA2-512/256:SHA-512/256:SHA512-256", "fips=yes",
|
||||
{ "SHA2-512/256:SHA-512/256:SHA512-256", "provider=fips,fips=yes",
|
||||
sha512_256_functions },
|
||||
|
||||
/* We agree with NIST here, so one name only */
|
||||
{ "SHA3-224", "fips=yes", sha3_224_functions },
|
||||
{ "SHA3-256", "fips=yes", sha3_256_functions },
|
||||
{ "SHA3-384", "fips=yes", sha3_384_functions },
|
||||
{ "SHA3-512", "fips=yes", sha3_512_functions },
|
||||
{ "SHA3-224", "provider=fips,fips=yes", sha3_224_functions },
|
||||
{ "SHA3-256", "provider=fips,fips=yes", sha3_256_functions },
|
||||
{ "SHA3-384", "provider=fips,fips=yes", sha3_384_functions },
|
||||
{ "SHA3-512", "provider=fips,fips=yes", sha3_512_functions },
|
||||
/*
|
||||
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
|
||||
* KMAC128 and KMAC256.
|
||||
*/
|
||||
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "fips=yes", keccak_kmac_128_functions },
|
||||
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "fips=yes", keccak_kmac_256_functions },
|
||||
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "provider=fips,fips=yes", keccak_kmac_128_functions },
|
||||
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "provider=fips,fips=yes", keccak_kmac_256_functions },
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
@@ -773,51 +773,51 @@ static OSSL_ALGORITHM exported_fips_ciphers[OSSL_NELEM(fips_ciphers)];
|
||||
|
||||
static const OSSL_ALGORITHM fips_macs[] = {
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
{ "CMAC", "fips=yes", cmac_functions },
|
||||
{ "CMAC", "provider=fips,fips=yes", cmac_functions },
|
||||
#endif
|
||||
{ "GMAC", "fips=yes", gmac_functions },
|
||||
{ "HMAC", "fips=yes", hmac_functions },
|
||||
{ "KMAC-128:KMAC128", "fips=yes", kmac128_functions },
|
||||
{ "KMAC-256:KMAC256", "fips=yes", kmac256_functions },
|
||||
{ "GMAC", "provider=fips,fips=yes", gmac_functions },
|
||||
{ "HMAC", "provider=fips,fips=yes", hmac_functions },
|
||||
{ "KMAC-128:KMAC128", "provider=fips,fips=yes", kmac128_functions },
|
||||
{ "KMAC-256:KMAC256", "provider=fips,fips=yes", kmac256_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM fips_kdfs[] = {
|
||||
{ "HKDF", "fips=yes", kdf_hkdf_functions },
|
||||
{ "SSKDF", "fips=yes", kdf_sskdf_functions },
|
||||
{ "PBKDF2", "fips=yes", kdf_pbkdf2_functions },
|
||||
{ "TLS1-PRF", "fips=yes", kdf_tls1_prf_functions },
|
||||
{ "KBKDF", "fips=yes", kdf_kbkdf_functions },
|
||||
{ "HKDF", "provider=fips,fips=yes", kdf_hkdf_functions },
|
||||
{ "SSKDF", "provider=fips,fips=yes", kdf_sskdf_functions },
|
||||
{ "PBKDF2", "provider=fips,fips=yes", kdf_pbkdf2_functions },
|
||||
{ "TLS1-PRF", "provider=fips,fips=yes", kdf_tls1_prf_functions },
|
||||
{ "KBKDF", "provider=fips,fips=yes", kdf_kbkdf_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM fips_keyexch[] = {
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "DH:dhKeyAgreement", "fips=yes", dh_keyexch_functions },
|
||||
{ "DH:dhKeyAgreement", "provider=fips,fips=yes", dh_keyexch_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM fips_signature[] = {
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
{ "DSA:dsaEncryption", "fips=yes", dsa_signature_functions },
|
||||
{ "DSA:dsaEncryption", "provider=fips,fips=yes", dsa_signature_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM fips_asym_cipher[] = {
|
||||
{ "RSA:rsaEncryption", "fips=yes", rsa_asym_cipher_functions },
|
||||
{ "RSA:rsaEncryption", "provider=fips,fips=yes", rsa_asym_cipher_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM fips_keymgmt[] = {
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "DH:dhKeyAgreement", "fips=yes", dh_keymgmt_functions },
|
||||
{ "DH:dhKeyAgreement", "provider=fips,fips=yes", dh_keymgmt_functions },
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
{ "DSA", "fips=yes", dsa_keymgmt_functions },
|
||||
{ "DSA", "provider=fips,fips=yes", dsa_keymgmt_functions },
|
||||
#endif
|
||||
{ "RSA:rsaEncryption", "default=yes", rsa_keymgmt_functions },
|
||||
{ "RSA:rsaEncryption", "provider=fips,fips=yes", rsa_keymgmt_functions },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -966,12 +966,12 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
|
||||
}
|
||||
|
||||
if (stcbfn != NULL && c_get_libctx != NULL) {
|
||||
stcbfn(c_get_libctx(provider), &selftest_params.event_cb,
|
||||
&selftest_params.event_cb_arg);
|
||||
stcbfn(c_get_libctx(provider), &selftest_params.cb,
|
||||
&selftest_params.cb_arg);
|
||||
}
|
||||
else {
|
||||
selftest_params.event_cb = NULL;
|
||||
selftest_params.event_cb_arg = NULL;
|
||||
selftest_params.cb = NULL;
|
||||
selftest_params.cb_arg = NULL;
|
||||
}
|
||||
|
||||
if (!c_get_params(provider, core_params))
|
||||
|
||||
@@ -132,7 +132,7 @@ DEP_FINI_ATTRIBUTE void cleanup(void)
|
||||
*/
|
||||
static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
|
||||
unsigned char *expected, size_t expected_len,
|
||||
OPENSSL_CTX *libctx, OSSL_ST_EVENT *ev,
|
||||
OPENSSL_CTX *libctx, OSSL_SELF_TEST *ev,
|
||||
const char *event_type)
|
||||
{
|
||||
int ret = 0, status;
|
||||
@@ -143,7 +143,7 @@ static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
|
||||
EVP_MAC_CTX *ctx = NULL;
|
||||
OSSL_PARAM params[3], *p = params;
|
||||
|
||||
SELF_TEST_EVENT_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
|
||||
OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
|
||||
|
||||
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
|
||||
ctx = EVP_MAC_CTX_new(mac);
|
||||
@@ -170,13 +170,13 @@ static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
|
||||
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
|
||||
goto err;
|
||||
|
||||
SELF_TEST_EVENT_oncorrupt_byte(ev, out);
|
||||
OSSL_SELF_TEST_oncorrupt_byte(ev, out);
|
||||
if (expected_len != out_len
|
||||
|| memcmp(expected, out, out_len) != 0)
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
SELF_TEST_EVENT_onend(ev, ret);
|
||||
OSSL_SELF_TEST_onend(ev, ret);
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
EVP_MAC_free(mac);
|
||||
return ret;
|
||||
@@ -192,7 +192,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|
||||
unsigned char *module_checksum = NULL;
|
||||
unsigned char *indicator_checksum = NULL;
|
||||
int loclstate;
|
||||
OSSL_ST_EVENT ev;
|
||||
OSSL_SELF_TEST *ev = NULL;
|
||||
|
||||
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
|
||||
return 0;
|
||||
@@ -223,7 +223,9 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|
||||
|| st->module_checksum_data == NULL)
|
||||
goto end;
|
||||
|
||||
SELF_TEST_EVENT_init(&ev, st->event_cb, st->event_cb_arg);
|
||||
ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg);
|
||||
if (ev == NULL)
|
||||
goto end;
|
||||
|
||||
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
|
||||
&checksum_len);
|
||||
@@ -235,7 +237,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|
||||
if (bio_module == NULL
|
||||
|| !verify_integrity(bio_module, st->bio_read_ex_cb,
|
||||
module_checksum, checksum_len, st->libctx,
|
||||
&ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
|
||||
ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
|
||||
goto end;
|
||||
|
||||
/* This will be NULL during installation - so the self test KATS will run */
|
||||
@@ -257,7 +259,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|
||||
if (bio_indicator == NULL
|
||||
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
|
||||
indicator_checksum, checksum_len,
|
||||
st->libctx, &ev,
|
||||
st->libctx, ev,
|
||||
OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY))
|
||||
goto end;
|
||||
else
|
||||
@@ -266,11 +268,12 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|
||||
|
||||
/* Only runs the KAT's during installation OR on_demand() */
|
||||
if (on_demand_test || kats_already_passed == 0) {
|
||||
if (!SELF_TEST_kats(&ev, st->libctx))
|
||||
if (!SELF_TEST_kats(ev, st->libctx))
|
||||
goto end;
|
||||
}
|
||||
ok = 1;
|
||||
end:
|
||||
OSSL_SELF_TEST_free(ev);
|
||||
OPENSSL_free(module_checksum);
|
||||
OPENSSL_free(indicator_checksum);
|
||||
|
||||
|
||||
@@ -26,31 +26,11 @@ typedef struct self_test_post_params_st {
|
||||
OSSL_BIO_new_membuf_fn *bio_new_buffer_cb;
|
||||
OSSL_BIO_read_ex_fn *bio_read_ex_cb;
|
||||
OSSL_BIO_free_fn *bio_free_cb;
|
||||
OSSL_CALLBACK *event_cb;
|
||||
void *event_cb_arg;
|
||||
OSSL_CALLBACK *cb;
|
||||
void *cb_arg;
|
||||
OPENSSL_CTX *libctx;
|
||||
|
||||
} SELF_TEST_POST_PARAMS;
|
||||
|
||||
typedef struct st_event_st
|
||||
{
|
||||
/* local state variables */
|
||||
const char *phase;
|
||||
const char *type;
|
||||
const char *desc;
|
||||
OSSL_CALLBACK *cb;
|
||||
|
||||
/* callback related variables used to pass the state back to the user */
|
||||
OSSL_PARAM params[4];
|
||||
void *cb_arg;
|
||||
|
||||
} OSSL_ST_EVENT;
|
||||
|
||||
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
|
||||
int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx);
|
||||
|
||||
void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg);
|
||||
void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
|
||||
const char *desc);
|
||||
void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret);
|
||||
void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes);
|
||||
int SELF_TEST_kats(OSSL_SELF_TEST *event, OPENSSL_CTX *libctx);
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -42,6 +42,28 @@ typedef struct st_kat_kdf_st {
|
||||
size_t expected_len;
|
||||
} ST_KAT_KDF;
|
||||
|
||||
typedef struct st_kat_drbg_st {
|
||||
const char *desc;
|
||||
const char *algorithm;
|
||||
int nid;
|
||||
const unsigned char *entropyin;
|
||||
size_t entropyinlen;
|
||||
const unsigned char *nonce;
|
||||
size_t noncelen;
|
||||
const unsigned char *persstr;
|
||||
size_t persstrlen;
|
||||
const unsigned char *entropyinpr1;
|
||||
size_t entropyinpr1len;
|
||||
const unsigned char *entropyinpr2;
|
||||
size_t entropyinpr2len;
|
||||
const unsigned char *entropyaddin1;
|
||||
size_t entropyaddin1len;
|
||||
const unsigned char *entropyaddin2;
|
||||
size_t entropyaddin2len;
|
||||
const unsigned char *expected;
|
||||
size_t expectedlen;
|
||||
} ST_KAT_DRBG;
|
||||
|
||||
/* Macros to build Self test data */
|
||||
#define ITM(x) x, sizeof(x)
|
||||
#define ITM_STR(x) x, sizeof(x) - 1
|
||||
@@ -191,3 +213,212 @@ static const ST_KAT_KDF st_kat_kdf_tests[] =
|
||||
}
|
||||
};
|
||||
|
||||
/*-
|
||||
* DRBG test vectors are a small subset of
|
||||
* https://csrc.nist.rip/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
|
||||
* Using the folder drbgvectors_pr_true
|
||||
* Generated for CAVS 14.3.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hash_DRBG.rsp
|
||||
*
|
||||
* [SHA-256]
|
||||
* [PredictionResistance = True]
|
||||
* [EntropyInputLen = 256]
|
||||
* [NonceLen = 128]
|
||||
* [PersonalizationStringLen = 256]
|
||||
* [AdditionalInputLen = 256]
|
||||
* [ReturnedBitsLen = 1024]
|
||||
*
|
||||
* COUNT = 14
|
||||
*/
|
||||
static const unsigned char drbg_hash_sha256_pr_entropyin[] = {
|
||||
0x06, 0x6d, 0xc8, 0xce, 0x75, 0xb2, 0x89, 0x66, 0xa6, 0x85, 0x16, 0x3f,
|
||||
0xe2, 0xa4, 0xd4, 0x27, 0xfb, 0xdb, 0x61, 0x66, 0x50, 0x61, 0x6b, 0xa2,
|
||||
0x82, 0xfc, 0x33, 0x2b, 0x4e, 0x6f, 0x12, 0x20
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_nonce[] = {
|
||||
0x55, 0x9f, 0x7c, 0x64, 0x89, 0x70, 0x83, 0xec, 0x2d, 0x73, 0x70, 0xd9,
|
||||
0xf0, 0xe5, 0x07, 0x1f
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_persstr[] = {
|
||||
0x88, 0x6f, 0x54, 0x9a, 0xad, 0x1a, 0xc6, 0x3d, 0x18, 0xcb, 0xcc, 0x66,
|
||||
0x85, 0xda, 0xa2, 0xc2, 0xf7, 0x9e, 0xb0, 0x89, 0x4c, 0xb4, 0xae, 0xf1,
|
||||
0xac, 0x54, 0x4f, 0xce, 0x57, 0xf1, 0x5e, 0x11
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_entropyinpr0[] = {
|
||||
0xff, 0x80, 0xb7, 0xd2, 0x6a, 0x05, 0xbc, 0x8a, 0x7a, 0xbe, 0x53, 0x28,
|
||||
0x6b, 0x0e, 0xeb, 0x73, 0x3b, 0x71, 0x5a, 0x20, 0x5b, 0xfa, 0x4f, 0xf6,
|
||||
0x37, 0x03, 0xde, 0xad, 0xb6, 0xea, 0x0e, 0xf4
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_entropyinpr1[] = {
|
||||
0xc7, 0x38, 0x32, 0x53, 0x46, 0x81, 0xed, 0xe3, 0x7e, 0x03, 0x84, 0x6d,
|
||||
0x3c, 0x84, 0x17, 0x67, 0x29, 0x7d, 0x24, 0x6c, 0x68, 0x92, 0x41, 0xd2,
|
||||
0xe7, 0x75, 0xbe, 0x7e, 0xc9, 0x96, 0x29, 0x3d
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_addin0[] = {
|
||||
0xb7, 0x21, 0x5f, 0x14, 0xac, 0x7b, 0xaf, 0xd0, 0xa9, 0x17, 0x72, 0xba,
|
||||
0x22, 0xf7, 0x19, 0xaf, 0xbd, 0x20, 0xb3, 0x11, 0x63, 0x6c, 0x2b, 0x1e,
|
||||
0x83, 0xe4, 0xa8, 0x23, 0x35, 0x3f, 0xc6, 0xea
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_addin1[] = {
|
||||
0xce, 0xd3, 0x1f, 0x7e, 0x0d, 0xae, 0x5b, 0xb5, 0xc0, 0x43, 0xe2, 0x46,
|
||||
0xb2, 0x94, 0x73, 0xe2, 0xfd, 0x39, 0x51, 0x2e, 0xad, 0x45, 0x69, 0xee,
|
||||
0xe3, 0xe3, 0x80, 0x33, 0x14, 0xab, 0xa7, 0xa3
|
||||
};
|
||||
static const unsigned char drbg_hash_sha256_pr_expected[] = {
|
||||
0x60, 0xc2, 0x34, 0xcf, 0xaf, 0xb4, 0x68, 0x03, 0x3b, 0xf1, 0x95, 0xe5,
|
||||
0x78, 0xce, 0x26, 0x6e, 0x14, 0x65, 0x32, 0x6a, 0x96, 0xa9, 0xe0, 0x3f,
|
||||
0x8b, 0x89, 0x36, 0x70, 0xef, 0x62, 0x75, 0x4d, 0x5e, 0x80, 0xd5, 0x53,
|
||||
0xa1, 0xf8, 0x49, 0x50, 0x20, 0x8b, 0x93, 0x43, 0x07, 0x9f, 0x2e, 0xf8,
|
||||
0x56, 0xe9, 0xc5, 0x70, 0x61, 0x85, 0x97, 0xb5, 0xdc, 0x82, 0xa2, 0xda,
|
||||
0xea, 0xa3, 0xfd, 0x9b, 0x2f, 0xd2, 0xa0, 0xd7, 0x1b, 0xc6, 0x29, 0x35,
|
||||
0xcc, 0xb8, 0x3d, 0xa0, 0x67, 0x98, 0x05, 0xa0, 0xe3, 0x1e, 0xfe, 0xe4,
|
||||
0xf0, 0xe5, 0x13, 0xb0, 0x83, 0x17, 0xfa, 0xca, 0x93, 0x5e, 0x38, 0x29,
|
||||
0x48, 0xd2, 0x72, 0xdb, 0x76, 0x3e, 0x6d, 0xf3, 0x25, 0x10, 0xff, 0x1b,
|
||||
0x99, 0xff, 0xf8, 0xc6, 0x0e, 0xb0, 0xdd, 0x29, 0x2e, 0xbc, 0xbb, 0xc8,
|
||||
0x0a, 0x01, 0x6e, 0xd3, 0xb0, 0x0e, 0x4e, 0xab
|
||||
};
|
||||
|
||||
/*
|
||||
* CTR_DRBG.rsp
|
||||
*
|
||||
* [AES-128 use df]
|
||||
* [PredictionResistance = True]
|
||||
* [EntropyInputLen = 128]
|
||||
* [NonceLen = 64]
|
||||
* [PersonalizationStringLen = 128]
|
||||
* [AdditionalInputLen = 128]
|
||||
* [ReturnedBitsLen = 512]
|
||||
*
|
||||
* COUNT = 0
|
||||
*/
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_entropyin[] = {
|
||||
0x92, 0x89, 0x8f, 0x31, 0xfa, 0x1c, 0xff, 0x6d, 0x18, 0x2f, 0x26, 0x06,
|
||||
0x43, 0xdf, 0xf8, 0x18
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_nonce[] = {
|
||||
0xc2, 0xa4, 0xd9, 0x72, 0xc3, 0xb9, 0xb6, 0x97
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_persstr[] = {
|
||||
0xea, 0x65, 0xee, 0x60, 0x26, 0x4e, 0x7e, 0xb6, 0x0e, 0x82, 0x68, 0xc4,
|
||||
0x37, 0x3c, 0x5c, 0x0b
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_entropyinpr0[] = {
|
||||
0x20, 0x72, 0x8a, 0x06, 0xf8, 0x6f, 0x8d, 0xd4, 0x41, 0xe2, 0x72, 0xb7,
|
||||
0xc4, 0x2c, 0xe8, 0x10
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_entropyinpr1[] = {
|
||||
0x3d, 0xb0, 0xf0, 0x94, 0xf3, 0x05, 0x50, 0x33, 0x17, 0x86, 0x3e, 0x22,
|
||||
0x08, 0xf7, 0xa5, 0x01
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_addin0[] = {
|
||||
0x1a, 0x40, 0xfa, 0xe3, 0xcc, 0x6c, 0x7c, 0xa0, 0xf8, 0xda, 0xba, 0x59,
|
||||
0x23, 0x6d, 0xad, 0x1d
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_addin1[] = {
|
||||
0x9f, 0x72, 0x76, 0x6c, 0xc7, 0x46, 0xe5, 0xed, 0x2e, 0x53, 0x20, 0x12,
|
||||
0xbc, 0x59, 0x31, 0x8c
|
||||
};
|
||||
static const unsigned char drbg_ctr_aes128_pr_df_expected[] = {
|
||||
0x5a, 0x35, 0x39, 0x87, 0x0f, 0x4d, 0x22, 0xa4, 0x09, 0x24, 0xee, 0x71,
|
||||
0xc9, 0x6f, 0xac, 0x72, 0x0a, 0xd6, 0xf0, 0x88, 0x82, 0xd0, 0x83, 0x28,
|
||||
0x73, 0xec, 0x3f, 0x93, 0xd8, 0xab, 0x45, 0x23, 0xf0, 0x7e, 0xac, 0x45,
|
||||
0x14, 0x5e, 0x93, 0x9f, 0xb1, 0xd6, 0x76, 0x43, 0x3d, 0xb6, 0xe8, 0x08,
|
||||
0x88, 0xf6, 0xda, 0x89, 0x08, 0x77, 0x42, 0xfe, 0x1a, 0xf4, 0x3f, 0xc4,
|
||||
0x23, 0xc5, 0x1f, 0x68
|
||||
};
|
||||
|
||||
/*
|
||||
* HMAC_DRBG.rsp
|
||||
*
|
||||
* [SHA-1]
|
||||
* [PredictionResistance = True]
|
||||
* [EntropyInputLen = 128]
|
||||
* [NonceLen = 64]
|
||||
* [PersonalizationStringLen = 128]
|
||||
* [AdditionalInputLen = 128]
|
||||
* [ReturnedBitsLen = 640]
|
||||
*
|
||||
* COUNT = 0
|
||||
*/
|
||||
static const unsigned char drbg_hmac_sha1_pr_entropyin[] = {
|
||||
0x68, 0x0f, 0xac, 0xe9, 0x0d, 0x7b, 0xca, 0x21, 0xd4, 0xa0, 0xed, 0xb7,
|
||||
0x79, 0x9e, 0xe5, 0xd8
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_nonce[] = {
|
||||
0xb7, 0xbe, 0x9e, 0xed, 0xdd, 0x0e, 0x3b, 0x4b
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_persstr[] = {
|
||||
0xf5, 0x8c, 0x40, 0xae, 0x70, 0xf7, 0xa5, 0x56, 0x48, 0xa9, 0x31, 0xa0,
|
||||
0xa9, 0x31, 0x3d, 0xd7
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_entropyinpr0[] = {
|
||||
0x7c, 0xaf, 0xe2, 0x31, 0x63, 0x0a, 0xa9, 0x5a, 0x74, 0x2c, 0x4e, 0x5f,
|
||||
0x5f, 0x22, 0xc6, 0xa4
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_entropyinpr1[] = {
|
||||
0x1c, 0x0d, 0x77, 0x92, 0x89, 0x88, 0x27, 0x94, 0x8a, 0x58, 0x9f, 0x82,
|
||||
0x2d, 0x1a, 0xf7, 0xa6
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_addin0[] = {
|
||||
0xdc, 0x36, 0x63, 0xf0, 0x62, 0x78, 0x9c, 0xd1, 0x5c, 0xbb, 0x20, 0xc3,
|
||||
0xc1, 0x8c, 0xd9, 0xd7
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_addin1[] = {
|
||||
0xfe, 0x85, 0xb0, 0xab, 0x14, 0xc6, 0x96, 0xe6, 0x9c, 0x24, 0xe7, 0xb5,
|
||||
0xa1, 0x37, 0x12, 0x0c
|
||||
};
|
||||
static const unsigned char drbg_hmac_sha1_pr_expected[] = {
|
||||
0x68, 0x00, 0x4b, 0x3a, 0x28, 0xf7, 0xf0, 0x1c, 0xf9, 0xe9, 0xb5, 0x71,
|
||||
0x20, 0x79, 0xef, 0x80, 0x87, 0x1b, 0x08, 0xb9, 0xa9, 0x1b, 0xcd, 0x2b,
|
||||
0x9f, 0x09, 0x4d, 0xa4, 0x84, 0x80, 0xb3, 0x4c, 0xaf, 0xd5, 0x59, 0x6b,
|
||||
0x0c, 0x0a, 0x48, 0xe1, 0x48, 0xda, 0xbc, 0x6f, 0x77, 0xb8, 0xff, 0xaf,
|
||||
0x18, 0x70, 0x28, 0xe1, 0x04, 0x13, 0x7a, 0x4f, 0xeb, 0x1c, 0x72, 0xb0,
|
||||
0xc4, 0x4f, 0xe8, 0xb1, 0xaf, 0xab, 0xa5, 0xbc, 0xfd, 0x86, 0x67, 0xf2,
|
||||
0xf5, 0x5b, 0x46, 0x06, 0x63, 0x2e, 0x3c, 0xbc
|
||||
};
|
||||
|
||||
static const ST_KAT_DRBG st_kat_drbg_tests[] =
|
||||
{
|
||||
{
|
||||
OSSL_SELF_TEST_DESC_DRBG_HASH,
|
||||
"SHA256",
|
||||
NID_sha256,
|
||||
ITM(drbg_hash_sha256_pr_entropyin),
|
||||
ITM(drbg_hash_sha256_pr_nonce),
|
||||
ITM(drbg_hash_sha256_pr_persstr),
|
||||
ITM(drbg_hash_sha256_pr_entropyinpr0),
|
||||
ITM(drbg_hash_sha256_pr_entropyinpr1),
|
||||
ITM(drbg_hash_sha256_pr_addin0),
|
||||
ITM(drbg_hash_sha256_pr_addin1),
|
||||
ITM(drbg_hash_sha256_pr_expected)
|
||||
},
|
||||
{
|
||||
OSSL_SELF_TEST_DESC_DRBG_CTR,
|
||||
"AES-128",
|
||||
NID_aes_128_ctr,
|
||||
ITM(drbg_ctr_aes128_pr_df_entropyin),
|
||||
ITM(drbg_ctr_aes128_pr_df_nonce),
|
||||
ITM(drbg_ctr_aes128_pr_df_persstr),
|
||||
ITM(drbg_ctr_aes128_pr_df_entropyinpr0),
|
||||
ITM(drbg_ctr_aes128_pr_df_entropyinpr1),
|
||||
ITM(drbg_ctr_aes128_pr_df_addin0),
|
||||
ITM(drbg_ctr_aes128_pr_df_addin1),
|
||||
ITM(drbg_ctr_aes128_pr_df_expected)
|
||||
},
|
||||
{
|
||||
OSSL_SELF_TEST_DESC_DRBG_HMAC,
|
||||
"SHA1",
|
||||
NID_sha1,
|
||||
ITM(drbg_hmac_sha1_pr_entropyin),
|
||||
ITM(drbg_hmac_sha1_pr_nonce),
|
||||
ITM(drbg_hmac_sha1_pr_persstr),
|
||||
ITM(drbg_hmac_sha1_pr_entropyinpr0),
|
||||
ITM(drbg_hmac_sha1_pr_entropyinpr1),
|
||||
ITM(drbg_hmac_sha1_pr_addin0),
|
||||
ITM(drbg_hmac_sha1_pr_addin1),
|
||||
ITM(drbg_hmac_sha1_pr_expected)
|
||||
}
|
||||
};
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
#include "self_test.h"
|
||||
|
||||
static void self_test_event_setparams(OSSL_ST_EVENT *ev)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
if (ev->cb != NULL) {
|
||||
ev->params[n++] =
|
||||
OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
|
||||
(char *)ev->phase, 0);
|
||||
ev->params[n++] =
|
||||
OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
|
||||
(char *)ev->type, 0);
|
||||
ev->params[n++] =
|
||||
OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
|
||||
(char *)ev->desc, 0);
|
||||
}
|
||||
ev->params[n++] = OSSL_PARAM_construct_end();
|
||||
}
|
||||
|
||||
void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
if (ev == NULL)
|
||||
return;
|
||||
|
||||
ev->cb = cb;
|
||||
ev->cb_arg = cbarg;
|
||||
ev->phase = "";
|
||||
ev->type = "";
|
||||
ev->desc = "";
|
||||
self_test_event_setparams(ev);
|
||||
}
|
||||
|
||||
/* Can be used during application testing to log that a test has started. */
|
||||
void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
|
||||
const char *desc)
|
||||
{
|
||||
if (ev != NULL && ev->cb != NULL) {
|
||||
ev->phase = OSSL_SELF_TEST_PHASE_START;
|
||||
ev->type = type;
|
||||
ev->desc = desc;
|
||||
self_test_event_setparams(ev);
|
||||
(void)ev->cb(ev->params, ev->cb_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Can be used during application testing to log that a test has either
|
||||
* passed or failed.
|
||||
*/
|
||||
void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret)
|
||||
{
|
||||
if (ev != NULL && ev->cb != NULL) {
|
||||
ev->phase =
|
||||
(ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
|
||||
self_test_event_setparams(ev);
|
||||
(void)ev->cb(ev->params, ev->cb_arg);
|
||||
|
||||
ev->phase = OSSL_SELF_TEST_PHASE_NONE;
|
||||
ev->type = OSSL_SELF_TEST_TYPE_NONE;
|
||||
ev->desc = OSSL_SELF_TEST_DESC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used for failure testing.
|
||||
*
|
||||
* Call the applications SELF_TEST_cb() if it exists.
|
||||
* If the application callback decides to return 0 then the first byte of 'bytes'
|
||||
* is modified (corrupted). This is used to modify output signatures or
|
||||
* ciphertext before they are verified or decrypted.
|
||||
*/
|
||||
void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes)
|
||||
{
|
||||
if (ev != NULL && ev->cb != NULL) {
|
||||
ev->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
|
||||
self_test_event_setparams(ev);
|
||||
if (!ev->cb(ev->params, ev->cb_arg))
|
||||
bytes[0] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
+160
-40
@@ -10,12 +10,17 @@
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/rand_drbg.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "self_test.h"
|
||||
#include "self_test_data.inc"
|
||||
#include "../../crypto/rand/rand_local.h"
|
||||
|
||||
static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
|
||||
#define DRBG_PARAM_ENTROPY "DRBG-ENTROPY"
|
||||
#define DRBG_PARAM_NONCE "DRBG-NONCE"
|
||||
|
||||
static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
|
||||
OPENSSL_CTX *libctx)
|
||||
{
|
||||
int ok = 0;
|
||||
@@ -24,7 +29,7 @@ static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
|
||||
|
||||
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
|
||||
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
|
||||
|
||||
if (ctx == NULL
|
||||
|| md == NULL
|
||||
@@ -34,14 +39,14 @@ static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
|
||||
goto err;
|
||||
|
||||
/* Optional corruption */
|
||||
SELF_TEST_EVENT_oncorrupt_byte(event, out);
|
||||
OSSL_SELF_TEST_oncorrupt_byte(st, out);
|
||||
|
||||
if (out_len != t->expected_len
|
||||
|| memcmp(out, t->expected, out_len) != 0)
|
||||
goto err;
|
||||
ok = 1;
|
||||
err:
|
||||
SELF_TEST_EVENT_onend(event, ok);
|
||||
OSSL_SELF_TEST_onend(st, ok);
|
||||
EVP_MD_free(md);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
@@ -81,7 +86,7 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
}
|
||||
|
||||
/* Test a single KAT for encrypt/decrypt */
|
||||
static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
|
||||
static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_SELF_TEST *st,
|
||||
OPENSSL_CTX *libctx)
|
||||
{
|
||||
int ret = 0, encrypt = 1, len, ct_len = 0, pt_len = 0;
|
||||
@@ -90,54 +95,54 @@ static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
|
||||
unsigned char ct_buf[256] = { 0 };
|
||||
unsigned char pt_buf[256] = { 0 };
|
||||
|
||||
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
|
||||
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto end;
|
||||
goto err;
|
||||
cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, "");
|
||||
if (cipher == NULL)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
/* Encrypt plain text message */
|
||||
if (!cipher_init(ctx, cipher, t, encrypt)
|
||||
|| !EVP_CipherUpdate(ctx, ct_buf, &len, t->base.pt, t->base.pt_len)
|
||||
|| !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
SELF_TEST_EVENT_oncorrupt_byte(event, ct_buf);
|
||||
OSSL_SELF_TEST_oncorrupt_byte(st, ct_buf);
|
||||
ct_len += len;
|
||||
if (ct_len != (int)t->base.expected_len
|
||||
|| memcmp(t->base.expected, ct_buf, ct_len) != 0)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
if (t->tag != NULL) {
|
||||
unsigned char tag[16] = { 0 };
|
||||
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, t->tag_len, tag)
|
||||
|| memcmp(tag, t->tag, t->tag_len) != 0)
|
||||
goto end;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(cipher_init(ctx, cipher, t, !encrypt)
|
||||
&& EVP_CipherUpdate(ctx, pt_buf, &len, ct_buf, ct_len)
|
||||
&& EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
|
||||
goto end;
|
||||
goto err;
|
||||
pt_len += len;
|
||||
|
||||
if (pt_len != (int)t->base.pt_len
|
||||
|| memcmp(pt_buf, t->base.pt, pt_len) != 0)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
err:
|
||||
EVP_CIPHER_free(cipher);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
SELF_TEST_EVENT_onend(event, ret);
|
||||
OSSL_SELF_TEST_onend(st, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
|
||||
static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st,
|
||||
OPENSSL_CTX *libctx)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -149,7 +154,7 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
|
||||
const OSSL_PARAM *settables = NULL;
|
||||
|
||||
numparams = OSSL_NELEM(params);
|
||||
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
|
||||
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
|
||||
|
||||
/* Zeroize the params array to avoid mem leaks on error */
|
||||
for (i = 0; i < numparams; ++i)
|
||||
@@ -158,38 +163,140 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
|
||||
kdf = EVP_KDF_fetch(libctx, t->algorithm, "");
|
||||
ctx = EVP_KDF_CTX_new(kdf);
|
||||
if (ctx == NULL)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
settables = EVP_KDF_settable_ctx_params(kdf);
|
||||
for (i = 0; t->ctrls[i].name != NULL; ++i) {
|
||||
if (!ossl_assert(i < (numparams - 1)))
|
||||
goto end;
|
||||
goto err;
|
||||
if (!OSSL_PARAM_allocate_from_text(¶ms[i], settables,
|
||||
t->ctrls[i].name,
|
||||
t->ctrls[i].value,
|
||||
strlen(t->ctrls[i].value)))
|
||||
goto end;
|
||||
strlen(t->ctrls[i].value), NULL))
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_KDF_CTX_set_params(ctx, params))
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
if (t->expected_len > sizeof(out))
|
||||
goto end;
|
||||
goto err;
|
||||
if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
SELF_TEST_EVENT_oncorrupt_byte(event, out);
|
||||
OSSL_SELF_TEST_oncorrupt_byte(st, out);
|
||||
|
||||
if (memcmp(out, t->expected, t->expected_len) != 0)
|
||||
goto end;
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
err:
|
||||
for (i = 0; params[i].key != NULL; ++i)
|
||||
OPENSSL_free(params[i].data);
|
||||
EVP_KDF_free(kdf);
|
||||
EVP_KDF_CTX_free(ctx);
|
||||
SELF_TEST_EVENT_onend(event, ret);
|
||||
OSSL_SELF_TEST_onend(st, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t drbg_kat_entropy_cb(RAND_DRBG *drbg, unsigned char **pout,
|
||||
int entropy, size_t min_len, size_t max_len,
|
||||
int prediction_resistance)
|
||||
{
|
||||
OSSL_PARAM *drbg_params = RAND_DRBG_get_callback_data(drbg);
|
||||
OSSL_PARAM *p = OSSL_PARAM_locate(drbg_params, DRBG_PARAM_ENTROPY);
|
||||
|
||||
if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
*pout = (unsigned char *)p->data;
|
||||
return p->data_size;
|
||||
}
|
||||
|
||||
static size_t drbg_kat_nonce_cb(RAND_DRBG *drbg, unsigned char **pout,
|
||||
int entropy, size_t min_len, size_t max_len)
|
||||
{
|
||||
OSSL_PARAM *drbg_params = RAND_DRBG_get_callback_data(drbg);
|
||||
OSSL_PARAM *p = OSSL_PARAM_locate(drbg_params, DRBG_PARAM_NONCE);
|
||||
|
||||
if (p == NULL || p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
*pout = (unsigned char *)p->data;
|
||||
return p->data_size;
|
||||
}
|
||||
|
||||
static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,
|
||||
OPENSSL_CTX *libctx)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char out[256];
|
||||
RAND_DRBG *drbg = NULL;
|
||||
unsigned int flags = 0;
|
||||
int prediction_resistance = 1; /* Causes a reseed */
|
||||
OSSL_PARAM drbg_params[3] = {
|
||||
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
|
||||
};
|
||||
static const unsigned char zero[sizeof(drbg->data)] = { 0 };
|
||||
|
||||
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_DRBG, t->desc);
|
||||
|
||||
if (strcmp(t->desc, OSSL_SELF_TEST_DESC_DRBG_HMAC) == 0)
|
||||
flags |= RAND_DRBG_FLAG_HMAC;
|
||||
|
||||
drbg = RAND_DRBG_new_ex(libctx, t->nid, flags, NULL);
|
||||
if (drbg == NULL)
|
||||
goto err;
|
||||
|
||||
if (!RAND_DRBG_set_callback_data(drbg, drbg_params))
|
||||
goto err;
|
||||
|
||||
if (!RAND_DRBG_set_callbacks(drbg, drbg_kat_entropy_cb, NULL,
|
||||
drbg_kat_nonce_cb, NULL))
|
||||
goto err;
|
||||
|
||||
drbg_params[0] =
|
||||
OSSL_PARAM_construct_octet_string(DRBG_PARAM_ENTROPY,
|
||||
(void *)t->entropyin, t->entropyinlen);
|
||||
drbg_params[1] =
|
||||
OSSL_PARAM_construct_octet_string(DRBG_PARAM_NONCE,
|
||||
(void *)t->nonce, t->noncelen);
|
||||
|
||||
if (!RAND_DRBG_instantiate(drbg, t->persstr, t->persstrlen))
|
||||
goto err;
|
||||
|
||||
drbg_params[0] =
|
||||
OSSL_PARAM_construct_octet_string(DRBG_PARAM_ENTROPY,
|
||||
(void *)t->entropyinpr1,
|
||||
t->entropyinpr1len);
|
||||
|
||||
if (!RAND_DRBG_generate(drbg, out, t->expectedlen, prediction_resistance,
|
||||
t->entropyaddin1, t->entropyaddin1len))
|
||||
goto err;
|
||||
|
||||
drbg_params[0] =
|
||||
OSSL_PARAM_construct_octet_string(DRBG_PARAM_ENTROPY,
|
||||
(void *)t->entropyinpr2,
|
||||
t->entropyinpr2len);
|
||||
/* This calls RAND_DRBG_reseed() internally when prediction_resistance = 1 */
|
||||
if (!RAND_DRBG_generate(drbg, out, t->expectedlen, prediction_resistance,
|
||||
t->entropyaddin2, t->entropyaddin2len))
|
||||
goto err;
|
||||
|
||||
OSSL_SELF_TEST_oncorrupt_byte(st, out);
|
||||
|
||||
if (memcmp(out, t->expected, t->expectedlen) != 0)
|
||||
goto err;
|
||||
|
||||
if (!RAND_DRBG_uninstantiate(drbg))
|
||||
goto err;
|
||||
/*
|
||||
* Check that the DRBG data has been zeroized after RAND_DRBG_uninstantiate.
|
||||
*/
|
||||
if (memcmp((unsigned char *)&drbg->data, zero, sizeof(drbg->data)) != 0)
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
RAND_DRBG_free(drbg);
|
||||
OSSL_SELF_TEST_onend(st, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -198,34 +305,45 @@ end:
|
||||
* All tests are run regardless of if they fail or not.
|
||||
* Return 0 if any test fails.
|
||||
*/
|
||||
static int self_test_digests(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
|
||||
static int self_test_digests(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
|
||||
{
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
|
||||
if (!self_test_digest(&st_kat_digest_tests[i], event, libctx))
|
||||
if (!self_test_digest(&st_kat_digest_tests[i], st, libctx))
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int self_test_ciphers(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
|
||||
static int self_test_ciphers(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
|
||||
{
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
|
||||
if (!self_test_cipher(&st_kat_cipher_tests[i], event, libctx))
|
||||
if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx))
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int self_test_kdfs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
|
||||
static int self_test_kdfs(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
|
||||
{
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
|
||||
if (!self_test_kdf(&st_kat_kdf_tests[i], event, libctx))
|
||||
if (!self_test_kdf(&st_kat_kdf_tests[i], st, libctx))
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int self_test_drbgs(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
|
||||
{
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < (int)OSSL_NELEM(st_kat_drbg_tests); ++i) {
|
||||
if (!self_test_drbg(&st_kat_drbg_tests[i], st, libctx))
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
@@ -236,17 +354,19 @@ static int self_test_kdfs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
|
||||
* Return 1 is successful, otherwise return 0.
|
||||
* This runs all the tests regardless of if any fail.
|
||||
*
|
||||
* TODO(3.0) Add self tests for KA, DRBG, Sign/Verify when they become available
|
||||
* TODO(3.0) Add self tests for KA, Sign/Verify when they become available
|
||||
*/
|
||||
int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
|
||||
int SELF_TEST_kats(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (!self_test_digests(event, libctx))
|
||||
if (!self_test_digests(st, libctx))
|
||||
ret = 0;
|
||||
if (!self_test_ciphers(event, libctx))
|
||||
if (!self_test_ciphers(st, libctx))
|
||||
ret = 0;
|
||||
if (!self_test_kdfs(event, libctx))
|
||||
if (!self_test_kdfs(st, libctx))
|
||||
ret = 0;
|
||||
if (!self_test_drbgs(st, libctx))
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
$DH_GOAL=../../libimplementations.a
|
||||
$ECX_GOAL=../../libimplementations.a
|
||||
$ECDH_GOAL=../../libimplementations.a
|
||||
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[$DH_GOAL]=dh_exch.c
|
||||
@@ -21,4 +22,5 @@ ENDIF
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ECX_GOAL]=ecx_exch.c
|
||||
DEFINE[$ECX_GOAL]=$ECDEF
|
||||
SOURCE[$ECDH_GOAL]=ecdh_exch.c
|
||||
ENDIF
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* ECDH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/err.h>
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "crypto/ec.h" /* ecdh_KDF_X9_63() */
|
||||
|
||||
static OSSL_OP_keyexch_newctx_fn ecdh_newctx;
|
||||
static OSSL_OP_keyexch_init_fn ecdh_init;
|
||||
static OSSL_OP_keyexch_set_peer_fn ecdh_set_peer;
|
||||
static OSSL_OP_keyexch_derive_fn ecdh_derive;
|
||||
static OSSL_OP_keyexch_freectx_fn ecdh_freectx;
|
||||
static OSSL_OP_keyexch_dupctx_fn ecdh_dupctx;
|
||||
static OSSL_OP_keyexch_set_ctx_params_fn ecdh_set_ctx_params;
|
||||
static OSSL_OP_keyexch_settable_ctx_params_fn ecdh_settable_ctx_params;
|
||||
static OSSL_OP_keyexch_get_ctx_params_fn ecdh_get_ctx_params;
|
||||
static OSSL_OP_keyexch_gettable_ctx_params_fn ecdh_gettable_ctx_params;
|
||||
|
||||
enum kdf_type {
|
||||
PROV_ECDH_KDF_NONE = 0,
|
||||
PROV_ECDH_KDF_X9_63
|
||||
};
|
||||
|
||||
/*
|
||||
* What's passed as an actual key is defined by the KEYMGMT interface.
|
||||
* We happen to know that our KEYMGMT simply passes EC_KEY structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
OPENSSL_CTX *libctx;
|
||||
|
||||
EC_KEY *k;
|
||||
EC_KEY *peerk;
|
||||
|
||||
/*
|
||||
* ECDH cofactor mode:
|
||||
*
|
||||
* . 0 disabled
|
||||
* . 1 enabled
|
||||
* . -1 use cofactor mode set for k
|
||||
*/
|
||||
int cofactor_mode;
|
||||
|
||||
/************
|
||||
* ECDH KDF *
|
||||
************/
|
||||
/* KDF (if any) to use for ECDH */
|
||||
enum kdf_type kdf_type;
|
||||
/* Message digest to use for key derivation */
|
||||
EVP_MD *kdf_md;
|
||||
/* User key material */
|
||||
unsigned char *kdf_ukm;
|
||||
size_t kdf_ukmlen;
|
||||
/* KDF output length */
|
||||
size_t kdf_outlen;
|
||||
} PROV_ECDH_CTX;
|
||||
|
||||
static
|
||||
void *ecdh_newctx(void *provctx)
|
||||
{
|
||||
PROV_ECDH_CTX *pectx = OPENSSL_zalloc(sizeof(*pectx));
|
||||
|
||||
if (pectx == NULL)
|
||||
return NULL;
|
||||
|
||||
pectx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
|
||||
pectx->cofactor_mode = -1;
|
||||
pectx->kdf_type = PROV_ECDH_KDF_NONE;
|
||||
|
||||
return (void *)pectx;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_init(void *vpecdhctx, void *vecdh)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
if (pecdhctx == NULL || vecdh == NULL || !EC_KEY_up_ref(vecdh))
|
||||
return 0;
|
||||
EC_KEY_free(pecdhctx->k);
|
||||
pecdhctx->k = vecdh;
|
||||
pecdhctx->cofactor_mode = -1;
|
||||
pecdhctx->kdf_type = PROV_ECDH_KDF_NONE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_set_peer(void *vpecdhctx, void *vecdh)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
if (pecdhctx == NULL || vecdh == NULL || !EC_KEY_up_ref(vecdh))
|
||||
return 0;
|
||||
EC_KEY_free(pecdhctx->peerk);
|
||||
pecdhctx->peerk = vecdh;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void ecdh_freectx(void *vpecdhctx)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
EC_KEY_free(pecdhctx->k);
|
||||
EC_KEY_free(pecdhctx->peerk);
|
||||
|
||||
EVP_MD_free(pecdhctx->kdf_md);
|
||||
OPENSSL_clear_free(pecdhctx->kdf_ukm, pecdhctx->kdf_ukmlen);
|
||||
|
||||
OPENSSL_free(pecdhctx);
|
||||
}
|
||||
|
||||
static
|
||||
void *ecdh_dupctx(void *vpecdhctx)
|
||||
{
|
||||
PROV_ECDH_CTX *srcctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
PROV_ECDH_CTX *dstctx;
|
||||
|
||||
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
|
||||
if (dstctx == NULL)
|
||||
return NULL;
|
||||
|
||||
*dstctx = *srcctx;
|
||||
|
||||
/* clear all pointers */
|
||||
|
||||
dstctx->k= NULL;
|
||||
dstctx->peerk = NULL;
|
||||
dstctx->kdf_md = NULL;
|
||||
dstctx->kdf_ukm = NULL;
|
||||
|
||||
/* up-ref all ref-counted objects referenced in dstctx */
|
||||
|
||||
if (srcctx->k != NULL && !EC_KEY_up_ref(srcctx->k))
|
||||
goto err;
|
||||
else
|
||||
dstctx->k = srcctx->k;
|
||||
|
||||
if (srcctx->peerk != NULL && !EC_KEY_up_ref(srcctx->peerk))
|
||||
goto err;
|
||||
else
|
||||
dstctx->peerk = srcctx->peerk;
|
||||
|
||||
if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
|
||||
goto err;
|
||||
else
|
||||
dstctx->kdf_md = srcctx->kdf_md;
|
||||
|
||||
/* Duplicate UKM data if present */
|
||||
if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
|
||||
dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
|
||||
srcctx->kdf_ukmlen);
|
||||
if (dstctx->kdf_ukm == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return dstctx;
|
||||
|
||||
err:
|
||||
ecdh_freectx(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[])
|
||||
{
|
||||
char name[80] = { '\0' }; /* should be big enough */
|
||||
char *str = NULL;
|
||||
PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (pectx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
|
||||
if (p != NULL) {
|
||||
int mode;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &mode))
|
||||
return 0;
|
||||
|
||||
if (mode < -1 || mode > 1)
|
||||
return 0;
|
||||
|
||||
pectx->cofactor_mode = mode;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
|
||||
if (p != NULL) {
|
||||
str = name;
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
|
||||
return 0;
|
||||
|
||||
if (name[0] == '\0')
|
||||
pectx->kdf_type = PROV_ECDH_KDF_NONE;
|
||||
else if (strcmp(name, OSSL_KDF_NAME_X963KDF) == 0)
|
||||
pectx->kdf_type = PROV_ECDH_KDF_X9_63;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
|
||||
if (p != NULL) {
|
||||
char mdprops[80] = { '\0' }; /* should be big enough */
|
||||
|
||||
str = name;
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
|
||||
return 0;
|
||||
|
||||
str = mdprops;
|
||||
p = OSSL_PARAM_locate_const(params,
|
||||
OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
|
||||
|
||||
if (p != NULL) {
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_free(pectx->kdf_md);
|
||||
pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops);
|
||||
|
||||
if (pectx->kdf_md == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
|
||||
if (p != NULL) {
|
||||
size_t outlen;
|
||||
|
||||
if (!OSSL_PARAM_get_size_t(p, &outlen))
|
||||
return 0;
|
||||
pectx->kdf_outlen = outlen;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
|
||||
if (p != NULL) {
|
||||
void *tmp_ukm = NULL;
|
||||
size_t tmp_ukmlen;
|
||||
|
||||
if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
|
||||
return 0;
|
||||
OPENSSL_free(pectx->kdf_ukm);
|
||||
pectx->kdf_ukm = tmp_ukm;
|
||||
pectx->kdf_ukmlen = tmp_ukmlen;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
|
||||
OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ecdh_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_get_ctx_params(void *vpecdhctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if (pectx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
|
||||
if (p != NULL) {
|
||||
int mode = pectx->cofactor_mode;
|
||||
|
||||
if (mode == -1) {
|
||||
/* check what is the default for pecdhctx->k */
|
||||
mode = EC_KEY_get_flags(pectx->k) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!OSSL_PARAM_set_int(p, mode))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
|
||||
if (p != NULL) {
|
||||
const char *kdf_type = NULL;
|
||||
|
||||
switch (pectx->kdf_type) {
|
||||
case PROV_ECDH_KDF_NONE:
|
||||
kdf_type = "";
|
||||
break;
|
||||
case PROV_ECDH_KDF_X9_63:
|
||||
kdf_type = OSSL_KDF_NAME_X963KDF;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
|
||||
if (p != NULL
|
||||
&& !OSSL_PARAM_set_utf8_string(p, pectx->kdf_md == NULL
|
||||
? ""
|
||||
: EVP_MD_name(pectx->kdf_md))){
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, pectx->kdf_outlen))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
|
||||
if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pectx->kdf_ukm, 0))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM_LEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, pectx->kdf_ukmlen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
|
||||
OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
|
||||
NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ecdh_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
size_t ecdh_size(const EC_KEY *k)
|
||||
{
|
||||
size_t degree = 0;
|
||||
const EC_GROUP *group;
|
||||
|
||||
if (k == NULL
|
||||
|| (group = EC_KEY_get0_group(k)) == NULL)
|
||||
return 0;
|
||||
|
||||
degree = EC_GROUP_get_degree(group);
|
||||
|
||||
return (degree + 7) / 8;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int ecdh_plain_derive(void *vpecdhctx, unsigned char *secret,
|
||||
size_t *psecretlen, size_t outlen)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
int retlen, ret = 0;
|
||||
size_t ecdhsize, size;
|
||||
const EC_POINT *ppubkey = NULL;
|
||||
EC_KEY *privk = NULL;
|
||||
const EC_GROUP *group;
|
||||
const BIGNUM *cofactor;
|
||||
int key_cofactor_mode;
|
||||
|
||||
if (pecdhctx->k == NULL || pecdhctx->peerk == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, EC_R_KEYS_NOT_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ecdhsize = ecdh_size(pecdhctx->k);
|
||||
if (secret == NULL) {
|
||||
*psecretlen = ecdhsize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((group = EC_KEY_get0_group(pecdhctx->k)) == NULL
|
||||
|| (cofactor = EC_GROUP_get0_cofactor(group)) == NULL )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* NB: unlike PKCS#3 DH, if outlen is less than maximum size this is not
|
||||
* an error, the result is truncated.
|
||||
*/
|
||||
size = outlen < ecdhsize ? outlen : ecdhsize;
|
||||
|
||||
/*
|
||||
* The ctx->cofactor_mode flag has precedence over the
|
||||
* cofactor_mode flag set on ctx->k.
|
||||
*
|
||||
* - if ctx->cofactor_mode == -1, use ctx->k directly
|
||||
* - if ctx->cofactor_mode == key_cofactor_mode, use ctx->k directly
|
||||
* - if ctx->cofactor_mode != key_cofactor_mode:
|
||||
* - if ctx->k->cofactor == 1, the cofactor_mode flag is irrelevant, use
|
||||
* ctx->k directly
|
||||
* - if ctx->k->cofactor != 1, use a duplicate of ctx->k with the flag
|
||||
* set to ctx->cofactor_mode
|
||||
*/
|
||||
key_cofactor_mode =
|
||||
(EC_KEY_get_flags(pecdhctx->k) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
||||
if (pecdhctx->cofactor_mode != -1
|
||||
&& pecdhctx->cofactor_mode != key_cofactor_mode
|
||||
&& !BN_is_one(cofactor)) {
|
||||
if ((privk = EC_KEY_dup(pecdhctx->k)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (pecdhctx->cofactor_mode == 1)
|
||||
EC_KEY_set_flags(privk, EC_FLAG_COFACTOR_ECDH);
|
||||
else
|
||||
EC_KEY_clear_flags(privk, EC_FLAG_COFACTOR_ECDH);
|
||||
} else {
|
||||
privk = pecdhctx->k;
|
||||
}
|
||||
|
||||
ppubkey = EC_KEY_get0_public_key(pecdhctx->peerk);
|
||||
|
||||
retlen = ECDH_compute_key(secret, size, ppubkey, privk, NULL);
|
||||
|
||||
if (retlen <= 0)
|
||||
goto end;
|
||||
|
||||
*psecretlen = retlen;
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
if (privk != pecdhctx->k)
|
||||
EC_KEY_free(privk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int ecdh_X9_63_kdf_derive(void *vpecdhctx, unsigned char *secret,
|
||||
size_t *psecretlen, size_t outlen)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
unsigned char *stmp = NULL;
|
||||
size_t stmplen;
|
||||
int ret = 0;
|
||||
|
||||
if (secret == NULL) {
|
||||
*psecretlen = pecdhctx->kdf_outlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pecdhctx->kdf_outlen > outlen)
|
||||
return 0;
|
||||
if (!ecdh_plain_derive(vpecdhctx, NULL, &stmplen, 0))
|
||||
return 0;
|
||||
if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!ecdh_plain_derive(vpecdhctx, stmp, &stmplen, stmplen))
|
||||
goto err;
|
||||
|
||||
/* Do KDF stuff */
|
||||
if (!ecdh_KDF_X9_63(secret, pecdhctx->kdf_outlen,
|
||||
stmp, stmplen,
|
||||
pecdhctx->kdf_ukm,
|
||||
pecdhctx->kdf_ukmlen,
|
||||
pecdhctx->kdf_md))
|
||||
goto err;
|
||||
*psecretlen = pecdhctx->kdf_outlen;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_secure_clear_free(stmp, stmplen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_derive(void *vpecdhctx, unsigned char *secret,
|
||||
size_t *psecretlen, size_t outlen)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
switch (pecdhctx->kdf_type) {
|
||||
case PROV_ECDH_KDF_NONE:
|
||||
return ecdh_plain_derive(vpecdhctx, secret, psecretlen, outlen);
|
||||
case PROV_ECDH_KDF_X9_63:
|
||||
return ecdh_X9_63_kdf_derive(vpecdhctx, secret, psecretlen, outlen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const OSSL_DISPATCH ecdh_keyexch_functions[] = {
|
||||
{ OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ecdh_newctx },
|
||||
{ OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecdh_init },
|
||||
{ OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecdh_derive },
|
||||
{ OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecdh_set_peer },
|
||||
{ OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecdh_freectx },
|
||||
{ OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecdh_dupctx },
|
||||
{ OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))ecdh_set_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))ecdh_settable_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecdh_get_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))ecdh_gettable_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -259,14 +259,17 @@ extern const OSSL_DISPATCH dsa_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH rsa_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH x25519_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH x448_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ec_keymgmt_functions[];
|
||||
|
||||
/* Key Exchange */
|
||||
extern const OSSL_DISPATCH dh_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH x25519_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH x448_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH ecdh_keyexch_functions[];
|
||||
|
||||
/* Signature */
|
||||
extern const OSSL_DISPATCH dsa_signature_functions[];
|
||||
extern const OSSL_DISPATCH rsa_signature_functions[];
|
||||
|
||||
/* Asym Cipher */
|
||||
extern const OSSL_DISPATCH rsa_asym_cipher_functions[];
|
||||
@@ -278,6 +281,7 @@ extern const OSSL_DISPATCH rsa_priv_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH rsa_pub_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH rsa_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH rsa_pub_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH dh_priv_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_pub_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_param_text_serializer_functions[];
|
||||
@@ -287,6 +291,7 @@ extern const OSSL_DISPATCH dh_param_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_pub_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_param_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH dsa_priv_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_pub_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_param_text_serializer_functions[];
|
||||
@@ -296,3 +301,17 @@ extern const OSSL_DISPATCH dsa_param_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_pub_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_param_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH x25519_priv_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_pub_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_priv_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_pub_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_pub_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH x448_priv_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_pub_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_priv_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_pub_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_pub_pem_serializer_functions[];
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
$DH_GOAL=../../libimplementations.a
|
||||
$DSA_GOAL=../../libimplementations.a
|
||||
$EC_GOAL=../../libimplementations.a
|
||||
$RSA_GOAL=../../libimplementations.a
|
||||
$ECX_GOAL=../../libimplementations.a
|
||||
|
||||
@@ -12,6 +13,9 @@ ENDIF
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=dsa_kmgmt.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$EC_GOAL]=ec_kmgmt.c
|
||||
ENDIF
|
||||
SOURCE[$RSA_GOAL]=rsa_kmgmt.c
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ECX_GOAL]=ecx_kmgmt.c
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
@@ -23,6 +29,7 @@ static OSSL_OP_keymgmt_free_fn dh_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn dh_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn dh_gettable_params;
|
||||
static OSSL_OP_keymgmt_has_fn dh_has;
|
||||
static OSSL_OP_keymgmt_match_fn dh_match;
|
||||
static OSSL_OP_keymgmt_import_fn dh_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn dh_import_types;
|
||||
static OSSL_OP_keymgmt_export_fn dh_export;
|
||||
@@ -111,7 +118,7 @@ static int params_to_key(DH *dh, const OSSL_PARAM params[])
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(priv_key);
|
||||
BN_clear_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
@@ -163,6 +170,25 @@ static int dh_has(void *keydata, int selection)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dh_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const DH *dh1 = keydata1;
|
||||
const DH *dh2 = keydata2;
|
||||
int ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok && BN_cmp(DH_get0_pub_key(dh1), DH_get0_pub_key(dh2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok && BN_cmp(DH_get0_priv_key(dh1), DH_get0_priv_key(dh2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
|
||||
FFC_PARAMS *dhparams1 = dh_get0_params((DH *)dh1);
|
||||
FFC_PARAMS *dhparams2 = dh_get0_params((DH *)dh2);
|
||||
|
||||
ok = ok && ffc_params_cmp(dhparams1, dhparams2, 1);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
DH *dh = keydata;
|
||||
@@ -296,6 +322,7 @@ const OSSL_DISPATCH dh_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
|
||||
|
||||
@@ -29,6 +29,7 @@ static OSSL_OP_keymgmt_free_fn dsa_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn dsa_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn dsa_gettable_params;
|
||||
static OSSL_OP_keymgmt_has_fn dsa_has;
|
||||
static OSSL_OP_keymgmt_match_fn dsa_match;
|
||||
static OSSL_OP_keymgmt_import_fn dsa_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn dsa_import_types;
|
||||
static OSSL_OP_keymgmt_export_fn dsa_export;
|
||||
@@ -123,7 +124,7 @@ static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(priv_key);
|
||||
BN_clear_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
@@ -175,6 +176,27 @@ static int dsa_has(void *keydata, int selection)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dsa_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const DSA *dsa1 = keydata1;
|
||||
const DSA *dsa2 = keydata2;
|
||||
int ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok
|
||||
&& BN_cmp(DSA_get0_pub_key(dsa1), DSA_get0_pub_key(dsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok
|
||||
&& BN_cmp(DSA_get0_priv_key(dsa1), DSA_get0_priv_key(dsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
|
||||
FFC_PARAMS *dsaparams1 = dsa_get0_params((DSA *)dsa1);
|
||||
FFC_PARAMS *dsaparams2 = dsa_get0_params((DSA *)dsa2);
|
||||
|
||||
ok = ok && ffc_params_cmp(dsaparams1, dsaparams2, 1);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
DSA *dsa = keydata;
|
||||
@@ -313,6 +335,7 @@ const OSSL_DISPATCH dsa_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dsa_match },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
|
||||
|
||||
@@ -0,0 +1,749 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* ECDH/ECDSA low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/params.h>
|
||||
#include "crypto/bn.h"
|
||||
#include "internal/param_build.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/providercommon.h"
|
||||
|
||||
static OSSL_OP_keymgmt_new_fn ec_newdata;
|
||||
static OSSL_OP_keymgmt_free_fn ec_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn ec_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn ec_gettable_params;
|
||||
static OSSL_OP_keymgmt_set_params_fn ec_set_params;
|
||||
static OSSL_OP_keymgmt_settable_params_fn ec_settable_params;
|
||||
static OSSL_OP_keymgmt_has_fn ec_has;
|
||||
static OSSL_OP_keymgmt_match_fn ec_match;
|
||||
static OSSL_OP_keymgmt_import_fn ec_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn ec_import_types;
|
||||
static OSSL_OP_keymgmt_export_fn ec_export;
|
||||
static OSSL_OP_keymgmt_export_types_fn ec_export_types;
|
||||
static OSSL_OP_keymgmt_query_operation_name_fn ec_query_operation_name;
|
||||
|
||||
#define EC_POSSIBLE_SELECTIONS \
|
||||
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
|
||||
|
||||
static
|
||||
const char *ec_query_operation_name(int operation_id)
|
||||
{
|
||||
switch (operation_id) {
|
||||
case OSSL_OP_KEYEXCH:
|
||||
return "ECDH";
|
||||
#if 0
|
||||
case OSSL_OP_SIGNATURE:
|
||||
return deflt_signature;
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int params_to_domparams(EC_KEY *ec, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *param_ec_name;
|
||||
EC_GROUP *ecg = NULL;
|
||||
char *curve_name = NULL;
|
||||
int ok = 0;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
param_ec_name = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME);
|
||||
if (param_ec_name == NULL) {
|
||||
/* explicit parameters */
|
||||
|
||||
/*
|
||||
* TODO(3.0): should we support explicit parameters curves?
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
/* named curve */
|
||||
int curve_nid;
|
||||
|
||||
if (!OSSL_PARAM_get_utf8_string(param_ec_name, &curve_name, 0)
|
||||
|| curve_name == NULL
|
||||
|| (curve_nid = OBJ_sn2nid(curve_name)) == NID_undef)
|
||||
goto err;
|
||||
|
||||
if ((ecg = EC_GROUP_new_by_curve_name(curve_nid)) == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_group(ec, ecg))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* TODO(3.0): if the group has changed, should we invalidate the private and
|
||||
* public key?
|
||||
*/
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(curve_name);
|
||||
EC_GROUP_free(ecg);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
|
||||
{
|
||||
const EC_GROUP *ecg;
|
||||
int curve_nid;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
ecg = EC_KEY_get0_group(ec);
|
||||
if (ecg == NULL)
|
||||
return 0;
|
||||
|
||||
curve_nid = EC_GROUP_get_curve_name(ecg);
|
||||
|
||||
if (curve_nid == NID_undef) {
|
||||
/* explicit parameters */
|
||||
|
||||
/*
|
||||
* TODO(3.0): should we support explicit parameters curves?
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
/* named curve */
|
||||
const char *curve_name = NULL;
|
||||
|
||||
if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callers of params_to_key MUST make sure that params_to_domparams has been
|
||||
* called before!
|
||||
*
|
||||
* This function only imports the bare keypair, domain parameters and other
|
||||
* parameters are imported separately, and domain parameters are required to
|
||||
* define a keypair.
|
||||
*/
|
||||
static ossl_inline
|
||||
int params_to_key(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
|
||||
{
|
||||
const OSSL_PARAM *param_priv_key, *param_pub_key;
|
||||
BIGNUM *priv_key = NULL;
|
||||
unsigned char *pub_key = NULL;
|
||||
size_t pub_key_len;
|
||||
const EC_GROUP *ecg = NULL;
|
||||
EC_POINT *pub_point = NULL;
|
||||
int ok = 0;
|
||||
|
||||
ecg = EC_KEY_get0_group(ec);
|
||||
if (ecg == NULL)
|
||||
return 0;
|
||||
|
||||
param_priv_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
||||
param_pub_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
|
||||
|
||||
/*
|
||||
* We want to have at least a public key either way, so we end up
|
||||
* requiring it unconditionally.
|
||||
*/
|
||||
if (param_pub_key == NULL
|
||||
|| !OSSL_PARAM_get_octet_string(param_pub_key,
|
||||
(void **)&pub_key, 0, &pub_key_len)
|
||||
|| (pub_point = EC_POINT_new(ecg)) == NULL
|
||||
|| !EC_POINT_oct2point(ecg, pub_point,
|
||||
pub_key, pub_key_len, NULL))
|
||||
goto err;
|
||||
|
||||
if (param_priv_key != NULL && include_private) {
|
||||
int fixed_top;
|
||||
const BIGNUM *order;
|
||||
|
||||
/*
|
||||
* Key import/export should never leak the bit length of the secret
|
||||
* scalar in the key.
|
||||
*
|
||||
* For this reason, on export we use padded BIGNUMs with fixed length.
|
||||
*
|
||||
* When importing we also should make sure that, even if short lived,
|
||||
* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
|
||||
* soon as possible, so that any processing of this BIGNUM might opt for
|
||||
* constant time implementations in the backend.
|
||||
*
|
||||
* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
|
||||
* to preallocate the BIGNUM internal buffer to a fixed public size big
|
||||
* enough that operations performed during the processing never trigger
|
||||
* a realloc which would leak the size of the scalar through memory
|
||||
* accesses.
|
||||
*
|
||||
* Fixed Length
|
||||
* ------------
|
||||
*
|
||||
* The order of the large prime subgroup of the curve is our choice for
|
||||
* a fixed public size, as that is generally the upper bound for
|
||||
* generating a private key in EC cryptosystems and should fit all valid
|
||||
* secret scalars.
|
||||
*
|
||||
* For padding on export we just use the bit length of the order
|
||||
* converted to bytes (rounding up).
|
||||
*
|
||||
* For preallocating the BIGNUM storage we look at the number of "words"
|
||||
* required for the internal representation of the order, and we
|
||||
* preallocate 2 extra "words" in case any of the subsequent processing
|
||||
* might temporarily overflow the order length.
|
||||
*/
|
||||
order = EC_GROUP_get0_order(ecg);
|
||||
if (order == NULL || BN_is_zero(order))
|
||||
goto err;
|
||||
|
||||
fixed_top = bn_get_top(order) + 2;
|
||||
|
||||
if ((priv_key = BN_new()) == NULL)
|
||||
goto err;
|
||||
if (bn_wexpand(priv_key, fixed_top) == NULL)
|
||||
goto err;
|
||||
BN_set_flags(priv_key, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (priv_key != NULL
|
||||
&& !EC_KEY_set_private_key(ec, priv_key))
|
||||
goto err;
|
||||
|
||||
if (!EC_KEY_set_public_key(ec, pub_point))
|
||||
goto err;
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_clear_free(priv_key);
|
||||
OPENSSL_free(pub_key);
|
||||
EC_POINT_free(pub_point);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callers of key_to_params MUST make sure that domparams_to_params is also
|
||||
* called!
|
||||
*
|
||||
* This function only exports the bare keypair, domain parameters and other
|
||||
* parameters are exported separately.
|
||||
*/
|
||||
static ossl_inline
|
||||
int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private)
|
||||
{
|
||||
const BIGNUM *priv_key = NULL;
|
||||
const EC_POINT *pub_point = NULL;
|
||||
const EC_GROUP *ecg = NULL;
|
||||
unsigned char *pub_key = NULL;
|
||||
size_t pub_key_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (eckey == NULL)
|
||||
return 0;
|
||||
|
||||
ecg = EC_KEY_get0_group(eckey);
|
||||
priv_key = EC_KEY_get0_private_key(eckey);
|
||||
pub_point = EC_KEY_get0_public_key(eckey);
|
||||
|
||||
/* group and public_key must be present, priv_key is optional */
|
||||
if (ecg == NULL || pub_point == NULL)
|
||||
return 0;
|
||||
if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
|
||||
POINT_CONVERSION_COMPRESSED,
|
||||
&pub_key, NULL)) == 0)
|
||||
return 0;
|
||||
|
||||
if (!ossl_param_bld_push_octet_string(tmpl,
|
||||
OSSL_PKEY_PARAM_PUB_KEY,
|
||||
pub_key, pub_key_len))
|
||||
goto err;
|
||||
|
||||
if (priv_key != NULL && include_private) {
|
||||
size_t sz;
|
||||
int ecbits;
|
||||
|
||||
/*
|
||||
* Key import/export should never leak the bit length of the secret
|
||||
* scalar in the key.
|
||||
*
|
||||
* For this reason, on export we use padded BIGNUMs with fixed length.
|
||||
*
|
||||
* When importing we also should make sure that, even if short lived,
|
||||
* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
|
||||
* soon as possible, so that any processing of this BIGNUM might opt for
|
||||
* constant time implementations in the backend.
|
||||
*
|
||||
* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
|
||||
* to preallocate the BIGNUM internal buffer to a fixed public size big
|
||||
* enough that operations performed during the processing never trigger
|
||||
* a realloc which would leak the size of the scalar through memory
|
||||
* accesses.
|
||||
*
|
||||
* Fixed Length
|
||||
* ------------
|
||||
*
|
||||
* The order of the large prime subgroup of the curve is our choice for
|
||||
* a fixed public size, as that is generally the upper bound for
|
||||
* generating a private key in EC cryptosystems and should fit all valid
|
||||
* secret scalars.
|
||||
*
|
||||
* For padding on export we just use the bit length of the order
|
||||
* converted to bytes (rounding up).
|
||||
*
|
||||
* For preallocating the BIGNUM storage we look at the number of "words"
|
||||
* required for the internal representation of the order, and we
|
||||
* preallocate 2 extra "words" in case any of the subsequent processing
|
||||
* might temporarily overflow the order length.
|
||||
*/
|
||||
ecbits = EC_GROUP_order_bits(ecg);
|
||||
if (ecbits <= 0)
|
||||
goto err;
|
||||
sz = (ecbits + 7 ) / 8;
|
||||
if (!ossl_param_bld_push_BN_pad(tmpl,
|
||||
OSSL_PKEY_PARAM_PRIV_KEY,
|
||||
priv_key, sz))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(pub_key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p)
|
||||
{
|
||||
const EC_GROUP *ecg = EC_KEY_get0_group(ec);
|
||||
const BIGNUM *cofactor;
|
||||
int mode;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &mode))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* mode can be only 0 for disable, or 1 for enable here.
|
||||
*
|
||||
* This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
|
||||
* also supports mode == -1 with the meaning of "reset to the default for
|
||||
* the associated key".
|
||||
*/
|
||||
if (mode < 0 || mode > 1)
|
||||
return 0;
|
||||
|
||||
if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
|
||||
return 0;
|
||||
|
||||
/* ECDH cofactor mode has no effect if cofactor is 1 */
|
||||
if (BN_is_one(cofactor))
|
||||
return 1;
|
||||
|
||||
if (mode == 1)
|
||||
EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
|
||||
else if (mode == 0)
|
||||
EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int params_to_otherparams(EC_KEY *ec, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
|
||||
if (p != NULL && !ec_set_param_ecdh_cofactor_mode(ec, p))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
|
||||
{
|
||||
int ecdh_cofactor_mode = 0;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
ecdh_cofactor_mode =
|
||||
(EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
||||
if (!ossl_param_bld_push_int(tmpl,
|
||||
OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
|
||||
ecdh_cofactor_mode))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void *ec_newdata(void *provctx)
|
||||
{
|
||||
return EC_KEY_new();
|
||||
}
|
||||
|
||||
static
|
||||
void ec_freedata(void *keydata)
|
||||
{
|
||||
EC_KEY_free(keydata);
|
||||
}
|
||||
|
||||
static
|
||||
int ec_has(void *keydata, int selection)
|
||||
{
|
||||
EC_KEY *ec = keydata;
|
||||
int ok = 0;
|
||||
|
||||
if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
|
||||
ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && (EC_KEY_get0_group(ec) != NULL);
|
||||
/*
|
||||
* We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be available,
|
||||
* so no extra check is needed other than the previous one against
|
||||
* EC_POSSIBLE_SELECTIONS.
|
||||
*/
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ec_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const EC_KEY *ec1 = keydata1;
|
||||
const EC_KEY *ec2 = keydata2;
|
||||
const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
|
||||
const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
|
||||
int ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && group_a != NULL && group_b != NULL
|
||||
&& EC_GROUP_cmp(group_a, group_b, NULL) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
|
||||
const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
|
||||
const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
|
||||
|
||||
ok = ok && BN_cmp(pa, pb) == 0;
|
||||
}
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
|
||||
const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
|
||||
const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
|
||||
|
||||
ok = ok && EC_POINT_cmp(group_b, pa, pb, NULL);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
EC_KEY *ec = keydata;
|
||||
int ok = 0;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* In this implementation, we can export/import only keydata in the
|
||||
* following combinations:
|
||||
* - domain parameters only
|
||||
* - public key with associated domain parameters (+optional other params)
|
||||
* - private key with associated public key and domain parameters
|
||||
* (+optional other params)
|
||||
*
|
||||
* This means:
|
||||
* - domain parameters must always be requested
|
||||
* - private key must be requested alongside public key
|
||||
* - other parameters must be requested only alongside a key
|
||||
*/
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && params_to_domparams(ec, params);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
|
||||
int include_private =
|
||||
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
|
||||
|
||||
ok = ok && params_to_key(ec, params, include_private);
|
||||
}
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
||||
ok = ok && params_to_otherparams(ec, params);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
|
||||
void *cbarg)
|
||||
{
|
||||
EC_KEY *ec = keydata;
|
||||
OSSL_PARAM_BLD tmpl;
|
||||
OSSL_PARAM *params = NULL;
|
||||
int ok = 1;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* In this implementation, we can export/import only keydata in the
|
||||
* following combinations:
|
||||
* - domain parameters only
|
||||
* - public key with associated domain parameters (+optional other params)
|
||||
* - private key with associated public key and domain parameters
|
||||
* (+optional other params)
|
||||
*
|
||||
* This means:
|
||||
* - domain parameters must always be requested
|
||||
* - private key must be requested alongside public key
|
||||
* - other parameters must be requested only alongside a key
|
||||
*/
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return 0;
|
||||
|
||||
ossl_param_bld_init(&tmpl);
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && domparams_to_params(ec, &tmpl);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
|
||||
int include_private =
|
||||
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
|
||||
|
||||
ok = ok && key_to_params(ec, &tmpl, include_private);
|
||||
}
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
||||
ok = ok && otherparams_to_params(ec, &tmpl);
|
||||
|
||||
if (!ok
|
||||
|| (params = ossl_param_bld_to_param(&tmpl)) == NULL)
|
||||
return 0;
|
||||
|
||||
ok = param_cb(params, cbarg);
|
||||
ossl_param_bld_free(params);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* IMEXPORT = IMPORT + EXPORT */
|
||||
|
||||
# define EC_IMEXPORTABLE_DOM_PARAMETERS \
|
||||
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_NAME, NULL, 0)
|
||||
# define EC_IMEXPORTABLE_PUBLIC_KEY \
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
|
||||
# define EC_IMEXPORTABLE_PRIVATE_KEY \
|
||||
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
|
||||
# define EC_IMEXPORTABLE_OTHER_PARAMETERS \
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL)
|
||||
|
||||
/*
|
||||
* Include all the possible combinations of OSSL_PARAM arrays for
|
||||
* ec_imexport_types().
|
||||
*
|
||||
* They are in a separate file as it is ~100 lines of unreadable and
|
||||
* uninteresting machine generated stuff.
|
||||
*
|
||||
* TODO(3.0): the generated list looks quite ugly, as to cover all possible
|
||||
* combinations of the bits in `selection`, it also includes combinations that
|
||||
* are not really useful: we might want to consider alternatives to this
|
||||
* solution.
|
||||
*/
|
||||
#include "ec_kmgmt_imexport.inc"
|
||||
|
||||
static ossl_inline
|
||||
const OSSL_PARAM *ec_imexport_types(int selection)
|
||||
{
|
||||
int type_select = 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
type_select += 1;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
type_select += 2;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
type_select += 4;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
||||
type_select += 8;
|
||||
return ec_types[type_select];
|
||||
}
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_import_types(int selection)
|
||||
{
|
||||
return ec_imexport_types(selection);
|
||||
}
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_export_types(int selection)
|
||||
{
|
||||
return ec_imexport_types(selection);
|
||||
}
|
||||
|
||||
static
|
||||
int ec_get_params(void *key, OSSL_PARAM params[])
|
||||
{
|
||||
EC_KEY *eck = key;
|
||||
const EC_GROUP *ecg = NULL;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
ecg = EC_KEY_get0_group(eck);
|
||||
if (ecg == NULL)
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
|
||||
&& !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
|
||||
return 0;
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
|
||||
&& !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
|
||||
return 0;
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
|
||||
int ecbits, sec_bits;
|
||||
|
||||
ecbits = EC_GROUP_order_bits(ecg);
|
||||
|
||||
/*
|
||||
* The following estimates are based on the values published
|
||||
* in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
|
||||
* at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
|
||||
*
|
||||
* Note that the above reference explicitly categorizes algorithms in a
|
||||
* discrete set of values {80, 112, 128, 192, 256}, and that it is
|
||||
* relevant only for NIST approved Elliptic Curves, while OpenSSL
|
||||
* applies the same logic also to other curves.
|
||||
*
|
||||
* Classifications produced by other standardazing bodies might differ,
|
||||
* so the results provided for "bits of security" by this provider are
|
||||
* to be considered merely indicative, and it is the users'
|
||||
* responsibility to compare these values against the normative
|
||||
* references that may be relevant for their intent and purposes.
|
||||
*/
|
||||
if (ecbits >= 512)
|
||||
sec_bits = 256;
|
||||
else if (ecbits >= 384)
|
||||
sec_bits = 192;
|
||||
else if (ecbits >= 256)
|
||||
sec_bits = 128;
|
||||
else if (ecbits >= 224)
|
||||
sec_bits = 112;
|
||||
else if (ecbits >= 160)
|
||||
sec_bits = 80;
|
||||
else
|
||||
sec_bits = ecbits / 2;
|
||||
|
||||
if (!OSSL_PARAM_set_int(p, sec_bits))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
|
||||
if (p != NULL) {
|
||||
int ecdh_cofactor_mode = 0;
|
||||
|
||||
ecdh_cofactor_mode =
|
||||
(EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
||||
|
||||
if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM ec_known_gettable_params[] = {
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_gettable_params(void)
|
||||
{
|
||||
return ec_known_gettable_params;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM ec_known_settable_params[] = {
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_settable_params(void)
|
||||
{
|
||||
return ec_known_settable_params;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_set_params(void *key, const OSSL_PARAM params[])
|
||||
{
|
||||
EC_KEY *eck = key;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
|
||||
if (p != NULL && !ec_set_param_ecdh_cofactor_mode(eck, p))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH ec_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
|
||||
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
|
||||
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
|
||||
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
|
||||
(void (*)(void))ec_query_operation_name },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is meant to be included from ec_kmgmt.c
|
||||
*/
|
||||
|
||||
static const OSSL_PARAM ec_private_key_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_public_key_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_key_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_dom_parameters_types[] = {
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_5_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_6_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_key_domp_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_other_parameters_types[] = {
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_9_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_10_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_11_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_all_parameters_types[] = {
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_13_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_14_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_all_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *ec_types[] = {
|
||||
NULL,
|
||||
ec_private_key_types,
|
||||
ec_public_key_types,
|
||||
ec_key_types,
|
||||
ec_dom_parameters_types,
|
||||
ec_5_types,
|
||||
ec_6_types,
|
||||
ec_key_domp_types,
|
||||
ec_other_parameters_types,
|
||||
ec_9_types,
|
||||
ec_10_types,
|
||||
ec_11_types,
|
||||
ec_all_parameters_types,
|
||||
ec_13_types,
|
||||
ec_14_types,
|
||||
ec_all_types
|
||||
};
|
||||
@@ -154,8 +154,8 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
|
||||
}
|
||||
|
||||
static const OSSL_PARAM ecx_key_types[] = {
|
||||
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
|
||||
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *ecx_imexport_types(int selection)
|
||||
|
||||
@@ -26,6 +26,7 @@ static OSSL_OP_keymgmt_free_fn rsa_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn rsa_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn rsa_gettable_params;
|
||||
static OSSL_OP_keymgmt_has_fn rsa_has;
|
||||
static OSSL_OP_keymgmt_match_fn rsa_match;
|
||||
static OSSL_OP_keymgmt_validate_fn rsa_validate;
|
||||
static OSSL_OP_keymgmt_import_fn rsa_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn rsa_import_types;
|
||||
@@ -197,6 +198,21 @@ static int rsa_has(void *keydata, int selection)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int rsa_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const RSA *rsa1 = keydata1;
|
||||
const RSA *rsa2 = keydata2;
|
||||
int ok = 1;
|
||||
|
||||
/* There is always an |e| */
|
||||
ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok && BN_cmp(RSA_get0_n(rsa1), RSA_get0_n(rsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok && BN_cmp(RSA_get0_d(rsa1), RSA_get0_d(rsa2)) == 0;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
RSA *rsa = keydata;
|
||||
@@ -393,6 +409,7 @@ const OSSL_DISPATCH rsa_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
|
||||
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
|
||||
|
||||
@@ -5,6 +5,7 @@ $SERIALIZER_GOAL=../../libimplementations.a
|
||||
$RSA_GOAL=../../libimplementations.a
|
||||
$DH_GOAL=../../libimplementations.a
|
||||
$DSA_GOAL=../../libimplementations.a
|
||||
$ECX_GOAL=../../libimplementations.a
|
||||
|
||||
SOURCE[$SERIALIZER_GOAL]=serializer_common.c
|
||||
SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c
|
||||
@@ -14,3 +15,6 @@ ENDIF
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=serializer_dsa.c serializer_dsa_priv.c serializer_dsa_pub.c serializer_dsa_param.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ECX_GOAL]=serializer_ecx.c serializer_ecx_priv.c serializer_ecx_pub.c
|
||||
ENDIF
|
||||
@@ -243,6 +243,36 @@ int ossl_prov_print_labeled_bignum(BIO *out, const char *label,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Number of octets per line */
|
||||
#define LABELED_BUF_PRINT_WIDTH 15
|
||||
|
||||
int ossl_prov_print_labeled_buf(BIO *out, const char *label,
|
||||
const unsigned char *buf, size_t buflen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (ossl_prov_bio_printf(out, "%s\n", label) <= 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < buflen; i++) {
|
||||
if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
|
||||
if (i > 0 && ossl_prov_bio_printf(out, "\n") <= 0)
|
||||
return 0;
|
||||
if (ossl_prov_bio_printf(out, " ") <= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ossl_prov_bio_printf(out, "%02x%s", buf[i],
|
||||
(i == buflen - 1) ? "" : ":") <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (ossl_prov_bio_printf(out, "\n") <= 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* p2s = param to asn1_string, k2d = key to der */
|
||||
int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
int (*p2s)(const void *obj, int nid,
|
||||
@@ -254,7 +284,7 @@ int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
return 0;
|
||||
@@ -290,7 +320,7 @@ int ossl_prov_write_priv_pem_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
return 0;
|
||||
@@ -325,7 +355,7 @@ int ossl_prov_write_pub_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
X509_PUBKEY *xpk = NULL;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
@@ -350,7 +380,7 @@ int ossl_prov_write_pub_pem_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
X509_PUBKEY *xpk = NULL;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include "prov/bio.h" /* ossl_prov_bio_printf() */
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
@@ -126,7 +132,7 @@ static int dh_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
|
||||
static int dh_pub_print(void *ctx, void *dh, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
return ossl_prov_print_dh(out, dh, 0);
|
||||
return ossl_prov_print_dh(out, dh, dh_print_pub);
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dh_pub_der_serializer_functions[] = {
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "crypto/ecx.h"
|
||||
#include "prov/bio.h" /* ossl_prov_bio_printf() */
|
||||
#include "prov/implementations.h" /* ecx_keymgmt_functions */
|
||||
#include "serializer_local.h"
|
||||
|
||||
void ecx_get_new_free_import(ECX_KEY_TYPE type,
|
||||
OSSL_OP_keymgmt_new_fn **ecx_new,
|
||||
OSSL_OP_keymgmt_free_fn **ecx_free,
|
||||
OSSL_OP_keymgmt_import_fn **ecx_import)
|
||||
{
|
||||
if (type == ECX_KEY_TYPE_X25519) {
|
||||
*ecx_new = ossl_prov_get_keymgmt_new(x25519_keymgmt_functions);
|
||||
*ecx_free = ossl_prov_get_keymgmt_free(x25519_keymgmt_functions);
|
||||
*ecx_import = ossl_prov_get_keymgmt_import(x25519_keymgmt_functions);
|
||||
} else if (type == ECX_KEY_TYPE_X448) {
|
||||
*ecx_new = ossl_prov_get_keymgmt_new(x448_keymgmt_functions);
|
||||
*ecx_free = ossl_prov_get_keymgmt_free(x448_keymgmt_functions);
|
||||
*ecx_import = ossl_prov_get_keymgmt_import(x448_keymgmt_functions);
|
||||
} else {
|
||||
*ecx_new = NULL;
|
||||
*ecx_free = NULL;
|
||||
*ecx_import = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type)
|
||||
{
|
||||
const char *type_label = NULL;
|
||||
|
||||
switch (type) {
|
||||
case ecx_print_priv:
|
||||
switch (ecxkey->keylen) {
|
||||
case X25519_KEYLEN:
|
||||
type_label = "X25519 Private-Key";
|
||||
break;
|
||||
case X448_KEYLEN:
|
||||
type_label = "X448 Private-Key";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ecx_print_pub:
|
||||
switch (ecxkey->keylen) {
|
||||
case X25519_KEYLEN:
|
||||
type_label = "X25519 Public-Key";
|
||||
break;
|
||||
case X448_KEYLEN:
|
||||
type_label = "X448 Public-Key";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == ecx_print_priv && ecxkey->privkey == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ossl_prov_bio_printf(out, "%s:\n", type_label) <= 0)
|
||||
return 0;
|
||||
if (type == ecx_print_priv
|
||||
&& !ossl_prov_print_labeled_buf(out, "priv:", ecxkey->privkey,
|
||||
ecxkey->keylen))
|
||||
return 0;
|
||||
if (!ossl_prov_print_labeled_buf(out, "pub:", ecxkey->pubkey,
|
||||
ecxkey->keylen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ossl_prov_ecx_pub_to_der(const void *vecxkey, unsigned char **pder)
|
||||
{
|
||||
const ECX_KEY *ecxkey = vecxkey;
|
||||
unsigned char *keyblob;
|
||||
|
||||
if (ecxkey == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
keyblob = OPENSSL_memdup(ecxkey->pubkey, ecxkey->keylen);
|
||||
if (keyblob == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pder = keyblob;
|
||||
return ecxkey->keylen;
|
||||
}
|
||||
|
||||
int ossl_prov_ecx_priv_to_der(const void *vecxkey, unsigned char **pder)
|
||||
{
|
||||
const ECX_KEY *ecxkey = vecxkey;
|
||||
ASN1_OCTET_STRING oct;
|
||||
int keybloblen;
|
||||
|
||||
if (ecxkey == NULL || ecxkey->privkey == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
oct.data = ecxkey->privkey;
|
||||
oct.length = ecxkey->keylen;
|
||||
oct.flags = 0;
|
||||
|
||||
keybloblen = i2d_ASN1_OCTET_STRING(&oct, pder);
|
||||
if (keybloblen < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return keybloblen;
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/types.h>
|
||||
#include <openssl/params.h>
|
||||
#include "prov/bio.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "serializer_local.h"
|
||||
|
||||
static OSSL_OP_serializer_newctx_fn x25519_priv_newctx;
|
||||
static OSSL_OP_serializer_newctx_fn x448_priv_newctx;
|
||||
static OSSL_OP_serializer_freectx_fn ecx_priv_freectx;
|
||||
static OSSL_OP_serializer_set_ctx_params_fn ecx_priv_set_ctx_params;
|
||||
static OSSL_OP_serializer_settable_ctx_params_fn ecx_priv_settable_ctx_params;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_priv_der_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_priv_der;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_priv_pem_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_priv_pem;
|
||||
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_priv_print_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_priv_print;
|
||||
|
||||
/*
|
||||
* Context used for private key serialization.
|
||||
*/
|
||||
struct ecx_priv_ctx_st {
|
||||
void *provctx;
|
||||
|
||||
struct pkcs8_encrypt_ctx_st sc;
|
||||
ECX_KEY_TYPE type;
|
||||
};
|
||||
|
||||
/* Private key : context */
|
||||
static void *ecx_priv_newctx(void *provctx, ECX_KEY_TYPE type)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
ctx->provctx = provctx;
|
||||
|
||||
/* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */
|
||||
ctx->sc.pbe_nid = -1;
|
||||
ctx->type = type;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void *x25519_priv_newctx(void *provctx)
|
||||
{
|
||||
return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X25519);
|
||||
}
|
||||
|
||||
static void *x448_priv_newctx(void *provctx)
|
||||
{
|
||||
return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X448);
|
||||
}
|
||||
|
||||
static void ecx_priv_freectx(void *vctx)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
|
||||
EVP_CIPHER_free(ctx->sc.cipher);
|
||||
OPENSSL_free(ctx->sc.cipher_pass);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *ecx_priv_settable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM settables[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0),
|
||||
OSSL_PARAM_END,
|
||||
};
|
||||
|
||||
return settables;
|
||||
}
|
||||
|
||||
static int ecx_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER);
|
||||
if (p != NULL) {
|
||||
const OSSL_PARAM *propsp =
|
||||
OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES);
|
||||
const char *props;
|
||||
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
props = (propsp != NULL ? propsp->data : NULL);
|
||||
|
||||
EVP_CIPHER_free(ctx->sc.cipher);
|
||||
ctx->sc.cipher_intent = p->data != NULL;
|
||||
if (p->data != NULL
|
||||
&& ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props))
|
||||
== NULL))
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS);
|
||||
if (p != NULL) {
|
||||
OPENSSL_free(ctx->sc.cipher_pass);
|
||||
ctx->sc.cipher_pass = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0,
|
||||
&ctx->sc.cipher_pass_length))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Private key : DER */
|
||||
static int ecx_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_priv_der(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_priv_der(void *vctx, void *vecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
ECX_KEY *ecxkey = vecxkey;
|
||||
int ret;
|
||||
int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
|
||||
: EVP_PKEY_X448;
|
||||
|
||||
ctx->sc.cb = cb;
|
||||
ctx->sc.cbarg = cbarg;
|
||||
|
||||
ret = ossl_prov_write_priv_der_from_obj(out, ecxkey,
|
||||
type,
|
||||
NULL,
|
||||
ossl_prov_ecx_priv_to_der,
|
||||
&ctx->sc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Private key : PEM */
|
||||
static int ecx_priv_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_priv_pem(ctx->provctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_priv_pem(void *vctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
int ret;
|
||||
int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
|
||||
: EVP_PKEY_X448;
|
||||
|
||||
ctx->sc.cb = cb;
|
||||
ctx->sc.cbarg = cbarg;
|
||||
|
||||
ret = ossl_prov_write_priv_pem_from_obj(out, ecxkey,
|
||||
type,
|
||||
NULL,
|
||||
ossl_prov_ecx_priv_to_der,
|
||||
&ctx->sc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ecx_priv_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_priv_print(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_priv_print(void *ctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
return ossl_prov_print_ecx(out, ecxkey, ecx_print_priv);
|
||||
}
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
|
||||
const OSSL_DISPATCH alg##_priv_##type##_serializer_functions[] = { \
|
||||
{ OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, \
|
||||
(void (*)(void))ecx_priv_set_ctx_params }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))ecx_priv_settable_ctx_params }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
|
||||
(void (*)(void))ecx_priv_##type##_data }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
|
||||
(void (*)(void))ecx_priv_##type }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, der) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
|
||||
const OSSL_DISPATCH alg##_priv_print_serializer_functions[] = { \
|
||||
{ OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
|
||||
(void (*)(void))ecx_priv_print }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
|
||||
(void (*)(void))ecx_priv_print_data }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/types.h>
|
||||
#include <openssl/params.h>
|
||||
#include "prov/bio.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "serializer_local.h"
|
||||
|
||||
static OSSL_OP_serializer_newctx_fn x25519_pub_newctx;
|
||||
static OSSL_OP_serializer_newctx_fn x448_pub_newctx;
|
||||
static OSSL_OP_serializer_freectx_fn ecx_pub_freectx;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_pub_der_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_pub_der;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_pub_pem_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_pub_pem;
|
||||
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_pub_print_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_pub_print;
|
||||
|
||||
/*
|
||||
* Context used for public key serialization.
|
||||
*/
|
||||
struct ecx_pub_ctx_st {
|
||||
void *provctx;
|
||||
ECX_KEY_TYPE type;
|
||||
};
|
||||
|
||||
/* Public key : context */
|
||||
static void *ecx_pub_newctx(void *provctx, ECX_KEY_TYPE type)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
ctx->provctx = provctx;
|
||||
ctx->type = type;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void *x25519_pub_newctx(void *provctx)
|
||||
{
|
||||
return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X25519);
|
||||
}
|
||||
|
||||
static void *x448_pub_newctx(void *provctx)
|
||||
{
|
||||
return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X448);
|
||||
}
|
||||
|
||||
static void ecx_pub_freectx(void *ctx)
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
/* Public key : DER */
|
||||
static int ecx_pub_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_pub_der(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_pub_der(void *vctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
|
||||
return ossl_prov_write_pub_der_from_obj(out, ecxkey,
|
||||
ctx->type == ECX_KEY_TYPE_X25519
|
||||
? EVP_PKEY_X25519 : EVP_PKEY_X448,
|
||||
NULL,
|
||||
ossl_prov_ecx_pub_to_der);
|
||||
}
|
||||
|
||||
/* Public key : PEM */
|
||||
static int ecx_pub_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_pub_pem(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_pub_pem(void *vctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
|
||||
return ossl_prov_write_pub_pem_from_obj(out, ecxkey,
|
||||
ctx->type == ECX_KEY_TYPE_X25519
|
||||
? EVP_PKEY_X25519 : EVP_PKEY_X448,
|
||||
NULL,
|
||||
ossl_prov_ecx_pub_to_der);
|
||||
|
||||
}
|
||||
|
||||
static int ecx_pub_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_pub_print(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_pub_print(void *ctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
return ossl_prov_print_ecx(out, ecxkey, ecx_print_pub);
|
||||
}
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
|
||||
const OSSL_DISPATCH alg##_pub_##type##_serializer_functions[] = { \
|
||||
{ OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_pub_newctx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_pub_freectx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
|
||||
(void (*)(void))ecx_pub_##type##_data }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
|
||||
(void (*)(void))ecx_pub_##type }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, der) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, print)
|
||||
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <openssl/asn1.h> /* i2d_of_void */
|
||||
#include <openssl/x509.h> /* X509_SIG */
|
||||
#include <openssl/types.h>
|
||||
#include <crypto/ecx.h>
|
||||
|
||||
struct pkcs8_encrypt_ctx_st {
|
||||
/* Set to 1 if intending to encrypt/decrypt, otherwise 0 */
|
||||
@@ -30,6 +31,11 @@ struct pkcs8_encrypt_ctx_st {
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ECX_KEY_TYPE_X25519,
|
||||
ECX_KEY_TYPE_X448
|
||||
} ECX_KEY_TYPE;
|
||||
|
||||
OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns);
|
||||
OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns);
|
||||
OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns);
|
||||
@@ -49,8 +55,15 @@ int ossl_prov_prepare_dh_params(const void *dh, int nid,
|
||||
int ossl_prov_dh_pub_to_der(const void *dh, unsigned char **pder);
|
||||
int ossl_prov_dh_priv_to_der(const void *dh, unsigned char **pder);
|
||||
|
||||
void ecx_get_new_free_import(ECX_KEY_TYPE type,
|
||||
OSSL_OP_keymgmt_new_fn **ecx_new,
|
||||
OSSL_OP_keymgmt_free_fn **ecx_free,
|
||||
OSSL_OP_keymgmt_import_fn **ecx_import);
|
||||
int ossl_prov_ecx_pub_to_der(const void *ecxkey, unsigned char **pder);
|
||||
int ossl_prov_ecx_priv_to_der(const void *ecxkey, unsigned char **pder);
|
||||
|
||||
int ossl_prov_prepare_dsa_params(const void *dsa, int nid,
|
||||
ASN1_STRING **pstr, int *pstrtype);
|
||||
ASN1_STRING **pstr, int *pstrtype);
|
||||
/*
|
||||
* Special variant of ossl_prov_prepare_dsa_params() that requires all
|
||||
* three parameters (P, Q and G) to be set. This is used when serializing
|
||||
@@ -63,6 +76,8 @@ int ossl_prov_dsa_priv_to_der(const void *dsa, unsigned char **pder);
|
||||
|
||||
int ossl_prov_print_labeled_bignum(BIO *out, const char *label,
|
||||
const BIGNUM *bn);
|
||||
int ossl_prov_print_labeled_buf(BIO *out, const char *label,
|
||||
const unsigned char *buf, size_t buflen);
|
||||
int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv);
|
||||
|
||||
enum dh_print_type {
|
||||
@@ -81,6 +96,15 @@ enum dsa_print_type {
|
||||
|
||||
int ossl_prov_print_dsa(BIO *out, DSA *dsa, enum dsa_print_type type);
|
||||
|
||||
enum ecx_print_type {
|
||||
ecx_print_priv,
|
||||
ecx_print_pub
|
||||
};
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type);
|
||||
#endif
|
||||
|
||||
int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
int (*p2s)(const void *obj, int nid,
|
||||
ASN1_STRING **str,
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
# switch each to the Legacy provider when needed.
|
||||
|
||||
$DSA_GOAL=../../libimplementations.a
|
||||
$RSA_GOAL=../../libimplementations.a
|
||||
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=dsa.c
|
||||
ENDIF
|
||||
|
||||
SOURCE[$RSA_GOAL]=rsa.c
|
||||
|
||||
|
||||
@@ -0,0 +1,1115 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* RSA low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/sizes.h"
|
||||
#include "crypto/rsa.h"
|
||||
#include "prov/providercommonerr.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
|
||||
static OSSL_OP_signature_newctx_fn rsa_newctx;
|
||||
static OSSL_OP_signature_sign_init_fn rsa_signature_init;
|
||||
static OSSL_OP_signature_verify_init_fn rsa_signature_init;
|
||||
static OSSL_OP_signature_verify_recover_init_fn rsa_signature_init;
|
||||
static OSSL_OP_signature_sign_fn rsa_sign;
|
||||
static OSSL_OP_signature_verify_fn rsa_verify;
|
||||
static OSSL_OP_signature_verify_recover_fn rsa_verify_recover;
|
||||
static OSSL_OP_signature_digest_sign_init_fn rsa_digest_signverify_init;
|
||||
static OSSL_OP_signature_digest_sign_update_fn rsa_digest_signverify_update;
|
||||
static OSSL_OP_signature_digest_sign_final_fn rsa_digest_sign_final;
|
||||
static OSSL_OP_signature_digest_verify_init_fn rsa_digest_signverify_init;
|
||||
static OSSL_OP_signature_digest_verify_update_fn rsa_digest_signverify_update;
|
||||
static OSSL_OP_signature_digest_verify_final_fn rsa_digest_verify_final;
|
||||
static OSSL_OP_signature_freectx_fn rsa_freectx;
|
||||
static OSSL_OP_signature_dupctx_fn rsa_dupctx;
|
||||
static OSSL_OP_signature_get_ctx_params_fn rsa_get_ctx_params;
|
||||
static OSSL_OP_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
|
||||
static OSSL_OP_signature_set_ctx_params_fn rsa_set_ctx_params;
|
||||
static OSSL_OP_signature_settable_ctx_params_fn rsa_settable_ctx_params;
|
||||
static OSSL_OP_signature_get_ctx_md_params_fn rsa_get_ctx_md_params;
|
||||
static OSSL_OP_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
|
||||
static OSSL_OP_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
|
||||
static OSSL_OP_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params;
|
||||
|
||||
static OSSL_ITEM padding_item[] = {
|
||||
{ RSA_PKCS1_PADDING, "pkcs1" },
|
||||
{ RSA_SSLV23_PADDING, "sslv23" },
|
||||
{ RSA_NO_PADDING, "none" },
|
||||
{ RSA_PKCS1_OAEP_PADDING, "oaep" }, /* Correct spelling first */
|
||||
{ RSA_PKCS1_OAEP_PADDING, "oeap" },
|
||||
{ RSA_X931_PADDING, "x931" },
|
||||
{ RSA_PKCS1_PSS_PADDING, "pss" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* What's passed as an actual key is defined by the KEYMGMT interface.
|
||||
* We happen to know that our KEYMGMT simply passes RSA structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
OPENSSL_CTX *libctx;
|
||||
RSA *rsa;
|
||||
|
||||
/*
|
||||
* Flag to determine if the hash function can be changed (1) or not (0)
|
||||
* Because it's dangerous to change during a DigestSign or DigestVerify
|
||||
* operation, this flag is cleared by their Init function, and set again
|
||||
* by their Final function.
|
||||
*/
|
||||
unsigned int flag_allow_md : 1;
|
||||
|
||||
/* The Algorithm Identifier of the combined signature agorithm */
|
||||
unsigned char aid[128];
|
||||
size_t aid_len;
|
||||
|
||||
/* main digest */
|
||||
EVP_MD *md;
|
||||
EVP_MD_CTX *mdctx;
|
||||
int mdnid;
|
||||
char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
|
||||
|
||||
/* RSA padding mode */
|
||||
int pad_mode;
|
||||
/* message digest for MGF1 */
|
||||
EVP_MD *mgf1_md;
|
||||
char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
|
||||
/* PSS salt length */
|
||||
int saltlen;
|
||||
/* Minimum salt length or -1 if no PSS parameter restriction */
|
||||
int min_saltlen;
|
||||
|
||||
/* Temp buffer */
|
||||
unsigned char *tbuf;
|
||||
|
||||
} PROV_RSA_CTX;
|
||||
|
||||
static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
|
||||
{
|
||||
if (prsactx->md != NULL)
|
||||
return EVP_MD_size(prsactx->md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsa_get_md_nid(const EVP_MD *md)
|
||||
{
|
||||
/*
|
||||
* Because the RSA library deals with NIDs, we need to translate.
|
||||
* We do so using EVP_MD_is_a(), and therefore need a name to NID
|
||||
* map.
|
||||
*/
|
||||
static const OSSL_ITEM name_to_nid[] = {
|
||||
{ NID_sha1, OSSL_DIGEST_NAME_SHA1 },
|
||||
{ NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
|
||||
{ NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
|
||||
{ NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
|
||||
{ NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
|
||||
{ NID_md5, OSSL_DIGEST_NAME_MD5 },
|
||||
{ NID_md5_sha1, OSSL_DIGEST_NAME_MD5_SHA1 },
|
||||
{ NID_md2, OSSL_DIGEST_NAME_MD2 },
|
||||
{ NID_md4, OSSL_DIGEST_NAME_MD4 },
|
||||
{ NID_mdc2, OSSL_DIGEST_NAME_MDC2 },
|
||||
{ NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 },
|
||||
{ NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
|
||||
{ NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
|
||||
{ NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
|
||||
{ NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
|
||||
};
|
||||
size_t i;
|
||||
int mdnid = NID_undef;
|
||||
|
||||
if (md == NULL)
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
|
||||
if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
|
||||
mdnid = (int)name_to_nid[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdnid == NID_undef)
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
|
||||
|
||||
end:
|
||||
return mdnid;
|
||||
}
|
||||
|
||||
static int rsa_check_padding(int mdnid, int padding)
|
||||
{
|
||||
if (padding == RSA_NO_PADDING) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
if (RSA_X931_hash_id(mdnid) == -1) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *rsa_newctx(void *provctx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
|
||||
|
||||
if (prsactx == NULL)
|
||||
return NULL;
|
||||
|
||||
prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
|
||||
prsactx->flag_allow_md = 1;
|
||||
return prsactx;
|
||||
}
|
||||
|
||||
/* True if PSS parameters are restricted */
|
||||
#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
|
||||
|
||||
static int rsa_signature_init(void *vprsactx, void *vrsa)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa))
|
||||
return 0;
|
||||
|
||||
RSA_free(prsactx->rsa);
|
||||
prsactx->rsa = vrsa;
|
||||
if (RSA_get0_pss_params(prsactx->rsa) != NULL)
|
||||
prsactx->pad_mode = RSA_PKCS1_PSS_PADDING;
|
||||
else
|
||||
prsactx->pad_mode = RSA_PKCS1_PADDING;
|
||||
/* Maximum for sign, auto for verify */
|
||||
prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
|
||||
prsactx->min_saltlen = -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
|
||||
const char *mdprops)
|
||||
{
|
||||
if (mdname != NULL) {
|
||||
EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
|
||||
int md_nid = rsa_get_md_nid(md);
|
||||
size_t algorithmidentifier_len = 0;
|
||||
const unsigned char *algorithmidentifier = NULL;
|
||||
|
||||
if (md == NULL)
|
||||
return 0;
|
||||
|
||||
if (!rsa_check_padding(md_nid, ctx->pad_mode)) {
|
||||
EVP_MD_free(md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(ctx->mdctx);
|
||||
EVP_MD_free(ctx->md);
|
||||
ctx->md = NULL;
|
||||
ctx->mdctx = NULL;
|
||||
ctx->mdname[0] = '\0';
|
||||
ctx->aid[0] = '\0';
|
||||
ctx->aid_len = 0;
|
||||
|
||||
algorithmidentifier =
|
||||
rsa_algorithmidentifier_encoding(md_nid, &algorithmidentifier_len);
|
||||
|
||||
ctx->md = md;
|
||||
ctx->mdnid = md_nid;
|
||||
OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
|
||||
if (algorithmidentifier != NULL) {
|
||||
memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
|
||||
ctx->aid_len = algorithmidentifier_len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
|
||||
const char *props)
|
||||
{
|
||||
if (ctx->mgf1_mdname[0] != '\0')
|
||||
EVP_MD_free(ctx->mgf1_md);
|
||||
|
||||
if ((ctx->mgf1_md = EVP_MD_fetch(ctx->libctx, mdname, props)) == NULL)
|
||||
return 0;
|
||||
OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setup_tbuf(PROV_RSA_CTX *ctx)
|
||||
{
|
||||
if (ctx->tbuf != NULL)
|
||||
return 1;
|
||||
if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void clean_tbuf(PROV_RSA_CTX *ctx)
|
||||
{
|
||||
if (ctx->tbuf != NULL)
|
||||
OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa));
|
||||
}
|
||||
|
||||
static void free_tbuf(PROV_RSA_CTX *ctx)
|
||||
{
|
||||
OPENSSL_clear_free(ctx->tbuf, RSA_size(ctx->rsa));
|
||||
ctx->tbuf = NULL;
|
||||
}
|
||||
|
||||
static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
|
||||
size_t sigsize, const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
int ret;
|
||||
size_t rsasize = RSA_size(prsactx->rsa);
|
||||
size_t mdsize = rsa_get_md_size(prsactx);
|
||||
|
||||
if (sig == NULL) {
|
||||
*siglen = rsasize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sigsize < (size_t)rsasize)
|
||||
return 0;
|
||||
|
||||
if (mdsize != 0) {
|
||||
if (tbslen != mdsize) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) {
|
||||
unsigned int sltmp;
|
||||
|
||||
if (prsactx->pad_mode != RSA_PKCS1_PADDING) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"only PKCS#1 padding supported with MDC2");
|
||||
return 0;
|
||||
}
|
||||
ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp,
|
||||
prsactx->rsa);
|
||||
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = sltmp;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (prsactx->pad_mode) {
|
||||
case RSA_X931_PADDING:
|
||||
if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!setup_tbuf(prsactx)) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(prsactx->tbuf, tbs, tbslen);
|
||||
prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid);
|
||||
ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf,
|
||||
sig, prsactx->rsa, RSA_X931_PADDING);
|
||||
clean_tbuf(prsactx);
|
||||
break;
|
||||
|
||||
case RSA_PKCS1_PADDING:
|
||||
{
|
||||
unsigned int sltmp;
|
||||
|
||||
ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp,
|
||||
prsactx->rsa);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = sltmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case RSA_PKCS1_PSS_PADDING:
|
||||
/* Check PSS restrictions */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
switch (prsactx->saltlen) {
|
||||
case RSA_PSS_SALTLEN_DIGEST:
|
||||
if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
if (prsactx->saltlen >= 0
|
||||
&& prsactx->saltlen < prsactx->min_saltlen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa,
|
||||
prsactx->tbuf, tbs,
|
||||
prsactx->md, prsactx->mgf1_md,
|
||||
prsactx->saltlen)) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf,
|
||||
sig, prsactx->rsa, RSA_NO_PADDING);
|
||||
clean_tbuf(prsactx);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"Only X.931, PKCS#1 v1.5 or PSS padding allowed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa,
|
||||
prsactx->pad_mode);
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
end:
|
||||
#endif
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*siglen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_verify_recover(void *vprsactx,
|
||||
unsigned char *rout,
|
||||
size_t *routlen,
|
||||
size_t routsize,
|
||||
const unsigned char *sig,
|
||||
size_t siglen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
int ret;
|
||||
|
||||
if (rout == NULL) {
|
||||
*routlen = RSA_size(prsactx->rsa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (prsactx->md != NULL) {
|
||||
switch (prsactx->pad_mode) {
|
||||
case RSA_X931_PADDING:
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
|
||||
RSA_X931_PADDING);
|
||||
if (ret < 1) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret--;
|
||||
if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (ret != EVP_MD_size(prsactx->md)) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
|
||||
"Should be %d, but got %d",
|
||||
EVP_MD_size(prsactx->md), ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*routlen = ret;
|
||||
if (routsize < (size_t)ret) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
memcpy(rout, prsactx->tbuf, ret);
|
||||
break;
|
||||
|
||||
case RSA_PKCS1_PADDING:
|
||||
{
|
||||
size_t sltmp;
|
||||
|
||||
ret = int_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp,
|
||||
sig, siglen, prsactx->rsa);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = sltmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"Only X.931 or PKCS#1 v1.5 padding allowed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa,
|
||||
prsactx->pad_mode);
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*routlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
|
||||
const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
size_t rslen;
|
||||
|
||||
if (prsactx->md != NULL) {
|
||||
switch (prsactx->pad_mode) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen,
|
||||
prsactx->rsa)) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
case RSA_X931_PADDING:
|
||||
if (rsa_verify_recover(prsactx, NULL, &rslen, 0, sig, siglen) <= 0)
|
||||
return 0;
|
||||
break;
|
||||
case RSA_PKCS1_PSS_PADDING:
|
||||
{
|
||||
int ret;
|
||||
size_t mdsize;
|
||||
|
||||
/* Check PSS restrictions */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
switch (prsactx->saltlen) {
|
||||
case RSA_PSS_SALTLEN_AUTO:
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN);
|
||||
return 0;
|
||||
case RSA_PSS_SALTLEN_DIGEST:
|
||||
if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) {
|
||||
ERR_raise(ERR_LIB_PROV,
|
||||
PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
if (prsactx->saltlen >= 0
|
||||
&& prsactx->saltlen < prsactx->min_saltlen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to check this for the RSA_verify_PKCS1_PSS_mgf1()
|
||||
* call
|
||||
*/
|
||||
mdsize = rsa_get_md_size(prsactx);
|
||||
if (tbslen != mdsize) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
|
||||
"Should be %d, but got %d",
|
||||
mdsize, tbslen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf,
|
||||
prsactx->rsa, RSA_NO_PADDING);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs,
|
||||
prsactx->md, prsactx->mgf1_md,
|
||||
prsactx->tbuf,
|
||||
prsactx->saltlen);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"Only X.931, PKCS#1 v1.5 or PSS padding allowed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
rslen = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
|
||||
prsactx->pad_mode);
|
||||
if (rslen == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
|
||||
const char *props, void *vrsa)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
prsactx->flag_allow_md = 0;
|
||||
if (!rsa_signature_init(vprsactx, vrsa)
|
||||
|| !rsa_setup_md(prsactx, mdname, props))
|
||||
return 0;
|
||||
|
||||
prsactx->mdctx = EVP_MD_CTX_new();
|
||||
if (prsactx->mdctx == NULL)
|
||||
goto error;
|
||||
|
||||
if (!EVP_DigestInit_ex(prsactx->mdctx, prsactx->md, NULL))
|
||||
goto error;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
EVP_MD_CTX_free(prsactx->mdctx);
|
||||
EVP_MD_free(prsactx->md);
|
||||
prsactx->mdctx = NULL;
|
||||
prsactx->md = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rsa_digest_signverify_update(void *vprsactx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx == NULL || prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
|
||||
}
|
||||
|
||||
int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, size_t *siglen,
|
||||
size_t sigsize)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int dlen = 0;
|
||||
|
||||
prsactx->flag_allow_md = 1;
|
||||
if (prsactx == NULL || prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If sig is NULL then we're just finding out the sig size. Other fields
|
||||
* are ignored. Defer to rsa_sign.
|
||||
*/
|
||||
if (sig != NULL) {
|
||||
/*
|
||||
* TODO(3.0): There is the possibility that some externally provided
|
||||
* digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
|
||||
* but that problem is much larger than just in RSA.
|
||||
*/
|
||||
if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
|
||||
}
|
||||
|
||||
|
||||
int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
|
||||
size_t siglen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int dlen = 0;
|
||||
|
||||
prsactx->flag_allow_md = 1;
|
||||
if (prsactx == NULL || prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* TODO(3.0): There is the possibility that some externally provided
|
||||
* digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
|
||||
* but that problem is much larger than just in RSA.
|
||||
*/
|
||||
if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
|
||||
return 0;
|
||||
|
||||
return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
|
||||
}
|
||||
|
||||
static void rsa_freectx(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx == NULL)
|
||||
return;
|
||||
|
||||
RSA_free(prsactx->rsa);
|
||||
EVP_MD_CTX_free(prsactx->mdctx);
|
||||
EVP_MD_free(prsactx->md);
|
||||
EVP_MD_free(prsactx->mgf1_md);
|
||||
free_tbuf(prsactx);
|
||||
|
||||
OPENSSL_clear_free(prsactx, sizeof(prsactx));
|
||||
}
|
||||
|
||||
static void *rsa_dupctx(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
|
||||
PROV_RSA_CTX *dstctx;
|
||||
|
||||
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
|
||||
if (dstctx == NULL)
|
||||
return NULL;
|
||||
|
||||
*dstctx = *srcctx;
|
||||
dstctx->rsa = NULL;
|
||||
dstctx->md = NULL;
|
||||
dstctx->mdctx = NULL;
|
||||
dstctx->tbuf = NULL;
|
||||
|
||||
if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa))
|
||||
goto err;
|
||||
dstctx->rsa = srcctx->rsa;
|
||||
|
||||
if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
|
||||
goto err;
|
||||
dstctx->md = srcctx->md;
|
||||
|
||||
if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md))
|
||||
goto err;
|
||||
dstctx->mgf1_md = srcctx->mgf1_md;
|
||||
|
||||
if (srcctx->mdctx != NULL) {
|
||||
dstctx->mdctx = EVP_MD_CTX_new();
|
||||
if (dstctx->mdctx == NULL
|
||||
|| !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return dstctx;
|
||||
err:
|
||||
rsa_freectx(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if (prsactx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
|
||||
if (p != NULL
|
||||
&& !OSSL_PARAM_set_octet_string(p, prsactx->aid, prsactx->aid_len))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
|
||||
if (p != NULL)
|
||||
switch (p->data_type) {
|
||||
case OSSL_PARAM_INTEGER:
|
||||
if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
|
||||
return 0;
|
||||
break;
|
||||
case OSSL_PARAM_UTF8_STRING:
|
||||
{
|
||||
int i;
|
||||
const char *word = NULL;
|
||||
|
||||
for (i = 0; padding_item[i].id != 0; i++) {
|
||||
if (prsactx->pad_mode == (int)padding_item[i].id) {
|
||||
word = padding_item[i].ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (word != NULL) {
|
||||
if (!OSSL_PARAM_set_utf8_string(p, word))
|
||||
return 0;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
|
||||
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
|
||||
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
|
||||
if (p != NULL) {
|
||||
if (p->data_type == OSSL_PARAM_INTEGER) {
|
||||
if (!OSSL_PARAM_set_int(p, prsactx->saltlen))
|
||||
return 0;
|
||||
} else if (p->data_type == OSSL_PARAM_UTF8_STRING) {
|
||||
switch (prsactx->saltlen) {
|
||||
case RSA_PSS_SALTLEN_DIGEST:
|
||||
if (!OSSL_PARAM_set_utf8_string(p, "digest"))
|
||||
return 0;
|
||||
break;
|
||||
case RSA_PSS_SALTLEN_MAX:
|
||||
if (!OSSL_PARAM_set_utf8_string(p, "max"))
|
||||
return 0;
|
||||
break;
|
||||
case RSA_PSS_SALTLEN_AUTO:
|
||||
if (!OSSL_PARAM_set_utf8_string(p, "auto"))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
if (BIO_snprintf(p->data, p->data_size, "%d", prsactx->saltlen)
|
||||
<= 0)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *rsa_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (prsactx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
|
||||
/* Not allowed during certain operations */
|
||||
if (p != NULL && !prsactx->flag_allow_md)
|
||||
return 0;
|
||||
if (p != NULL) {
|
||||
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
|
||||
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
|
||||
const OSSL_PARAM *propsp =
|
||||
OSSL_PARAM_locate_const(params,
|
||||
OSSL_SIGNATURE_PARAM_PROPERTIES);
|
||||
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
|
||||
return 0;
|
||||
if (propsp != NULL
|
||||
&& !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
|
||||
return 0;
|
||||
|
||||
/* TODO(3.0) PSS check needs more work */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
/* TODO(3.0) figure out what to do for prsactx->md == NULL */
|
||||
if (prsactx->md == NULL || EVP_MD_is_a(prsactx->md, mdname))
|
||||
return 1;
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non-PSS code follows */
|
||||
if (!rsa_setup_md(prsactx, mdname, mdprops))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
|
||||
if (p != NULL) {
|
||||
int pad_mode = 0;
|
||||
|
||||
switch (p->data_type) {
|
||||
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
|
||||
if (!OSSL_PARAM_get_int(p, &pad_mode))
|
||||
return 0;
|
||||
break;
|
||||
case OSSL_PARAM_UTF8_STRING:
|
||||
{
|
||||
int i;
|
||||
|
||||
if (p->data == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; padding_item[i].id != 0; i++) {
|
||||
if (strcmp(p->data, padding_item[i].ptr) == 0) {
|
||||
pad_mode = padding_item[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (pad_mode) {
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
/*
|
||||
* OAEP padding is for asymmetric cipher only so is not compatible
|
||||
* with signature use.
|
||||
*/
|
||||
ERR_raise_data(ERR_LIB_PROV,
|
||||
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
|
||||
"OAEP padding not allowed for signing / verifying");
|
||||
return 0;
|
||||
case RSA_PKCS1_PSS_PADDING:
|
||||
if (prsactx->mdname[0] == '\0')
|
||||
rsa_setup_md(prsactx, "SHA1", "");
|
||||
goto cont;
|
||||
case RSA_PKCS1_PADDING:
|
||||
case RSA_SSLV23_PADDING:
|
||||
case RSA_NO_PADDING:
|
||||
case RSA_X931_PADDING:
|
||||
if (RSA_get0_pss_params(prsactx->rsa) != NULL) {
|
||||
ERR_raise_data(ERR_LIB_PROV,
|
||||
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
|
||||
"X.931 padding not allowed with RSA-PSS");
|
||||
return 0;
|
||||
}
|
||||
cont:
|
||||
if (!rsa_check_padding(prsactx->mdnid, pad_mode))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
prsactx->pad_mode = pad_mode;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
|
||||
if (p != NULL) {
|
||||
int saltlen;
|
||||
|
||||
if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
|
||||
"PSS saltlen can only be specified if "
|
||||
"PSS padding has been specified first");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (p->data_type) {
|
||||
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
|
||||
if (!OSSL_PARAM_get_int(p, &saltlen))
|
||||
return 0;
|
||||
break;
|
||||
case OSSL_PARAM_UTF8_STRING:
|
||||
if (strcmp(p->data, "digest") == 0)
|
||||
saltlen = RSA_PSS_SALTLEN_DIGEST;
|
||||
else if (strcmp(p->data, "max") == 0)
|
||||
saltlen = RSA_PSS_SALTLEN_MAX;
|
||||
else if (strcmp(p->data, "auto") == 0)
|
||||
saltlen = RSA_PSS_SALTLEN_AUTO;
|
||||
else
|
||||
saltlen = atoi(p->data);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RSA_PSS_SALTLEN_MAX seems curiously named in this check.
|
||||
* Contrary to what it's name suggests, it's the currently
|
||||
* lowest saltlen number possible.
|
||||
*/
|
||||
if (saltlen < RSA_PSS_SALTLEN_MAX) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prsactx->saltlen = saltlen;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
|
||||
if (p != NULL) {
|
||||
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
|
||||
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
|
||||
const OSSL_PARAM *propsp =
|
||||
OSSL_PARAM_locate_const(params,
|
||||
OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES);
|
||||
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
|
||||
return 0;
|
||||
if (propsp != NULL
|
||||
&& !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
|
||||
return 0;
|
||||
|
||||
if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(3.0) PSS check needs more work */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
/* TODO(3.0) figure out what to do for prsactx->md == NULL */
|
||||
if (prsactx->mgf1_md == NULL
|
||||
|| EVP_MD_is_a(prsactx->mgf1_md, mdname))
|
||||
return 1;
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non-PSS code follows */
|
||||
if (!rsa_setup_mgf1_md(prsactx, mdname, mdprops))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *rsa_settable_ctx_params(void)
|
||||
{
|
||||
/*
|
||||
* TODO(3.0): Should this function return a different set of settable ctx
|
||||
* params if the ctx is being used for a DigestSign/DigestVerify? In that
|
||||
* case it is not allowed to set the digest size/digest name because the
|
||||
* digest is explicitly set as part of the init.
|
||||
*/
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_CTX_get_params(prsactx->mdctx, params);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->md == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_gettable_ctx_params(prsactx->md);
|
||||
}
|
||||
|
||||
static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_CTX_set_params(prsactx->mdctx, params);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->md == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_settable_ctx_params(prsactx->md);
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH rsa_signature_functions[] = {
|
||||
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx },
|
||||
{ OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, (void (*)(void))rsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))rsa_verify_recover },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
|
||||
(void (*)(void))rsa_digest_signverify_init },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
|
||||
(void (*)(void))rsa_digest_signverify_update },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
|
||||
(void (*)(void))rsa_digest_sign_final },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
|
||||
(void (*)(void))rsa_digest_signverify_init },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
|
||||
(void (*)(void))rsa_digest_signverify_update },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
|
||||
(void (*)(void))rsa_digest_verify_final },
|
||||
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
|
||||
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx },
|
||||
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))rsa_gettable_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))rsa_settable_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_get_ctx_md_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_gettable_ctx_md_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_set_ctx_md_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_settable_ctx_md_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -56,23 +56,23 @@ static int legacy_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
|
||||
|
||||
static const OSSL_ALGORITHM legacy_digests[] = {
|
||||
#ifndef OPENSSL_NO_MD2
|
||||
{ "MD2", "legacy=yes", md2_functions },
|
||||
{ "MD2", "provider=legacy", md2_functions },
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_MD4
|
||||
{ "MD4", "legacy=yes", md4_functions },
|
||||
{ "MD4", "provider=legacy", md4_functions },
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_MDC2
|
||||
{ "MDC2", "legacy=yes", mdc2_functions },
|
||||
{ "MDC2", "provider=legacy", mdc2_functions },
|
||||
#endif /* OPENSSL_NO_MDC2 */
|
||||
|
||||
#ifndef OPENSSL_NO_WHIRLPOOL
|
||||
{ "WHIRLPOOL", "legacy=yes", wp_functions },
|
||||
{ "WHIRLPOOL", "provider=legacy", wp_functions },
|
||||
#endif /* OPENSSL_NO_WHIRLPOOL */
|
||||
|
||||
#ifndef OPENSSL_NO_RMD160
|
||||
{ "RIPEMD-160:RIPEMD160:RIPEMD:RMD160", "legacy=yes", ripemd160_functions },
|
||||
{ "RIPEMD-160:RIPEMD160:RIPEMD:RMD160", "provider=legacy", ripemd160_functions },
|
||||
#endif /* OPENSSL_NO_RMD160 */
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
|
||||
Reference in New Issue
Block a user