From 675f4ceef880f9c4eb0fda5dacd18b001fefb5bc Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Wed, 5 Sep 2018 15:19:17 +0800 Subject: [PATCH] Update document for SM2 stuffs Reviewed-by: Tim Hudson Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/7113) --- crypto/err/openssl.txt | 2 ++ crypto/evp/m_sigver.c | 2 +- crypto/evp/pmeth_lib.c | 2 +- crypto/include/internal/sm2err.h | 5 +++++ crypto/sm2/sm2_err.c | 7 +++++++ crypto/sm2/sm2_pmeth.c | 12 ++++++++---- doc/man3/EVP_DigestInit.pod | 18 +++++++++++++++++- doc/man3/EVP_DigestSignInit.pod | 11 +++++++++-- doc/man3/EVP_DigestVerifyInit.pod | 9 +++++++-- doc/man3/EVP_PKEY_CTX_ctrl.pod | 22 ++++++++++++++++++++-- doc/man3/EVP_PKEY_meth_new.pod | 17 +++++++++++++++++ 11 files changed, 94 insertions(+), 13 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 2f86786d58..c998e61616 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1082,6 +1082,7 @@ RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1:126:RSA_verify_PKCS1_PSS_mgf1 RSA_F_SETUP_TBUF:167:setup_tbuf SM2_F_PKEY_SM2_CTRL:109:pkey_sm2_ctrl SM2_F_PKEY_SM2_CTRL_STR:110:pkey_sm2_ctrl_str +SM2_F_PKEY_SM2_DIGEST_CUSTOM:114:pkey_sm2_digest_custom SM2_F_PKEY_SM2_INIT:111:pkey_sm2_init SM2_F_PKEY_SM2_SIGN:112:pkey_sm2_sign SM2_F_SM2_COMPUTE_MSG_HASH:100:sm2_compute_msg_hash @@ -2556,6 +2557,7 @@ SM2_R_ASN1_ERROR:100:asn1 error SM2_R_BAD_SIGNATURE:101:bad signature SM2_R_BUFFER_TOO_SMALL:107:buffer too small SM2_R_DIST_ID_TOO_LARGE:110:dist id too large +SM2_R_ID_NOT_SET:112:id not set SM2_R_ID_TOO_LARGE:111:id too large SM2_R_INVALID_CURVE:108:invalid curve SM2_R_INVALID_DIGEST:102:invalid digest diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index 2eceede28c..94e37f02b2 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -79,7 +79,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, * This indicates the current algorithm requires * special treatment before hashing the tbs-message. */ - if (ctx->pctx->pmeth->digest_custom) + if (ctx->pctx->pmeth->digest_custom != NULL) return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); return 1; diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 76405154a9..633cb8863d 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -859,6 +859,6 @@ void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, int (**pdigest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)) { - if (*pdigest_custom) + if (pdigest_custom != NULL) *pdigest_custom = pmeth->digest_custom; } diff --git a/crypto/include/internal/sm2err.h b/crypto/include/internal/sm2err.h index 4b8536db32..62f2aa2a10 100644 --- a/crypto/include/internal/sm2err.h +++ b/crypto/include/internal/sm2err.h @@ -25,9 +25,11 @@ int ERR_load_SM2_strings(void); */ # define SM2_F_PKEY_SM2_CTRL 109 # define SM2_F_PKEY_SM2_CTRL_STR 110 +# define SM2_F_PKEY_SM2_DIGEST_CUSTOM 114 # define SM2_F_PKEY_SM2_INIT 111 # define SM2_F_PKEY_SM2_SIGN 112 # define SM2_F_SM2_COMPUTE_MSG_HASH 100 +# define SM2_F_SM2_COMPUTE_USERID_DIGEST 101 # define SM2_F_SM2_COMPUTE_Z_DIGEST 113 # define SM2_F_SM2_DECRYPT 102 # define SM2_F_SM2_ENCRYPT 103 @@ -43,6 +45,8 @@ int ERR_load_SM2_strings(void); # define SM2_R_ASN1_ERROR 100 # define SM2_R_BAD_SIGNATURE 101 # define SM2_R_BUFFER_TOO_SMALL 107 +# define SM2_R_DIST_ID_TOO_LARGE 110 +# define SM2_R_ID_NOT_SET 112 # define SM2_R_ID_TOO_LARGE 111 # define SM2_R_INVALID_CURVE 108 # define SM2_R_INVALID_DIGEST 102 @@ -50,6 +54,7 @@ int ERR_load_SM2_strings(void); # define SM2_R_INVALID_ENCODING 104 # define SM2_R_INVALID_FIELD 105 # define SM2_R_NO_PARAMETERS_SET 109 +# define SM2_R_USER_ID_TOO_LARGE 106 # endif #endif diff --git a/crypto/sm2/sm2_err.c b/crypto/sm2/sm2_err.c index 7bc812e42e..c2a96c15d9 100644 --- a/crypto/sm2/sm2_err.c +++ b/crypto/sm2/sm2_err.c @@ -16,10 +16,14 @@ static const ERR_STRING_DATA SM2_str_functs[] = { {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_DIGEST_CUSTOM, 0), + "pkey_sm2_digest_custom"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0), "sm2_compute_msg_hash"}, + {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0), + "sm2_compute_userid_digest"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_Z_DIGEST, 0), "sm2_compute_z_digest"}, {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_DECRYPT, 0), "sm2_decrypt"}, @@ -36,6 +40,8 @@ static const ERR_STRING_DATA SM2_str_reasons[] = { {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BAD_SIGNATURE), "bad signature"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_DIST_ID_TOO_LARGE), "dist id too large"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_NOT_SET), "id not set"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_TOO_LARGE), "id too large"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_CURVE), "invalid curve"}, {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST), "invalid digest"}, @@ -44,6 +50,7 @@ static const ERR_STRING_DATA SM2_str_reasons[] = { {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_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"}, {0, NULL} }; diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c index aed7f33044..4b61e243aa 100644 --- a/crypto/sm2/sm2_pmeth.c +++ b/crypto/sm2/sm2_pmeth.c @@ -163,6 +163,7 @@ static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { SM2_PKEY_CTX *smctx = ctx->data; EC_GROUP *group; + uint8_t *tmp_id; switch (type) { case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: @@ -192,14 +193,16 @@ static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return 1; case EVP_PKEY_CTRL_SET1_ID: - OPENSSL_free(smctx->id); if (p1 > 0) { - smctx->id = OPENSSL_malloc(p1); - if (smctx->id == NULL) + tmp_id = OPENSSL_malloc(p1); + if (tmp_id == NULL) return 0; - memcpy(smctx->id, p2, p1); + memcpy(tmp_id, p2, p1); + OPENSSL_free(smctx->id); + smctx->id = tmp_id; } else { /* set null-ID */ + OPENSSL_free(smctx->id); smctx->id = NULL; } smctx->id_len = (size_t)p1; @@ -260,6 +263,7 @@ static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) * NULL is allowed. We only allow it if set explicitly for maximum * flexibility. */ + SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET); return 0; } diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index 67f4f02196..02e7719274 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -11,7 +11,8 @@ EVP_MD_block_size, EVP_MD_CTX_md, EVP_MD_CTX_size, EVP_MD_CTX_block_size, EVP_MD_CTX_type, EVP_MD_CTX_md_data, EVP_md_null, EVP_get_digestbyname, EVP_get_digestbynid, -EVP_get_digestbyobj - EVP digest routines +EVP_get_digestbyobj, +EVP_MD_CTX_set_pkey_ctx - EVP digest routines =head1 SYNOPSIS @@ -54,6 +55,8 @@ EVP_get_digestbyobj - EVP digest routines const EVP_MD *EVP_get_digestbynid(int type); const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *o); + void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); + =head1 DESCRIPTION The EVP digest routines are a high level interface to message digests, @@ -179,6 +182,13 @@ EVP_get_digestbyobj() Returns an B structure when passed a digest name, a digest B or an B structure respectively. +=item EVP_MD_CTX_set_pkey_ctx() + +Assigns an B to B. This is usually used to provide +a customzied B to L or +L. The B passed to this function should +be freed by the caller. + =back =head1 FLAGS @@ -256,6 +266,10 @@ EVP_get_digestbyobj() Returns either an B structure or NULL if an error occurs. +=item EVP_MD_CTX_set_pkey_ctx() + +This function has no return value. + =back =head1 NOTES @@ -360,6 +374,8 @@ later, so now EVP_sha1() can be used with RSA and DSA. EVP_dss1() was removed in OpenSSL 1.1.0. +EVP_MD_CTX_set_pkey_ctx() is added in 1.1.1. + =head1 COPYRIGHT Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/EVP_DigestSignInit.pod b/doc/man3/EVP_DigestSignInit.pod index fe2be7bbf5..773de87efa 100644 --- a/doc/man3/EVP_DigestSignInit.pod +++ b/doc/man3/EVP_DigestSignInit.pod @@ -28,8 +28,15 @@ EVP_MD_CTX_new() before calling this function. If B is not NULL, the EVP_PKEY_CTX of the signing operation will be written to B<*pctx>: this can be used to set alternative signing options. Note that any existing value in B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed -directly by the application (it will be freed automatically when the EVP_MD_CTX -is freed). The digest B may be NULL if the signing algorithm supports it. +directly by the application if B is not assigned an EVP_PKEY_CTX value before +being passed to EVP_DigestSignInit() (which means the EVP_PKEY_CTX is created +inside EVP_DigestSignInit() and it will be freed automatically when the +EVP_MD_CTX is freed). + +The digest B may be NULL if the signing algorithm supports it. + +No B will be created by EVP_DigsetSignInit() if the passed B +has already been assigned one via L. See also L. Only EVP_PKEY types that support signing can be used with these functions. This includes MAC algorithms where the MAC generation is considered as a form of diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod index 0d25debcb1..e93ac2ef08 100644 --- a/doc/man3/EVP_DigestVerifyInit.pod +++ b/doc/man3/EVP_DigestVerifyInit.pod @@ -26,10 +26,15 @@ B from ENGINE B and public key B. B must be created with EVP_MD_CTX_new() before calling this function. If B is not NULL, the EVP_PKEY_CTX of the verification operation will be written to B<*pctx>: this can be used to set alternative verification options. Note that any existing -value in B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be -freed directly by the application (it will be freed automatically when the +value in B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed +directly by the application if B is not assigned an EVP_PKEY_CTX value before +being passed to EVP_DigestSignInit() (which means the EVP_PKEY_CTX is created +inside EVP_DigestSignInit() and it will be freed automatically when the EVP_MD_CTX is freed). +No B will be created by EVP_DigsetSignInit() if the passed B +has already been assigned one via L. See also L. + EVP_DigestVerifyUpdate() hashes B bytes of data at B into the verification context B. This function can be called several times on the same B to include additional data. This function is currently implemented diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index 7eb9796bdd..d70dbb9cf2 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -17,7 +17,9 @@ EVP_PKEY_CTX_set_dh_paramgen_generator, EVP_PKEY_CTX_set_dh_pad, EVP_PKEY_CTX_set_dh_nid, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, -EVP_PKEY_CTX_set_ec_param_enc - algorithm specific control operations +EVP_PKEY_CTX_set_ec_param_enc, +EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len +- algorithm specific control operations =head1 SYNOPSIS @@ -53,6 +55,10 @@ EVP_PKEY_CTX_set_ec_param_enc - algorithm specific control operations int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid); int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc); + int EVP_PKEY_CTX_set1_id(EVP_PKEY_CTX *ctx, void *id, size_t id_len); + int EVP_PKEY_CTX_get1_id(EVP_PKEY_CTX *ctx, void *id); + int EVP_PKEY_CTX_get1_id_len(EVP_PKEY_CTX *ctx, size_t *id_len); + =head1 DESCRIPTION The function EVP_PKEY_CTX_ctrl() sends a control operation to the context @@ -160,6 +166,17 @@ For maximum compatibility the named curve form should be used. Note: the B value was only added to OpenSSL 1.1.0; previous versions should use 0 instead. +The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len() +are used to manipulate special identifier field for specific signature algorithm +such as SM2. The EVP_PKEY_set1_id() sets an ID pointed by B with the length +B to the library. The library maintains the memory management stuffs so +the caller can safely free the original memory pointed by B. The +EVP_PKEY_CTX_get1_id_len() returns the length of the ID set via a previous call +to EVP_PKEY_set1_id(). The length is usually used to allocate adequate memory for +further calls to EVP_PKEY_CTX_get1_id(). The EVP_PKEY_CTX_get1_id() returns the +previously set ID value to caller into B, caller should allocate adequate +memory space to B before calling EVP_PKEY_CTX_get1_id(). + =head1 RETURN VALUES EVP_PKEY_CTX_ctrl() and its macros return a positive value for success and 0 @@ -179,7 +196,8 @@ L =head1 HISTORY -These functions were first added to OpenSSL 1.0.0. +EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len() +were added in 1.1.1, other functions were first added to OpenSSL 1.0.0. =head1 COPYRIGHT diff --git a/doc/man3/EVP_PKEY_meth_new.pod b/doc/man3/EVP_PKEY_meth_new.pod index ddc99d2800..171d4da744 100644 --- a/doc/man3/EVP_PKEY_meth_new.pod +++ b/doc/man3/EVP_PKEY_meth_new.pod @@ -10,12 +10,14 @@ EVP_PKEY_meth_set_verify, EVP_PKEY_meth_set_verify_recover, EVP_PKEY_meth_set_si EVP_PKEY_meth_set_verifyctx, EVP_PKEY_meth_set_encrypt, EVP_PKEY_meth_set_decrypt, EVP_PKEY_meth_set_derive, EVP_PKEY_meth_set_ctrl, EVP_PKEY_meth_set_check, EVP_PKEY_meth_set_public_check, EVP_PKEY_meth_set_param_check, +EVP_PKEY_meth_set_digest_custom, EVP_PKEY_meth_get_init, EVP_PKEY_meth_get_copy, EVP_PKEY_meth_get_cleanup, EVP_PKEY_meth_get_paramgen, EVP_PKEY_meth_get_keygen, EVP_PKEY_meth_get_sign, EVP_PKEY_meth_get_verify, EVP_PKEY_meth_get_verify_recover, EVP_PKEY_meth_get_signctx, EVP_PKEY_meth_get_verifyctx, EVP_PKEY_meth_get_encrypt, EVP_PKEY_meth_get_decrypt, EVP_PKEY_meth_get_derive, EVP_PKEY_meth_get_ctrl, EVP_PKEY_meth_get_check, EVP_PKEY_meth_get_public_check, EVP_PKEY_meth_get_param_check, +EVP_PKEY_meth_get_digest_custom, EVP_PKEY_meth_remove - manipulating EVP_PKEY_METHOD structure @@ -116,6 +118,9 @@ EVP_PKEY_meth_remove int (*check) (EVP_PKEY *pkey)); void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, int (*check) (EVP_PKEY *pkey)); + void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth, + int (*digest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)); void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth, int (**pinit) (EVP_PKEY_CTX *ctx)); @@ -201,6 +206,9 @@ EVP_PKEY_meth_remove int (**pcheck) (EVP_PKEY *pkey)); void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth, int (**pcheck) (EVP_PKEY *pkey)); + void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth, + int (**pdigest_custom) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx)); =head1 DESCRIPTION @@ -334,6 +342,15 @@ key-pair, the public component and parameters respectively for a given B. They could be called by L, L and L respectively. + int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); + +The digest_custom() method is used to generate customized digest content before +the real message is passed to functions like L or +L. This is usually required by some public key +signature algorithms like SM2 which requires a hashed prefix to the message to +be signed. The digest_custom() will be called by L and +L. + =head2 Functions EVP_PKEY_meth_new() creates and returns a new B object, -- 2.25.1