mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-04-29 11:14:36 +00:00
Add SM2 private key range validation
According to the relevant standards, the valid range for SM2 private keys is [1, n-1), where n is the order of the curve generator. For this reason we cannot reuse the EC validation function as it is, and we introduce a new internal function `sm2_key_private_check()`. Partially fixes https://github.com/openssl/openssl/issues/8435 Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/13359)
This commit is contained in:
parent
4554988e58
commit
9e49aff2aa
@ -23,6 +23,14 @@ OpenSSL 3.0
|
|||||||
|
|
||||||
### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
|
### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
|
||||||
|
|
||||||
|
* Validation of SM2 keys has been separated from the validation of regular EC
|
||||||
|
keys, allowing to improve the SM2 validation process to reject loaded private
|
||||||
|
keys that are not conforming to the SM2 ISO standard.
|
||||||
|
In particular, a private scalar `k` outside the range `1 <= k < n-1` is now
|
||||||
|
correctly rejected.
|
||||||
|
|
||||||
|
*Nicola Tuveri*
|
||||||
|
|
||||||
* Behavior of the `pkey` app is changed, when using the `-check` or `-pubcheck`
|
* Behavior of the `pkey` app is changed, when using the `-check` or `-pubcheck`
|
||||||
switches: a validation failure triggers an early exit, returning a failure
|
switches: a validation failure triggers an early exit, returning a failure
|
||||||
exit status to the parent process.
|
exit status to the parent process.
|
||||||
|
@ -3103,6 +3103,7 @@ SM2_R_INVALID_DIGEST:102:invalid digest
|
|||||||
SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type
|
SM2_R_INVALID_DIGEST_TYPE:103:invalid digest type
|
||||||
SM2_R_INVALID_ENCODING:104:invalid encoding
|
SM2_R_INVALID_ENCODING:104:invalid encoding
|
||||||
SM2_R_INVALID_FIELD:105:invalid field
|
SM2_R_INVALID_FIELD:105:invalid field
|
||||||
|
SM2_R_INVALID_PRIVATE_KEY:113:invalid private key
|
||||||
SM2_R_NO_PARAMETERS_SET:109:no parameters set
|
SM2_R_NO_PARAMETERS_SET:109:no parameters set
|
||||||
SM2_R_USER_ID_TOO_LARGE:106:user id too large
|
SM2_R_USER_ID_TOO_LARGE:106:user id too large
|
||||||
SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed
|
SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
LIBS=../../libcrypto
|
LIBS=../../libcrypto
|
||||||
SOURCE[../../libcrypto]=\
|
SOURCE[../../libcrypto]=\
|
||||||
sm2_sign.c sm2_crypt.c sm2_err.c
|
sm2_sign.c sm2_crypt.c sm2_err.c sm2_key.c
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ static const ERR_STRING_DATA SM2_str_reasons[] = {
|
|||||||
"invalid digest type"},
|
"invalid digest type"},
|
||||||
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"},
|
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"},
|
||||||
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"},
|
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"},
|
||||||
|
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_PRIVATE_KEY),
|
||||||
|
"invalid private key"},
|
||||||
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"},
|
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"},
|
||||||
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"},
|
{ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
|
49
crypto/sm2/sm2_key.c
Normal file
49
crypto/sm2/sm2_key.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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/sm2err.h"
|
||||||
|
#include "crypto/sm2.h"
|
||||||
|
#include <openssl/ec.h> /* EC_KEY and EC_GROUP functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SM2 key generation is implemented within ec_generate_key() in
|
||||||
|
* crypto/ec/ec_key.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
int sm2_key_private_check(const EC_KEY *eckey)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
BIGNUM *max = NULL;
|
||||||
|
const EC_GROUP *group = NULL;
|
||||||
|
const BIGNUM *priv_key = NULL, *order = NULL;
|
||||||
|
|
||||||
|
if (eckey == NULL
|
||||||
|
|| (group = EC_KEY_get0_group(eckey)) == NULL
|
||||||
|
|| (priv_key = EC_KEY_get0_private_key(eckey)) == NULL
|
||||||
|
|| (order = EC_GROUP_get0_order(group)) == NULL ) {
|
||||||
|
ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* range of SM2 private key is [1, n-1) */
|
||||||
|
max = BN_dup(order);
|
||||||
|
if (max == NULL || !BN_sub_word(max, 1))
|
||||||
|
goto end;
|
||||||
|
if (BN_cmp(priv_key, BN_value_one()) < 0
|
||||||
|
|| BN_cmp(priv_key, max) >= 0) {
|
||||||
|
ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_PRIVATE_KEY);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
end:
|
||||||
|
BN_free(max);
|
||||||
|
return ret;
|
||||||
|
}
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
# include <openssl/ec.h>
|
# include <openssl/ec.h>
|
||||||
|
|
||||||
|
int sm2_key_private_check(const EC_KEY *eckey);
|
||||||
|
|
||||||
/* The default user id as specified in GM/T 0009-2012 */
|
/* The default user id as specified in GM/T 0009-2012 */
|
||||||
# define SM2_DEFAULT_USERID "1234567812345678"
|
# define SM2_DEFAULT_USERID "1234567812345678"
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ int err_load_SM2_strings_int(void);
|
|||||||
# define SM2_R_INVALID_DIGEST_TYPE 103
|
# define SM2_R_INVALID_DIGEST_TYPE 103
|
||||||
# define SM2_R_INVALID_ENCODING 104
|
# define SM2_R_INVALID_ENCODING 104
|
||||||
# define SM2_R_INVALID_FIELD 105
|
# define SM2_R_INVALID_FIELD 105
|
||||||
|
# define SM2_R_INVALID_PRIVATE_KEY 113
|
||||||
# define SM2_R_NO_PARAMETERS_SET 109
|
# define SM2_R_NO_PARAMETERS_SET 109
|
||||||
# define SM2_R_USER_ID_TOO_LARGE 106
|
# define SM2_R_USER_ID_TOO_LARGE 106
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# We make separate GOAL variables for each algorithm, to make it easy to
|
# We make separate GOAL variables for each algorithm, to make it easy to
|
||||||
# switch each to the Legacy provider when needed.
|
# switch each to the Legacy provider when needed.
|
||||||
|
|
||||||
$EC_GOAL=../../libimplementations.a
|
|
||||||
$ECX_GOAL=../../libimplementations.a
|
$ECX_GOAL=../../libimplementations.a
|
||||||
$KDF_GOAL=../../libimplementations.a
|
$KDF_GOAL=../../libimplementations.a
|
||||||
|
|
||||||
@ -14,7 +13,8 @@ IF[{- !$disabled{dsa} -}]
|
|||||||
SOURCE[../../libnonfips.a]=dsa_kmgmt.c
|
SOURCE[../../libnonfips.a]=dsa_kmgmt.c
|
||||||
ENDIF
|
ENDIF
|
||||||
IF[{- !$disabled{ec} -}]
|
IF[{- !$disabled{ec} -}]
|
||||||
SOURCE[$EC_GOAL]=ec_kmgmt.c
|
SOURCE[../../libfips.a]=ec_kmgmt.c
|
||||||
|
SOURCE[../../libnonfips.a]=ec_kmgmt.c
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
IF[{- !$disabled{asm} -}]
|
IF[{- !$disabled{asm} -}]
|
||||||
|
@ -27,7 +27,12 @@
|
|||||||
#include "prov/providercommonerr.h"
|
#include "prov/providercommonerr.h"
|
||||||
#include "prov/provider_ctx.h"
|
#include "prov/provider_ctx.h"
|
||||||
#include "internal/param_build_set.h"
|
#include "internal/param_build_set.h"
|
||||||
#include "crypto/sm2.h"
|
|
||||||
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
|
# include "crypto/sm2.h"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
static OSSL_FUNC_keymgmt_new_fn ec_newdata;
|
static OSSL_FUNC_keymgmt_new_fn ec_newdata;
|
||||||
static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
|
static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
|
||||||
@ -50,13 +55,16 @@ static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
|
|||||||
static OSSL_FUNC_keymgmt_export_fn ec_export;
|
static OSSL_FUNC_keymgmt_export_fn ec_export;
|
||||||
static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
|
static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
|
||||||
static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
|
static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
|
||||||
#ifndef OPENSSL_NO_SM2
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
|
static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
|
||||||
static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
|
static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
|
||||||
static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
|
static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
|
||||||
static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
|
static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
|
||||||
static OSSL_FUNC_keymgmt_import_fn sm2_import;
|
static OSSL_FUNC_keymgmt_import_fn sm2_import;
|
||||||
static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
|
static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
|
||||||
|
static OSSL_FUNC_keymgmt_validate_fn sm2_validate;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EC_DEFAULT_MD "SHA256"
|
#define EC_DEFAULT_MD "SHA256"
|
||||||
@ -76,7 +84,8 @@ const char *ec_query_operation_name(int operation_id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SM2
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
static
|
static
|
||||||
const char *sm2_query_operation_name(int operation_id)
|
const char *sm2_query_operation_name(int operation_id)
|
||||||
{
|
{
|
||||||
@ -86,6 +95,7 @@ const char *sm2_query_operation_name(int operation_id)
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -364,12 +374,14 @@ int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
|
|||||||
return common_import(keydata, selection, params, 0);
|
return common_import(keydata, selection, params, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SM2
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
static
|
static
|
||||||
int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
|
int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||||
{
|
{
|
||||||
return common_import(keydata, selection, params, 1);
|
return common_import(keydata, selection, params, 1);
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -746,7 +758,8 @@ int ec_set_params(void *key, const OSSL_PARAM params[])
|
|||||||
return ec_key_otherparams_fromdata(eck, params);
|
return ec_key_otherparams_fromdata(eck, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SM2
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
static
|
static
|
||||||
int sm2_get_params(void *key, OSSL_PARAM params[])
|
int sm2_get_params(void *key, OSSL_PARAM params[])
|
||||||
{
|
{
|
||||||
@ -782,6 +795,40 @@ const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
|
|||||||
{
|
{
|
||||||
return sm2_known_settable_params;
|
return sm2_known_settable_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int sm2_validate(const void *keydata, int selection)
|
||||||
|
{
|
||||||
|
const EC_KEY *eck = keydata;
|
||||||
|
int ok = 0;
|
||||||
|
BN_CTX *ctx = NULL;
|
||||||
|
|
||||||
|
if (!ossl_prov_is_running())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ctx = BN_CTX_new_ex(ec_key_get_libctx(eck));
|
||||||
|
if (ctx == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
|
||||||
|
ok = 1;
|
||||||
|
|
||||||
|
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||||
|
ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
|
||||||
|
|
||||||
|
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||||
|
ok = ok && ec_key_public_check(eck, ctx);
|
||||||
|
|
||||||
|
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||||
|
ok = ok && sm2_key_private_check(eck);
|
||||||
|
|
||||||
|
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
|
||||||
|
ok = ok && ec_key_pairwise_check(eck, ctx);
|
||||||
|
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -1084,7 +1131,8 @@ err:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SM2
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
/*
|
/*
|
||||||
* The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
|
* The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
|
||||||
*/
|
*/
|
||||||
@ -1130,6 +1178,7 @@ err:
|
|||||||
EC_KEY_free(ec);
|
EC_KEY_free(ec);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void ec_gen_cleanup(void *genctx)
|
static void ec_gen_cleanup(void *genctx)
|
||||||
@ -1195,7 +1244,8 @@ const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
|
|||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SM2
|
#ifndef FIPS_MODULE
|
||||||
|
# ifndef OPENSSL_NO_SM2
|
||||||
const OSSL_DISPATCH sm2_keymgmt_functions[] = {
|
const OSSL_DISPATCH sm2_keymgmt_functions[] = {
|
||||||
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
|
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
|
||||||
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
|
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
|
||||||
@ -1213,7 +1263,7 @@ const OSSL_DISPATCH sm2_keymgmt_functions[] = {
|
|||||||
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
|
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
|
||||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
|
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
|
||||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
|
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
|
||||||
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
|
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
|
||||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
|
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
|
||||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
|
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
|
||||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
|
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
|
||||||
@ -1222,4 +1272,5 @@ const OSSL_DISPATCH sm2_keymgmt_functions[] = {
|
|||||||
(void (*)(void))sm2_query_operation_name },
|
(void (*)(void))sm2_query_operation_name },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user