diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2.h | 147 | ||||
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2_crypt.c | 632 | ||||
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2_err.c | 106 | ||||
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2_locl.h | 43 | ||||
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2_pmeth.c | 316 | ||||
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2_sign.c | 465 | ||||
| -rw-r--r-- | src/lib/libcrypto/sm2/sm2_za.c | 161 |
7 files changed, 1870 insertions, 0 deletions
diff --git a/src/lib/libcrypto/sm2/sm2.h b/src/lib/libcrypto/sm2/sm2.h new file mode 100644 index 0000000000..92eef8a6de --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2.h | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | /* $OpenBSD: sm2.h,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef HEADER_SM2_H | ||
| 19 | #define HEADER_SM2_H | ||
| 20 | |||
| 21 | #include <openssl/opensslconf.h> | ||
| 22 | |||
| 23 | #include <openssl/ec.h> | ||
| 24 | #include <openssl/ecdsa.h> | ||
| 25 | |||
| 26 | #ifdef OPENSSL_NO_SM2 | ||
| 27 | #error SM2 is disabled. | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #ifdef __cplusplus | ||
| 31 | extern "C" { | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* | ||
| 35 | * SM2 signature generation. | ||
| 36 | */ | ||
| 37 | int SM2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, | ||
| 38 | unsigned int *siglen, EC_KEY *eckey); | ||
| 39 | |||
| 40 | /* | ||
| 41 | * SM2 signature verification. Assumes input is an SM3 digest | ||
| 42 | */ | ||
| 43 | int SM2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, | ||
| 44 | int siglen, EC_KEY *eckey); | ||
| 45 | |||
| 46 | /* | ||
| 47 | * SM2 encryption | ||
| 48 | */ | ||
| 49 | int SM2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
| 50 | size_t *c_size); | ||
| 51 | |||
| 52 | int SM2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
| 53 | size_t *pl_size); | ||
| 54 | |||
| 55 | int SM2_encrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *msg, | ||
| 56 | size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len); | ||
| 57 | |||
| 58 | int SM2_decrypt(const EC_KEY *key, const EVP_MD *digest, | ||
| 59 | const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *ptext_buf, | ||
| 60 | size_t *ptext_len); | ||
| 61 | |||
| 62 | /* BEGIN ERROR CODES */ | ||
| 63 | /* The following lines are auto generated by the script mkerr.pl. Any changes | ||
| 64 | * made after this point may be overwritten when the script is next run. | ||
| 65 | */ | ||
| 66 | void ERR_load_SM2_strings(void); | ||
| 67 | |||
| 68 | /* Error codes for the SM2 functions. */ | ||
| 69 | |||
| 70 | /* Function codes. */ | ||
| 71 | # define SM2_F_PKEY_SM2_CTRL 274 | ||
| 72 | # define SM2_F_PKEY_SM2_CTRL_STR 275 | ||
| 73 | # define SM2_F_PKEY_SM2_KEYGEN 276 | ||
| 74 | # define SM2_F_PKEY_SM2_PARAMGEN 277 | ||
| 75 | # define SM2_F_PKEY_SM2_SIGN 278 | ||
| 76 | # define SM2_F_PKEY_SM2_VERIFY 279 | ||
| 77 | # define SM2_F_PKEY_SM2_ENCRYPT 280 | ||
| 78 | # define SM2_F_PKEY_SM2_DECRYPT 281 | ||
| 79 | |||
| 80 | /* Reason codes. */ | ||
| 81 | # define SM2_R_ASN1_ERROR 115 | ||
| 82 | # define SM2_R_ASN5_ERROR 1150 | ||
| 83 | # define SM2_R_BAD_SIGNATURE 156 | ||
| 84 | # define SM2_R_BIGNUM_OUT_OF_RANGE 144 | ||
| 85 | # define SM2_R_BUFFER_TOO_SMALL 100 | ||
| 86 | # define SM2_R_COORDINATES_OUT_OF_RANGE 146 | ||
| 87 | # define SM2_R_CURVE_DOES_NOT_SUPPORT_ECDH 160 | ||
| 88 | # define SM2_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159 | ||
| 89 | # define SM2_R_D2I_ECPKPARAMETERS_FAILURE 117 | ||
| 90 | # define SM2_R_DECODE_ERROR 142 | ||
| 91 | # define SM2_R_DIGEST_FAILURE 163 | ||
| 92 | # define SM2_R_DISCRIMINANT_IS_ZERO 118 | ||
| 93 | # define SM2_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 | ||
| 94 | # define SM2_R_FIELD_TOO_LARGE 143 | ||
| 95 | # define SM2_R_GF2M_NOT_SUPPORTED 147 | ||
| 96 | # define SM2_R_GROUP2PKPARAMETERS_FAILURE 120 | ||
| 97 | # define SM2_R_I2D_ECPKPARAMETERS_FAILURE 121 | ||
| 98 | # define SM2_R_INCOMPATIBLE_OBJECTS 101 | ||
| 99 | # define SM2_R_INVALID_ARGUMENT 112 | ||
| 100 | # define SM2_R_INVALID_COMPRESSED_POINT 110 | ||
| 101 | # define SM2_R_INVALID_COMPRESSION_BIT 109 | ||
| 102 | # define SM2_R_INVALID_CURVE 141 | ||
| 103 | # define SM2_R_INVALID_DIGEST 151 | ||
| 104 | # define SM2_R_INVALID_DIGEST_TYPE 138 | ||
| 105 | # define SM2_R_INVALID_ENCODING 102 | ||
| 106 | # define SM2_R_INVALID_FIELD 103 | ||
| 107 | # define SM2_R_INVALID_FORM 104 | ||
| 108 | # define SM2_R_INVALID_GROUP_ORDER 122 | ||
| 109 | # define SM2_R_INVALID_KEY 116 | ||
| 110 | # define SM2_R_INVALID_OUTPUT_LENGTH 161 | ||
| 111 | # define SM2_R_INVALID_PEER_KEY 133 | ||
| 112 | # define SM2_R_INVALID_PENTANOMIAL_BASIS 132 | ||
| 113 | # define SM2_R_INVALID_PRIVATE_KEY 123 | ||
| 114 | # define SM2_R_INVALID_TRINOMIAL_BASIS 137 | ||
| 115 | # define SM2_R_KDF_FAILURE 162 | ||
| 116 | # define SM2_R_KDF_PARAMETER_ERROR 148 | ||
| 117 | # define SM2_R_KEYS_NOT_SET 140 | ||
| 118 | # define SM2_R_MISSING_PARAMETERS 124 | ||
| 119 | # define SM2_R_MISSING_PRIVATE_KEY 125 | ||
| 120 | # define SM2_R_NEED_NEW_SETUP_VALUES 157 | ||
| 121 | # define SM2_R_NOT_A_NIST_PRIME 135 | ||
| 122 | # define SM2_R_NOT_IMPLEMENTED 126 | ||
| 123 | # define SM2_R_NOT_INITIALIZED 111 | ||
| 124 | # define SM2_R_NO_PARAMETERS_SET 139 | ||
| 125 | # define SM2_R_NO_PRIVATE_VALUE 154 | ||
| 126 | # define SM2_R_OPERATION_NOT_SUPPORTED 152 | ||
| 127 | # define SM2_R_PASSED_NULL_PARAMETER 134 | ||
| 128 | # define SM2_R_PEER_KEY_ERROR 149 | ||
| 129 | # define SM2_R_PKPARAMETERS2GROUP_FAILURE 127 | ||
| 130 | # define SM2_R_POINT_ARITHMETIC_FAILURE 155 | ||
| 131 | # define SM2_R_POINT_AT_INFINITY 106 | ||
| 132 | # define SM2_R_POINT_IS_NOT_ON_CURVE 107 | ||
| 133 | # define SM2_R_RANDOM_NUMBER_GENERATION_FAILED 158 | ||
| 134 | # define SM2_R_SHARED_INFO_ERROR 150 | ||
| 135 | # define SM2_R_SLOT_FULL 108 | ||
| 136 | # define SM2_R_UNDEFINED_GENERATOR 113 | ||
| 137 | # define SM2_R_UNDEFINED_ORDER 128 | ||
| 138 | # define SM2_R_UNKNOWN_GROUP 129 | ||
| 139 | # define SM2_R_UNKNOWN_ORDER 114 | ||
| 140 | # define SM2_R_UNSUPPORTED_FIELD 131 | ||
| 141 | # define SM2_R_WRONG_CURVE_PARAMETERS 145 | ||
| 142 | # define SM2_R_WRONG_ORDER 130 | ||
| 143 | |||
| 144 | #ifdef __cplusplus | ||
| 145 | } | ||
| 146 | #endif | ||
| 147 | #endif | ||
diff --git a/src/lib/libcrypto/sm2/sm2_crypt.c b/src/lib/libcrypto/sm2/sm2_crypt.c new file mode 100644 index 0000000000..2bb3b8ff63 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_crypt.c | |||
| @@ -0,0 +1,632 @@ | |||
| 1 | /* $OpenBSD: sm2_crypt.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef OPENSSL_NO_SM2 | ||
| 19 | |||
| 20 | #include <string.h> | ||
| 21 | |||
| 22 | #include <openssl/asn1.h> | ||
| 23 | #include <openssl/asn1t.h> | ||
| 24 | #include <openssl/bn.h> | ||
| 25 | #include <openssl/err.h> | ||
| 26 | #include <openssl/evp.h> | ||
| 27 | #include <openssl/sm2.h> | ||
| 28 | |||
| 29 | #include "sm2_locl.h" | ||
| 30 | |||
| 31 | typedef struct SM2_Ciphertext_st SM2_Ciphertext; | ||
| 32 | |||
| 33 | SM2_Ciphertext *SM2_Ciphertext_new(void); | ||
| 34 | void SM2_Ciphertext_free(SM2_Ciphertext *a); | ||
| 35 | SM2_Ciphertext *d2i_SM2_Ciphertext(SM2_Ciphertext **a, const unsigned char **in, | ||
| 36 | long len); | ||
| 37 | int i2d_SM2_Ciphertext(SM2_Ciphertext *a, unsigned char **out); | ||
| 38 | |||
| 39 | struct SM2_Ciphertext_st { | ||
| 40 | BIGNUM *C1x; | ||
| 41 | BIGNUM *C1y; | ||
| 42 | ASN1_OCTET_STRING *C3; | ||
| 43 | ASN1_OCTET_STRING *C2; | ||
| 44 | }; | ||
| 45 | |||
| 46 | static const ASN1_TEMPLATE SM2_Ciphertext_seq_tt[] = { | ||
| 47 | { | ||
| 48 | .flags = 0, | ||
| 49 | .tag = 0, | ||
| 50 | .offset = offsetof(SM2_Ciphertext, C1x), | ||
| 51 | .field_name = "C1x", | ||
| 52 | .item = &BIGNUM_it, | ||
| 53 | }, | ||
| 54 | { | ||
| 55 | .flags = 0, | ||
| 56 | .tag = 0, | ||
| 57 | .offset = offsetof(SM2_Ciphertext, C1y), | ||
| 58 | .field_name = "C1y", | ||
| 59 | .item = &BIGNUM_it, | ||
| 60 | }, | ||
| 61 | { | ||
| 62 | .flags = 0, | ||
| 63 | .tag = 0, | ||
| 64 | .offset = offsetof(SM2_Ciphertext, C3), | ||
| 65 | .field_name = "C3", | ||
| 66 | .item = &ASN1_OCTET_STRING_it, | ||
| 67 | }, | ||
| 68 | { | ||
| 69 | .flags = 0, | ||
| 70 | .tag = 0, | ||
| 71 | .offset = offsetof(SM2_Ciphertext, C2), | ||
| 72 | .field_name = "C2", | ||
| 73 | .item = &ASN1_OCTET_STRING_it, | ||
| 74 | }, | ||
| 75 | }; | ||
| 76 | |||
| 77 | const ASN1_ITEM SM2_Ciphertext_it = { | ||
| 78 | .itype = ASN1_ITYPE_SEQUENCE, | ||
| 79 | .utype = V_ASN1_SEQUENCE, | ||
| 80 | .templates = SM2_Ciphertext_seq_tt, | ||
| 81 | .tcount = sizeof(SM2_Ciphertext_seq_tt) / sizeof(ASN1_TEMPLATE), | ||
| 82 | .funcs = NULL, | ||
| 83 | .size = sizeof(SM2_Ciphertext), | ||
| 84 | .sname = "SM2_Ciphertext", | ||
| 85 | }; | ||
| 86 | |||
| 87 | SM2_Ciphertext * | ||
| 88 | d2i_SM2_Ciphertext(SM2_Ciphertext **a, const unsigned char **in, long len) | ||
| 89 | { | ||
| 90 | return (SM2_Ciphertext *) ASN1_item_d2i((ASN1_VALUE **)a, in, len, | ||
| 91 | &SM2_Ciphertext_it); | ||
| 92 | } | ||
| 93 | |||
| 94 | int | ||
| 95 | i2d_SM2_Ciphertext(SM2_Ciphertext *a, unsigned char **out) | ||
| 96 | { | ||
| 97 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &SM2_Ciphertext_it); | ||
| 98 | } | ||
| 99 | |||
| 100 | SM2_Ciphertext * | ||
| 101 | SM2_Ciphertext_new(void) | ||
| 102 | { | ||
| 103 | return (SM2_Ciphertext *)ASN1_item_new(&SM2_Ciphertext_it); | ||
| 104 | } | ||
| 105 | |||
| 106 | void | ||
| 107 | SM2_Ciphertext_free(SM2_Ciphertext *a) | ||
| 108 | { | ||
| 109 | ASN1_item_free((ASN1_VALUE *)a, &SM2_Ciphertext_it); | ||
| 110 | } | ||
| 111 | |||
| 112 | static size_t | ||
| 113 | ec_field_size(const EC_GROUP *group) | ||
| 114 | { | ||
| 115 | /* Is there some simpler way to do this? */ | ||
| 116 | BIGNUM *p; | ||
| 117 | size_t field_size = 0; | ||
| 118 | |||
| 119 | if ((p = BN_new()) == NULL) | ||
| 120 | goto err; | ||
| 121 | if (!EC_GROUP_get_curve(group, p, NULL, NULL, NULL)) | ||
| 122 | goto err; | ||
| 123 | field_size = BN_num_bytes(p); | ||
| 124 | err: | ||
| 125 | BN_free(p); | ||
| 126 | return field_size; | ||
| 127 | } | ||
| 128 | |||
| 129 | int | ||
| 130 | SM2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
| 131 | size_t *pl_size) | ||
| 132 | { | ||
| 133 | size_t field_size, overhead; | ||
| 134 | int md_size; | ||
| 135 | |||
| 136 | if ((field_size = ec_field_size(EC_KEY_get0_group(key))) == 0) { | ||
| 137 | SM2error(SM2_R_INVALID_FIELD); | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | if ((md_size = EVP_MD_size(digest)) < 0) { | ||
| 142 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | overhead = 10 + 2 * field_size + md_size; | ||
| 147 | if (msg_len <= overhead) { | ||
| 148 | SM2error(SM2_R_INVALID_ARGUMENT); | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | *pl_size = msg_len - overhead; | ||
| 153 | return 1; | ||
| 154 | } | ||
| 155 | |||
| 156 | int | ||
| 157 | SM2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
| 158 | size_t *c_size) | ||
| 159 | { | ||
| 160 | size_t asn_size, field_size; | ||
| 161 | int md_size; | ||
| 162 | |||
| 163 | if ((field_size = ec_field_size(EC_KEY_get0_group(key))) == 0) { | ||
| 164 | SM2error(SM2_R_INVALID_FIELD); | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | if ((md_size = EVP_MD_size(digest)) < 0) { | ||
| 169 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | asn_size = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER) + | ||
| 174 | ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) + | ||
| 175 | ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); | ||
| 176 | |||
| 177 | *c_size = ASN1_object_size(1, asn_size, V_ASN1_SEQUENCE); | ||
| 178 | return 1; | ||
| 179 | } | ||
| 180 | |||
| 181 | int | ||
| 182 | sm2_kdf(uint8_t *key, size_t key_len, uint8_t *secret, size_t secret_len, | ||
| 183 | const EVP_MD *digest) | ||
| 184 | { | ||
| 185 | EVP_MD_CTX *hash; | ||
| 186 | uint8_t *hash_buf = NULL; | ||
| 187 | uint32_t ctr = 1; | ||
| 188 | uint8_t ctr_buf[4] = {0}; | ||
| 189 | size_t hadd, hlen; | ||
| 190 | int rc = 0; | ||
| 191 | |||
| 192 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
| 193 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 194 | goto err; | ||
| 195 | } | ||
| 196 | |||
| 197 | if ((hlen = EVP_MD_size(digest)) < 0) { | ||
| 198 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 199 | goto err; | ||
| 200 | } | ||
| 201 | if ((hash_buf = malloc(hlen)) == NULL) { | ||
| 202 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 203 | goto err; | ||
| 204 | } | ||
| 205 | |||
| 206 | EVP_MD_CTX_init(hash); | ||
| 207 | while ((key_len > 0) && (ctr != 0)) { | ||
| 208 | if (!EVP_DigestInit_ex(hash, digest, NULL)) { | ||
| 209 | SM2error(ERR_R_EVP_LIB); | ||
| 210 | goto err; | ||
| 211 | } | ||
| 212 | if (!EVP_DigestUpdate(hash, secret, secret_len)) { | ||
| 213 | SM2error(ERR_R_EVP_LIB); | ||
| 214 | goto err; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* big-endian counter representation */ | ||
| 218 | ctr_buf[0] = (ctr >> 24) & 0xff; | ||
| 219 | ctr_buf[1] = (ctr >> 16) & 0xff; | ||
| 220 | ctr_buf[2] = (ctr >> 8) & 0xff; | ||
| 221 | ctr_buf[3] = ctr & 0xff; | ||
| 222 | ctr++; | ||
| 223 | |||
| 224 | if (!EVP_DigestUpdate(hash, ctr_buf, 4)) { | ||
| 225 | SM2error(ERR_R_EVP_LIB); | ||
| 226 | goto err; | ||
| 227 | } | ||
| 228 | if (!EVP_DigestFinal(hash, hash_buf, NULL)) { | ||
| 229 | SM2error(ERR_R_EVP_LIB); | ||
| 230 | goto err; | ||
| 231 | } | ||
| 232 | |||
| 233 | hadd = key_len > hlen ? hlen : key_len; | ||
| 234 | memcpy(key, hash_buf, hadd); | ||
| 235 | memset(hash_buf, 0, hlen); | ||
| 236 | key_len -= hadd; | ||
| 237 | key += hadd; | ||
| 238 | } | ||
| 239 | |||
| 240 | rc = 1; | ||
| 241 | err: | ||
| 242 | free(hash_buf); | ||
| 243 | EVP_MD_CTX_free(hash); | ||
| 244 | return rc; | ||
| 245 | } | ||
| 246 | |||
| 247 | int | ||
| 248 | SM2_encrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *msg, | ||
| 249 | size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len) | ||
| 250 | { | ||
| 251 | SM2_Ciphertext ctext_struct; | ||
| 252 | EVP_MD_CTX *hash = NULL; | ||
| 253 | BN_CTX *ctx = NULL; | ||
| 254 | BIGNUM *order = NULL; | ||
| 255 | BIGNUM *k, *x1, *y1, *x2, *y2; | ||
| 256 | const EC_GROUP *group; | ||
| 257 | const EC_POINT *P; | ||
| 258 | EC_POINT *kG = NULL, *kP = NULL; | ||
| 259 | uint8_t *msg_mask = NULL, *x2y2 = NULL, *C3 = NULL; | ||
| 260 | size_t C3_size, field_size, i, x2size, y2size; | ||
| 261 | int rc = 0; | ||
| 262 | int clen; | ||
| 263 | |||
| 264 | ctext_struct.C2 = NULL; | ||
| 265 | ctext_struct.C3 = NULL; | ||
| 266 | |||
| 267 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
| 268 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 269 | goto err; | ||
| 270 | } | ||
| 271 | |||
| 272 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
| 273 | SM2error(SM2_R_INVALID_KEY); | ||
| 274 | goto err; | ||
| 275 | } | ||
| 276 | |||
| 277 | if ((order = BN_new()) == NULL) { | ||
| 278 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 279 | goto err; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (!EC_GROUP_get_order(group, order, NULL)) { | ||
| 283 | SM2error(SM2_R_INVALID_GROUP_ORDER); | ||
| 284 | goto err; | ||
| 285 | } | ||
| 286 | |||
| 287 | if ((P = EC_KEY_get0_public_key(key)) == NULL) { | ||
| 288 | SM2error(SM2_R_INVALID_KEY); | ||
| 289 | goto err; | ||
| 290 | } | ||
| 291 | |||
| 292 | if ((field_size = ec_field_size(group)) == 0) { | ||
| 293 | SM2error(SM2_R_INVALID_FIELD); | ||
| 294 | goto err; | ||
| 295 | } | ||
| 296 | |||
| 297 | if ((C3_size = EVP_MD_size(digest)) < 0) { | ||
| 298 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 299 | goto err; | ||
| 300 | } | ||
| 301 | |||
| 302 | if ((kG = EC_POINT_new(group)) == NULL) { | ||
| 303 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 304 | goto err; | ||
| 305 | } | ||
| 306 | if ((kP = EC_POINT_new(group)) == NULL) { | ||
| 307 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 308 | goto err; | ||
| 309 | } | ||
| 310 | |||
| 311 | if ((ctx = BN_CTX_new()) == NULL) { | ||
| 312 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 313 | goto err; | ||
| 314 | } | ||
| 315 | |||
| 316 | BN_CTX_start(ctx); | ||
| 317 | if ((k = BN_CTX_get(ctx)) == NULL) { | ||
| 318 | SM2error(ERR_R_BN_LIB); | ||
| 319 | goto err; | ||
| 320 | } | ||
| 321 | if ((x1 = BN_CTX_get(ctx)) == NULL) { | ||
| 322 | SM2error(ERR_R_BN_LIB); | ||
| 323 | goto err; | ||
| 324 | } | ||
| 325 | if ((x2 = BN_CTX_get(ctx)) == NULL) { | ||
| 326 | SM2error(ERR_R_BN_LIB); | ||
| 327 | goto err; | ||
| 328 | } | ||
| 329 | if ((y1 = BN_CTX_get(ctx)) == NULL) { | ||
| 330 | SM2error(ERR_R_BN_LIB); | ||
| 331 | goto err; | ||
| 332 | } | ||
| 333 | if ((y2 = BN_CTX_get(ctx)) == NULL) { | ||
| 334 | SM2error(ERR_R_BN_LIB); | ||
| 335 | goto err; | ||
| 336 | } | ||
| 337 | |||
| 338 | if ((x2y2 = calloc(2, field_size)) == NULL) { | ||
| 339 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 340 | goto err; | ||
| 341 | } | ||
| 342 | |||
| 343 | if ((C3 = calloc(1, C3_size)) == NULL) { | ||
| 344 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 345 | goto err; | ||
| 346 | } | ||
| 347 | |||
| 348 | memset(ciphertext_buf, 0, *ciphertext_len); | ||
| 349 | |||
| 350 | if (!BN_rand_range(k, order)) { | ||
| 351 | SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED); | ||
| 352 | goto err; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) { | ||
| 356 | SM2error(ERR_R_EC_LIB); | ||
| 357 | goto err; | ||
| 358 | } | ||
| 359 | |||
| 360 | if (!EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx)) { | ||
| 361 | SM2error(ERR_R_EC_LIB); | ||
| 362 | goto err; | ||
| 363 | } | ||
| 364 | |||
| 365 | if (!EC_POINT_mul(group, kP, NULL, P, k, ctx)) { | ||
| 366 | SM2error(ERR_R_EC_LIB); | ||
| 367 | goto err; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (!EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) { | ||
| 371 | SM2error(ERR_R_EC_LIB); | ||
| 372 | goto err; | ||
| 373 | } | ||
| 374 | |||
| 375 | if ((x2size = BN_num_bytes(x2)) > field_size || | ||
| 376 | (y2size = BN_num_bytes(y2)) > field_size) { | ||
| 377 | SM2error(SM2_R_BIGNUM_OUT_OF_RANGE); | ||
| 378 | goto err; | ||
| 379 | } | ||
| 380 | |||
| 381 | BN_bn2bin(x2, x2y2 + field_size - x2size); | ||
| 382 | BN_bn2bin(y2, x2y2 + 2 * field_size - y2size); | ||
| 383 | |||
| 384 | if ((msg_mask = calloc(1, msg_len)) == NULL) { | ||
| 385 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 386 | goto err; | ||
| 387 | } | ||
| 388 | |||
| 389 | if (!sm2_kdf(msg_mask, msg_len, x2y2, 2 * field_size, digest)) { | ||
| 390 | SM2error(SM2_R_KDF_FAILURE); | ||
| 391 | goto err; | ||
| 392 | } | ||
| 393 | |||
| 394 | for (i = 0; i != msg_len; i++) | ||
| 395 | msg_mask[i] ^= msg[i]; | ||
| 396 | |||
| 397 | if (!EVP_DigestInit(hash, digest)) { | ||
| 398 | SM2error(ERR_R_EVP_LIB); | ||
| 399 | goto err; | ||
| 400 | } | ||
| 401 | |||
| 402 | if (!EVP_DigestUpdate(hash, x2y2, field_size)) { | ||
| 403 | SM2error(ERR_R_EVP_LIB); | ||
| 404 | goto err; | ||
| 405 | } | ||
| 406 | |||
| 407 | if (!EVP_DigestUpdate(hash, msg, msg_len)) { | ||
| 408 | SM2error(ERR_R_EVP_LIB); | ||
| 409 | goto err; | ||
| 410 | } | ||
| 411 | |||
| 412 | if (!EVP_DigestUpdate(hash, x2y2 + field_size, field_size)) { | ||
| 413 | SM2error(ERR_R_EVP_LIB); | ||
| 414 | goto err; | ||
| 415 | } | ||
| 416 | |||
| 417 | if (!EVP_DigestFinal(hash, C3, NULL)) { | ||
| 418 | SM2error(ERR_R_EVP_LIB); | ||
| 419 | goto err; | ||
| 420 | } | ||
| 421 | |||
| 422 | ctext_struct.C1x = x1; | ||
| 423 | ctext_struct.C1y = y1; | ||
| 424 | if ((ctext_struct.C3 = ASN1_OCTET_STRING_new()) == NULL) { | ||
| 425 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 426 | goto err; | ||
| 427 | } | ||
| 428 | if ((ctext_struct.C2 = ASN1_OCTET_STRING_new()) == NULL) { | ||
| 429 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 430 | goto err; | ||
| 431 | } | ||
| 432 | if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size)) { | ||
| 433 | SM2error(ERR_R_INTERNAL_ERROR); | ||
| 434 | goto err; | ||
| 435 | } | ||
| 436 | if (!ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) { | ||
| 437 | SM2error(ERR_R_INTERNAL_ERROR); | ||
| 438 | goto err; | ||
| 439 | } | ||
| 440 | |||
| 441 | if ((clen = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf)) < 0) { | ||
| 442 | SM2error(ERR_R_INTERNAL_ERROR); | ||
| 443 | goto err; | ||
| 444 | } | ||
| 445 | |||
| 446 | *ciphertext_len = clen; | ||
| 447 | rc = 1; | ||
| 448 | |||
| 449 | err: | ||
| 450 | ASN1_OCTET_STRING_free(ctext_struct.C2); | ||
| 451 | ASN1_OCTET_STRING_free(ctext_struct.C3); | ||
| 452 | free(msg_mask); | ||
| 453 | free(x2y2); | ||
| 454 | free(C3); | ||
| 455 | EVP_MD_CTX_free(hash); | ||
| 456 | BN_CTX_end(ctx); | ||
| 457 | BN_CTX_free(ctx); | ||
| 458 | EC_POINT_free(kG); | ||
| 459 | EC_POINT_free(kP); | ||
| 460 | BN_free(order); | ||
| 461 | return rc; | ||
| 462 | } | ||
| 463 | |||
| 464 | int | ||
| 465 | SM2_decrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *ciphertext, | ||
| 466 | size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len) | ||
| 467 | { | ||
| 468 | SM2_Ciphertext *sm2_ctext = NULL; | ||
| 469 | EVP_MD_CTX *hash = NULL; | ||
| 470 | BN_CTX *ctx = NULL; | ||
| 471 | BIGNUM *x2, *y2; | ||
| 472 | const EC_GROUP *group; | ||
| 473 | EC_POINT *C1 = NULL; | ||
| 474 | const uint8_t *C2, *C3; | ||
| 475 | uint8_t *computed_C3 = NULL, *msg_mask = NULL, *x2y2 = NULL; | ||
| 476 | size_t field_size, x2size, y2size; | ||
| 477 | int msg_len = 0, rc = 0; | ||
| 478 | int hash_size, i; | ||
| 479 | |||
| 480 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
| 481 | SM2error(SM2_R_INVALID_KEY); | ||
| 482 | goto err; | ||
| 483 | } | ||
| 484 | |||
| 485 | if ((field_size = ec_field_size(group)) == 0) { | ||
| 486 | SM2error(SM2_R_INVALID_FIELD); | ||
| 487 | goto err; | ||
| 488 | } | ||
| 489 | |||
| 490 | if ((hash_size = EVP_MD_size(digest)) < 0) { | ||
| 491 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 492 | goto err; | ||
| 493 | } | ||
| 494 | |||
| 495 | memset(ptext_buf, 0xFF, *ptext_len); | ||
| 496 | |||
| 497 | if ((sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, | ||
| 498 | ciphertext_len)) == NULL) { | ||
| 499 | SM2error(SM2_R_ASN1_ERROR); | ||
| 500 | goto err; | ||
| 501 | } | ||
| 502 | |||
| 503 | if (sm2_ctext->C3->length != hash_size) { | ||
| 504 | SM2error(SM2_R_INVALID_ENCODING); | ||
| 505 | goto err; | ||
| 506 | } | ||
| 507 | |||
| 508 | C2 = sm2_ctext->C2->data; | ||
| 509 | C3 = sm2_ctext->C3->data; | ||
| 510 | msg_len = sm2_ctext->C2->length; | ||
| 511 | |||
| 512 | if ((ctx = BN_CTX_new()) == NULL) { | ||
| 513 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 514 | goto err; | ||
| 515 | } | ||
| 516 | |||
| 517 | BN_CTX_start(ctx); | ||
| 518 | if ((x2 = BN_CTX_get(ctx)) == NULL) { | ||
| 519 | SM2error(ERR_R_BN_LIB); | ||
| 520 | goto err; | ||
| 521 | } | ||
| 522 | if ((y2 = BN_CTX_get(ctx)) == NULL) { | ||
| 523 | SM2error(ERR_R_BN_LIB); | ||
| 524 | goto err; | ||
| 525 | } | ||
| 526 | |||
| 527 | if ((msg_mask = calloc(1, msg_len)) == NULL) { | ||
| 528 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 529 | goto err; | ||
| 530 | } | ||
| 531 | if ((x2y2 = calloc(2, field_size)) == NULL) { | ||
| 532 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 533 | goto err; | ||
| 534 | } | ||
| 535 | if ((computed_C3 = calloc(1, hash_size)) == NULL) { | ||
| 536 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 537 | goto err; | ||
| 538 | } | ||
| 539 | |||
| 540 | if ((C1 = EC_POINT_new(group)) == NULL) { | ||
| 541 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 542 | goto err; | ||
| 543 | } | ||
| 544 | |||
| 545 | if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x, | ||
| 546 | sm2_ctext->C1y, ctx)) | ||
| 547 | { | ||
| 548 | SM2error(ERR_R_EC_LIB); | ||
| 549 | goto err; | ||
| 550 | } | ||
| 551 | |||
| 552 | if (!EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key), | ||
| 553 | ctx)) { | ||
| 554 | SM2error(ERR_R_EC_LIB); | ||
| 555 | goto err; | ||
| 556 | } | ||
| 557 | |||
| 558 | if (!EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) { | ||
| 559 | SM2error(ERR_R_EC_LIB); | ||
| 560 | goto err; | ||
| 561 | } | ||
| 562 | |||
| 563 | if ((x2size = BN_num_bytes(x2)) > field_size || | ||
| 564 | (y2size = BN_num_bytes(y2)) > field_size) { | ||
| 565 | SM2error(SM2_R_BIGNUM_OUT_OF_RANGE); | ||
| 566 | goto err; | ||
| 567 | } | ||
| 568 | |||
| 569 | BN_bn2bin(x2, x2y2 + field_size - x2size); | ||
| 570 | BN_bn2bin(y2, x2y2 + 2 * field_size - y2size); | ||
| 571 | |||
| 572 | if (!sm2_kdf(msg_mask, msg_len, x2y2, 2 * field_size, digest)) { | ||
| 573 | SM2error(SM2_R_KDF_FAILURE); | ||
| 574 | goto err; | ||
| 575 | } | ||
| 576 | |||
| 577 | for (i = 0; i != msg_len; ++i) | ||
| 578 | ptext_buf[i] = C2[i] ^ msg_mask[i]; | ||
| 579 | |||
| 580 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
| 581 | SM2error(ERR_R_EVP_LIB); | ||
| 582 | goto err; | ||
| 583 | } | ||
| 584 | |||
| 585 | if (!EVP_DigestInit(hash, digest)) { | ||
| 586 | SM2error(ERR_R_EVP_LIB); | ||
| 587 | goto err; | ||
| 588 | } | ||
| 589 | |||
| 590 | if (!EVP_DigestUpdate(hash, x2y2, field_size)) { | ||
| 591 | SM2error(ERR_R_EVP_LIB); | ||
| 592 | goto err; | ||
| 593 | } | ||
| 594 | |||
| 595 | if (!EVP_DigestUpdate(hash, ptext_buf, msg_len)) { | ||
| 596 | SM2error(ERR_R_EVP_LIB); | ||
| 597 | goto err; | ||
| 598 | } | ||
| 599 | |||
| 600 | if (!EVP_DigestUpdate(hash, x2y2 + field_size, field_size)) { | ||
| 601 | SM2error(ERR_R_EVP_LIB); | ||
| 602 | goto err; | ||
| 603 | } | ||
| 604 | |||
| 605 | if (!EVP_DigestFinal(hash, computed_C3, NULL)) { | ||
| 606 | SM2error(ERR_R_EVP_LIB); | ||
| 607 | goto err; | ||
| 608 | } | ||
| 609 | |||
| 610 | if (memcmp(computed_C3, C3, hash_size) != 0) | ||
| 611 | goto err; | ||
| 612 | |||
| 613 | rc = 1; | ||
| 614 | *ptext_len = msg_len; | ||
| 615 | |||
| 616 | err: | ||
| 617 | if (rc == 0) | ||
| 618 | memset(ptext_buf, 0, *ptext_len); | ||
| 619 | |||
| 620 | free(msg_mask); | ||
| 621 | free(x2y2); | ||
| 622 | free(computed_C3); | ||
| 623 | EC_POINT_free(C1); | ||
| 624 | BN_CTX_end(ctx); | ||
| 625 | BN_CTX_free(ctx); | ||
| 626 | SM2_Ciphertext_free(sm2_ctext); | ||
| 627 | EVP_MD_CTX_free(hash); | ||
| 628 | |||
| 629 | return rc; | ||
| 630 | } | ||
| 631 | |||
| 632 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_err.c b/src/lib/libcrypto/sm2/sm2_err.c new file mode 100644 index 0000000000..d34123cbf9 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_err.c | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | /* $OpenBSD: sm2_err.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Generated by util/mkerr.pl DO NOT EDIT | ||
| 4 | * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Licensed under the OpenSSL license (the "License"). You may not use | ||
| 7 | * this file except in compliance with the License. You can obtain a copy | ||
| 8 | * in the file LICENSE in the source distribution or at | ||
| 9 | * https://www.openssl.org/source/license.html | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef OPENSSL_NO_SM2 | ||
| 13 | |||
| 14 | #include <openssl/err.h> | ||
| 15 | #include <openssl/sm2.h> | ||
| 16 | |||
| 17 | #ifndef OPENSSL_NO_ERR | ||
| 18 | |||
| 19 | #define ERR_FUNC(func) ERR_PACK(ERR_LIB_SM2,func,0) | ||
| 20 | #define ERR_REASON(reason) ERR_PACK(ERR_LIB_SM2,0,reason) | ||
| 21 | |||
| 22 | static ERR_STRING_DATA SM2_str_functs[] = { | ||
| 23 | {ERR_FUNC(0xfff), "CRYPTO_internal"}, | ||
| 24 | {0, NULL} | ||
| 25 | }; | ||
| 26 | |||
| 27 | static ERR_STRING_DATA SM2_str_reasons[] = { | ||
| 28 | {ERR_REASON(SM2_R_ASN1_ERROR), "asn1 error"}, | ||
| 29 | {ERR_REASON(SM2_R_ASN5_ERROR), "asn5 error"}, | ||
| 30 | {ERR_REASON(SM2_R_BAD_SIGNATURE), "bad signature"}, | ||
| 31 | {ERR_REASON(SM2_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"}, | ||
| 32 | {ERR_REASON(SM2_R_BUFFER_TOO_SMALL), "buffer too small"}, | ||
| 33 | {ERR_REASON(SM2_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"}, | ||
| 34 | {ERR_REASON(SM2_R_CURVE_DOES_NOT_SUPPORT_ECDH), "curve does not support ecdh"}, | ||
| 35 | {ERR_REASON(SM2_R_CURVE_DOES_NOT_SUPPORT_SIGNING), "curve does not support signing"}, | ||
| 36 | {ERR_REASON(SM2_R_D2I_ECPKPARAMETERS_FAILURE), "d2i ecpkparameters failure"}, | ||
| 37 | {ERR_REASON(SM2_R_DECODE_ERROR), "decode error"}, | ||
| 38 | {ERR_REASON(SM2_R_DIGEST_FAILURE), "digest calculation failure"}, | ||
| 39 | {ERR_REASON(SM2_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"}, | ||
| 40 | {ERR_REASON(SM2_R_EC_GROUP_NEW_BY_NAME_FAILURE), "ec group new by name failure"}, | ||
| 41 | {ERR_REASON(SM2_R_FIELD_TOO_LARGE), "field too large"}, | ||
| 42 | {ERR_REASON(SM2_R_GF2M_NOT_SUPPORTED), "gf2m not supported"}, | ||
| 43 | {ERR_REASON(SM2_R_GROUP2PKPARAMETERS_FAILURE), "group2pkparameters failure"}, | ||
| 44 | {ERR_REASON(SM2_R_I2D_ECPKPARAMETERS_FAILURE), "i2d ecpkparameters failure"}, | ||
| 45 | {ERR_REASON(SM2_R_INCOMPATIBLE_OBJECTS), "incompatible objects"}, | ||
| 46 | {ERR_REASON(SM2_R_INVALID_ARGUMENT), "invalid argument"}, | ||
| 47 | {ERR_REASON(SM2_R_INVALID_COMPRESSED_POINT), "invalid compressed point"}, | ||
| 48 | {ERR_REASON(SM2_R_INVALID_COMPRESSION_BIT), "invalid compression bit"}, | ||
| 49 | {ERR_REASON(SM2_R_INVALID_CURVE), "invalid curve"}, | ||
| 50 | {ERR_REASON(SM2_R_INVALID_DIGEST), "invalid digest"}, | ||
| 51 | {ERR_REASON(SM2_R_INVALID_DIGEST_TYPE), "invalid digest type"}, | ||
| 52 | {ERR_REASON(SM2_R_INVALID_ENCODING), "invalid encoding"}, | ||
| 53 | {ERR_REASON(SM2_R_INVALID_FIELD), "invalid field"}, | ||
| 54 | {ERR_REASON(SM2_R_INVALID_FORM), "invalid form"}, | ||
| 55 | {ERR_REASON(SM2_R_INVALID_GROUP_ORDER), "invalid group order"}, | ||
| 56 | {ERR_REASON(SM2_R_INVALID_KEY), "invalid key"}, | ||
| 57 | {ERR_REASON(SM2_R_INVALID_OUTPUT_LENGTH), "invalid output length"}, | ||
| 58 | {ERR_REASON(SM2_R_INVALID_PEER_KEY), "invalid peer key"}, | ||
| 59 | {ERR_REASON(SM2_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"}, | ||
| 60 | {ERR_REASON(SM2_R_INVALID_PRIVATE_KEY), "invalid private key"}, | ||
| 61 | {ERR_REASON(SM2_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"}, | ||
| 62 | {ERR_REASON(SM2_R_KDF_FAILURE), "kdf calculation failure"}, | ||
| 63 | {ERR_REASON(SM2_R_KDF_PARAMETER_ERROR), "kdf parameter error"}, | ||
| 64 | {ERR_REASON(SM2_R_KEYS_NOT_SET), "keys not set"}, | ||
| 65 | {ERR_REASON(SM2_R_MISSING_PARAMETERS), "missing parameters"}, | ||
| 66 | {ERR_REASON(SM2_R_MISSING_PRIVATE_KEY), "missing private key"}, | ||
| 67 | {ERR_REASON(SM2_R_NEED_NEW_SETUP_VALUES), "need new setup values"}, | ||
| 68 | {ERR_REASON(SM2_R_NOT_A_NIST_PRIME), "not a NIST prime"}, | ||
| 69 | {ERR_REASON(SM2_R_NOT_IMPLEMENTED), "not implemented"}, | ||
| 70 | {ERR_REASON(SM2_R_NOT_INITIALIZED), "not initialized"}, | ||
| 71 | {ERR_REASON(SM2_R_NO_PARAMETERS_SET), "no parameters set"}, | ||
| 72 | {ERR_REASON(SM2_R_NO_PRIVATE_VALUE), "no private value"}, | ||
| 73 | {ERR_REASON(SM2_R_OPERATION_NOT_SUPPORTED), "operation not supported"}, | ||
| 74 | {ERR_REASON(SM2_R_PASSED_NULL_PARAMETER), "passed null parameter"}, | ||
| 75 | {ERR_REASON(SM2_R_PEER_KEY_ERROR), "peer key error"}, | ||
| 76 | {ERR_REASON(SM2_R_PKPARAMETERS2GROUP_FAILURE), "pkparameters2group failure"}, | ||
| 77 | {ERR_REASON(SM2_R_POINT_ARITHMETIC_FAILURE), "point arithmetic failure"}, | ||
| 78 | {ERR_REASON(SM2_R_POINT_AT_INFINITY), "point at infinity"}, | ||
| 79 | {ERR_REASON(SM2_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"}, | ||
| 80 | {ERR_REASON(SM2_R_RANDOM_NUMBER_GENERATION_FAILED), "random number generation failed"}, | ||
| 81 | {ERR_REASON(SM2_R_SHARED_INFO_ERROR), "shared info error"}, | ||
| 82 | {ERR_REASON(SM2_R_SLOT_FULL), "slot full"}, | ||
| 83 | {ERR_REASON(SM2_R_UNDEFINED_GENERATOR), "undefined generator"}, | ||
| 84 | {ERR_REASON(SM2_R_UNDEFINED_ORDER), "undefined order"}, | ||
| 85 | {ERR_REASON(SM2_R_UNKNOWN_GROUP), "unknown group"}, | ||
| 86 | {ERR_REASON(SM2_R_UNKNOWN_ORDER), "unknown order"}, | ||
| 87 | {ERR_REASON(SM2_R_UNSUPPORTED_FIELD), "unsupported field"}, | ||
| 88 | {ERR_REASON(SM2_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"}, | ||
| 89 | {ERR_REASON(SM2_R_WRONG_ORDER), "wrong order"}, | ||
| 90 | {0, NULL} | ||
| 91 | }; | ||
| 92 | |||
| 93 | #endif | ||
| 94 | |||
| 95 | void | ||
| 96 | ERR_load_SM2_strings(void) | ||
| 97 | { | ||
| 98 | #ifndef OPENSSL_NO_ERR | ||
| 99 | if (ERR_func_error_string(SM2_str_functs[0].error) == NULL) { | ||
| 100 | ERR_load_strings(0, SM2_str_functs); | ||
| 101 | ERR_load_strings(0, SM2_str_reasons); | ||
| 102 | } | ||
| 103 | #endif | ||
| 104 | } | ||
| 105 | |||
| 106 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_locl.h b/src/lib/libcrypto/sm2/sm2_locl.h new file mode 100644 index 0000000000..2e1626824f --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_locl.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* $OpenBSD: sm2_locl.h,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef HEADER_SM2_LOCL_H | ||
| 19 | #define HEADER_SM2_LOCL_H | ||
| 20 | |||
| 21 | #include <openssl/ec.h> | ||
| 22 | #include <openssl/ecdsa.h> | ||
| 23 | |||
| 24 | __BEGIN_HIDDEN_DECLS | ||
| 25 | |||
| 26 | int sm2_compute_userid_digest(uint8_t *out, const EVP_MD *digest, | ||
| 27 | const uint8_t *uid, size_t uid_len, const EC_KEY *key); | ||
| 28 | |||
| 29 | /* | ||
| 30 | * SM2 signature operation. Computes ZA (user id digest) and then signs | ||
| 31 | * H(ZA || msg) using SM2 | ||
| 32 | */ | ||
| 33 | ECDSA_SIG *sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, | ||
| 34 | const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len); | ||
| 35 | |||
| 36 | int sm2_do_verify(const EC_KEY *key, const EVP_MD *digest, | ||
| 37 | const ECDSA_SIG *signature, const uint8_t *uid, size_t uid_len, | ||
| 38 | const uint8_t *msg, size_t msg_len); | ||
| 39 | |||
| 40 | __END_HIDDEN_DECLS | ||
| 41 | |||
| 42 | #endif | ||
| 43 | |||
diff --git a/src/lib/libcrypto/sm2/sm2_pmeth.c b/src/lib/libcrypto/sm2/sm2_pmeth.c new file mode 100644 index 0000000000..af6e180a70 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_pmeth.c | |||
| @@ -0,0 +1,316 @@ | |||
| 1 | /* $OpenBSD: sm2_pmeth.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef OPENSSL_NO_SM2 | ||
| 19 | |||
| 20 | #include <string.h> | ||
| 21 | |||
| 22 | #include <openssl/sm2.h> | ||
| 23 | #include <openssl/asn1t.h> | ||
| 24 | #include <openssl/x509.h> | ||
| 25 | #include <openssl/err.h> | ||
| 26 | #include <openssl/evp.h> | ||
| 27 | |||
| 28 | #include "evp_locl.h" | ||
| 29 | #include "sm2_locl.h" | ||
| 30 | |||
| 31 | /* SM2 pkey context structure */ | ||
| 32 | |||
| 33 | typedef struct { | ||
| 34 | /* key and paramgen group */ | ||
| 35 | EC_GROUP *gen_group; | ||
| 36 | /* message digest */ | ||
| 37 | const EVP_MD *md; | ||
| 38 | EVP_MD_CTX *md_ctx; | ||
| 39 | /* personalization string */ | ||
| 40 | uint8_t* uid; | ||
| 41 | size_t uid_len; | ||
| 42 | } SM2_PKEY_CTX; | ||
| 43 | |||
| 44 | static int | ||
| 45 | pkey_sm2_init(EVP_PKEY_CTX *ctx) | ||
| 46 | { | ||
| 47 | SM2_PKEY_CTX *dctx; | ||
| 48 | |||
| 49 | if ((dctx = calloc(1, sizeof(*dctx))) == NULL) { | ||
| 50 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | ctx->data = dctx; | ||
| 54 | return 1; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void | ||
| 58 | pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) | ||
| 59 | { | ||
| 60 | SM2_PKEY_CTX *dctx = ctx->data; | ||
| 61 | |||
| 62 | if (ctx == NULL || ctx->data == NULL) | ||
| 63 | return; | ||
| 64 | |||
| 65 | EC_GROUP_free(dctx->gen_group); | ||
| 66 | free(dctx->uid); | ||
| 67 | free(dctx); | ||
| 68 | ctx->data = NULL; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int | ||
| 72 | pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) | ||
| 73 | { | ||
| 74 | SM2_PKEY_CTX *dctx, *sctx; | ||
| 75 | |||
| 76 | if (!pkey_sm2_init(dst)) | ||
| 77 | return 0; | ||
| 78 | sctx = src->data; | ||
| 79 | dctx = dst->data; | ||
| 80 | if (sctx->gen_group) { | ||
| 81 | if ((dctx->gen_group = EC_GROUP_dup(sctx->gen_group)) == NULL) { | ||
| 82 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 83 | goto err; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | if (sctx->uid != NULL) { | ||
| 88 | if ((dctx->uid = malloc(sctx->uid_len)) == NULL) { | ||
| 89 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 90 | goto err; | ||
| 91 | } | ||
| 92 | memcpy(dctx->uid, sctx->uid, sctx->uid_len); | ||
| 93 | dctx->uid_len = sctx->uid_len; | ||
| 94 | } | ||
| 95 | |||
| 96 | dctx->md = sctx->md; | ||
| 97 | |||
| 98 | if (!EVP_MD_CTX_copy(dctx->md_ctx, sctx->md_ctx)) | ||
| 99 | goto err; | ||
| 100 | |||
| 101 | return 1; | ||
| 102 | |||
| 103 | err: | ||
| 104 | pkey_sm2_cleanup(dst); | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int | ||
| 109 | pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, | ||
| 110 | const unsigned char *tbs, size_t tbslen) | ||
| 111 | { | ||
| 112 | unsigned int sltmp; | ||
| 113 | int ret, sig_sz; | ||
| 114 | |||
| 115 | if ((sig_sz = ECDSA_size(ctx->pkey->pkey.ec)) <= 0) | ||
| 116 | return 0; | ||
| 117 | |||
| 118 | if (sig == NULL) { | ||
| 119 | *siglen = sig_sz; | ||
| 120 | return 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | if (*siglen < (size_t)sig_sz) { | ||
| 124 | SM2error(SM2_R_BUFFER_TOO_SMALL); | ||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | if ((ret = SM2_sign(tbs, tbslen, sig, &sltmp, ctx->pkey->pkey.ec)) <= 0) | ||
| 129 | return ret; | ||
| 130 | |||
| 131 | *siglen = (size_t)sltmp; | ||
| 132 | return 1; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int | ||
| 136 | pkey_sm2_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, | ||
| 137 | const unsigned char *tbs, size_t tbslen) | ||
| 138 | { | ||
| 139 | return SM2_verify(tbs, tbslen, sig, siglen, ctx->pkey->pkey.ec); | ||
| 140 | } | ||
| 141 | |||
| 142 | static int | ||
| 143 | pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, | ||
| 144 | const unsigned char *in, size_t inlen) | ||
| 145 | { | ||
| 146 | SM2_PKEY_CTX *dctx = ctx->data; | ||
| 147 | const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; | ||
| 148 | |||
| 149 | if (out == NULL) { | ||
| 150 | if (!SM2_ciphertext_size(ctx->pkey->pkey.ec, md, inlen, outlen)) | ||
| 151 | return -1; | ||
| 152 | else | ||
| 153 | return 1; | ||
| 154 | } | ||
| 155 | |||
| 156 | return SM2_encrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int | ||
| 160 | pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, | ||
| 161 | const unsigned char *in, size_t inlen) | ||
| 162 | { | ||
| 163 | SM2_PKEY_CTX *dctx = ctx->data; | ||
| 164 | const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; | ||
| 165 | |||
| 166 | if (out == NULL) { | ||
| 167 | if (!SM2_plaintext_size(ctx->pkey->pkey.ec, md, inlen, outlen)) | ||
| 168 | return -1; | ||
| 169 | else | ||
| 170 | return 1; | ||
| 171 | } | ||
| 172 | |||
| 173 | return SM2_decrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen); | ||
| 174 | } | ||
| 175 | |||
| 176 | static int | ||
| 177 | pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | ||
| 178 | { | ||
| 179 | SM2_PKEY_CTX *dctx = ctx->data; | ||
| 180 | EC_GROUP *group = NULL; | ||
| 181 | |||
| 182 | switch (type) { | ||
| 183 | case EVP_PKEY_CTRL_DIGESTINIT: | ||
| 184 | dctx->md_ctx = p2; | ||
| 185 | return 1; | ||
| 186 | |||
| 187 | case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: | ||
| 188 | if ((group = EC_GROUP_new_by_curve_name(p1)) == NULL) { | ||
| 189 | SM2error(SM2_R_INVALID_CURVE); | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | EC_GROUP_free(dctx->gen_group); | ||
| 193 | dctx->gen_group = group; | ||
| 194 | return 1; | ||
| 195 | |||
| 196 | case EVP_PKEY_CTRL_SM2_SET_UID: | ||
| 197 | if ((p1 < 0) || ((p1 == 0) && (p2 != NULL))) { | ||
| 198 | SM2error(SM2_R_INVALID_ARGUMENT); | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | if ((p1 > 0) && (p2 == NULL)) { | ||
| 202 | SM2error(ERR_R_PASSED_NULL_PARAMETER); | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | free(dctx->uid); | ||
| 206 | if (p2 == NULL) { | ||
| 207 | dctx->uid = NULL; | ||
| 208 | dctx->uid_len = 0; | ||
| 209 | return 1; | ||
| 210 | } | ||
| 211 | |||
| 212 | if ((dctx->uid = malloc(p1)) == NULL) { | ||
| 213 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 214 | return 1; | ||
| 215 | } | ||
| 216 | memcpy(dctx->uid, p2, p1); | ||
| 217 | dctx->uid_len = p1; | ||
| 218 | return 1; | ||
| 219 | |||
| 220 | case EVP_PKEY_CTRL_SM2_HASH_UID: | ||
| 221 | { | ||
| 222 | const EVP_MD* md; | ||
| 223 | uint8_t za[EVP_MAX_MD_SIZE] = {0}; | ||
| 224 | int md_len; | ||
| 225 | |||
| 226 | if (dctx->uid == NULL) { | ||
| 227 | SM2error(SM2_R_INVALID_ARGUMENT); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | if ((md = EVP_MD_CTX_md(dctx->md_ctx)) == NULL) { | ||
| 232 | SM2error(ERR_R_EVP_LIB); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | if ((md_len = EVP_MD_size(md)) < 0) { | ||
| 237 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | if (sm2_compute_userid_digest(za, md, dctx->uid, dctx->uid_len, | ||
| 242 | ctx->pkey->pkey.ec) != 1) { | ||
| 243 | SM2error(SM2_R_DIGEST_FAILURE); | ||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | return EVP_DigestUpdate(dctx->md_ctx, za, md_len); | ||
| 247 | } | ||
| 248 | |||
| 249 | case EVP_PKEY_CTRL_SM2_GET_UID_LEN: | ||
| 250 | if (p2 == NULL) { | ||
| 251 | SM2error(ERR_R_PASSED_NULL_PARAMETER); | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | *(size_t *)p2 = dctx->uid_len; | ||
| 255 | return 1; | ||
| 256 | |||
| 257 | case EVP_PKEY_CTRL_SM2_GET_UID: | ||
| 258 | if (p2 == NULL) { | ||
| 259 | SM2error(ERR_R_PASSED_NULL_PARAMETER); | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | if (dctx->uid_len == 0) { | ||
| 263 | return 1; | ||
| 264 | } | ||
| 265 | memcpy(p2, dctx->uid, dctx->uid_len); | ||
| 266 | return 1; | ||
| 267 | |||
| 268 | case EVP_PKEY_CTRL_MD: | ||
| 269 | dctx->md = p2; | ||
| 270 | return 1; | ||
| 271 | |||
| 272 | default: | ||
| 273 | return -2; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | static int | ||
| 278 | pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) | ||
| 279 | { | ||
| 280 | int nid; | ||
| 281 | |||
| 282 | if (strcmp(type, "ec_paramgen_curve") == 0) { | ||
| 283 | if (((nid = EC_curve_nist2nid(value)) == NID_undef) && | ||
| 284 | ((nid = OBJ_sn2nid(value)) == NID_undef) && | ||
| 285 | ((nid = OBJ_ln2nid(value)) == NID_undef)) { | ||
| 286 | SM2error(SM2_R_INVALID_CURVE); | ||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); | ||
| 290 | } else if (strcmp(type, "sm2_uid") == 0) { | ||
| 291 | return EVP_PKEY_CTX_set_sm2_uid(ctx, (void*) value, | ||
| 292 | (int)strlen(value)); | ||
| 293 | } | ||
| 294 | |||
| 295 | return -2; | ||
| 296 | } | ||
| 297 | |||
| 298 | const EVP_PKEY_METHOD sm2_pkey_meth = { | ||
| 299 | .pkey_id = EVP_PKEY_SM2, | ||
| 300 | .init = pkey_sm2_init, | ||
| 301 | .copy = pkey_sm2_copy, | ||
| 302 | .cleanup = pkey_sm2_cleanup, | ||
| 303 | |||
| 304 | .sign = pkey_sm2_sign, | ||
| 305 | |||
| 306 | .verify = pkey_sm2_verify, | ||
| 307 | |||
| 308 | .encrypt = pkey_sm2_encrypt, | ||
| 309 | |||
| 310 | .decrypt = pkey_sm2_decrypt, | ||
| 311 | |||
| 312 | .ctrl = pkey_sm2_ctrl, | ||
| 313 | .ctrl_str = pkey_sm2_ctrl_str | ||
| 314 | }; | ||
| 315 | |||
| 316 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_sign.c b/src/lib/libcrypto/sm2/sm2_sign.c new file mode 100644 index 0000000000..d306658a48 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_sign.c | |||
| @@ -0,0 +1,465 @@ | |||
| 1 | /* $OpenBSD: sm2_sign.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef OPENSSL_NO_SM2 | ||
| 19 | |||
| 20 | #include <string.h> | ||
| 21 | |||
| 22 | #include <openssl/sm2.h> | ||
| 23 | #include <openssl/evp.h> | ||
| 24 | #include <openssl/err.h> | ||
| 25 | #include <openssl/bn.h> | ||
| 26 | |||
| 27 | #include "bn_lcl.h" | ||
| 28 | #include "sm2_locl.h" | ||
| 29 | |||
| 30 | static BIGNUM * | ||
| 31 | sm2_compute_msg_hash(const EVP_MD *digest, const EC_KEY *key, | ||
| 32 | const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len) | ||
| 33 | { | ||
| 34 | EVP_MD_CTX *hash; | ||
| 35 | BIGNUM *e = NULL; | ||
| 36 | int md_size; | ||
| 37 | uint8_t *za = NULL; | ||
| 38 | |||
| 39 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
| 40 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 41 | goto err; | ||
| 42 | } | ||
| 43 | |||
| 44 | if ((md_size = EVP_MD_size(digest)) < 0) { | ||
| 45 | SM2error(SM2_R_INVALID_DIGEST); | ||
| 46 | goto err; | ||
| 47 | } | ||
| 48 | |||
| 49 | if ((za = calloc(1, md_size)) == NULL) { | ||
| 50 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 51 | goto err; | ||
| 52 | } | ||
| 53 | |||
| 54 | if (!sm2_compute_userid_digest(za, digest, uid, uid_len, key)) { | ||
| 55 | SM2error(SM2_R_DIGEST_FAILURE); | ||
| 56 | goto err; | ||
| 57 | } | ||
| 58 | |||
| 59 | if (!EVP_DigestInit(hash, digest)) { | ||
| 60 | SM2error(ERR_R_EVP_LIB); | ||
| 61 | goto err; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (!EVP_DigestUpdate(hash, za, md_size)) { | ||
| 65 | SM2error(ERR_R_EVP_LIB); | ||
| 66 | goto err; | ||
| 67 | } | ||
| 68 | |||
| 69 | if (!EVP_DigestUpdate(hash, msg, msg_len)) { | ||
| 70 | SM2error(ERR_R_EVP_LIB); | ||
| 71 | goto err; | ||
| 72 | } | ||
| 73 | |||
| 74 | /* reuse za buffer to hold H(ZA || M) */ | ||
| 75 | if (!EVP_DigestFinal(hash, za, NULL)) { | ||
| 76 | SM2error(ERR_R_EVP_LIB); | ||
| 77 | goto err; | ||
| 78 | } | ||
| 79 | |||
| 80 | e = BN_bin2bn(za, md_size, NULL); | ||
| 81 | |||
| 82 | err: | ||
| 83 | free(za); | ||
| 84 | EVP_MD_CTX_free(hash); | ||
| 85 | return e; | ||
| 86 | } | ||
| 87 | |||
| 88 | static ECDSA_SIG * | ||
| 89 | sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) | ||
| 90 | { | ||
| 91 | ECDSA_SIG *sig = NULL; | ||
| 92 | const EC_GROUP *group; | ||
| 93 | EC_POINT *kG = NULL; | ||
| 94 | BN_CTX *ctx = NULL; | ||
| 95 | const BIGNUM *dA; | ||
| 96 | BIGNUM *order = NULL, *r = NULL, *s = NULL; | ||
| 97 | BIGNUM *k, *rk, *tmp, *x1; | ||
| 98 | |||
| 99 | if ((dA = EC_KEY_get0_private_key(key)) == NULL) { | ||
| 100 | SM2error(SM2_R_INVALID_FIELD); | ||
| 101 | goto err; | ||
| 102 | } | ||
| 103 | |||
| 104 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
| 105 | SM2error(SM2_R_INVALID_FIELD); | ||
| 106 | goto err; | ||
| 107 | } | ||
| 108 | |||
| 109 | if ((order = BN_new()) == NULL) { | ||
| 110 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 111 | goto err; | ||
| 112 | } | ||
| 113 | |||
| 114 | if (!EC_GROUP_get_order(group, order, NULL)) { | ||
| 115 | SM2error(ERR_R_EC_LIB); | ||
| 116 | goto err; | ||
| 117 | } | ||
| 118 | |||
| 119 | if ((kG = EC_POINT_new(group)) == NULL) { | ||
| 120 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 121 | goto err; | ||
| 122 | } | ||
| 123 | |||
| 124 | if ((ctx = BN_CTX_new()) == NULL) { | ||
| 125 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 126 | goto err; | ||
| 127 | } | ||
| 128 | |||
| 129 | BN_CTX_start(ctx); | ||
| 130 | |||
| 131 | if ((k = BN_CTX_get(ctx)) == NULL) { | ||
| 132 | SM2error(ERR_R_BN_LIB); | ||
| 133 | goto err; | ||
| 134 | } | ||
| 135 | if ((rk = BN_CTX_get(ctx)) == NULL) { | ||
| 136 | SM2error(ERR_R_BN_LIB); | ||
| 137 | goto err; | ||
| 138 | } | ||
| 139 | if ((x1 = BN_CTX_get(ctx)) == NULL) { | ||
| 140 | SM2error(ERR_R_BN_LIB); | ||
| 141 | goto err; | ||
| 142 | } | ||
| 143 | if ((tmp = BN_CTX_get(ctx)) == NULL) { | ||
| 144 | SM2error(ERR_R_BN_LIB); | ||
| 145 | goto err; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* r and s are returned as part of sig, so they can't be part of ctx. */ | ||
| 149 | if ((r = BN_new()) == NULL) { | ||
| 150 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 151 | goto err; | ||
| 152 | } | ||
| 153 | if ((s = BN_new()) == NULL) { | ||
| 154 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 155 | goto err; | ||
| 156 | } | ||
| 157 | |||
| 158 | for (;;) { | ||
| 159 | if (!BN_rand_range(k, order)) { | ||
| 160 | SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED); | ||
| 161 | goto err; | ||
| 162 | } | ||
| 163 | |||
| 164 | if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) { | ||
| 165 | SM2error(ERR_R_EC_LIB); | ||
| 166 | goto err; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (!EC_POINT_get_affine_coordinates(group, kG, x1, NULL, | ||
| 170 | ctx)) { | ||
| 171 | SM2error(ERR_R_EC_LIB); | ||
| 172 | goto err; | ||
| 173 | } | ||
| 174 | |||
| 175 | if (!BN_mod_add(r, e, x1, order, ctx)) { | ||
| 176 | SM2error(ERR_R_BN_LIB); | ||
| 177 | goto err; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* try again if r == 0 or r + k == n */ | ||
| 181 | if (BN_is_zero(r)) | ||
| 182 | continue; | ||
| 183 | |||
| 184 | if (!BN_add(rk, r, k)) { | ||
| 185 | SM2error(ERR_R_BN_LIB); | ||
| 186 | goto err; | ||
| 187 | } | ||
| 188 | |||
| 189 | if (BN_cmp(rk, order) == 0) | ||
| 190 | continue; | ||
| 191 | |||
| 192 | if (!BN_add(s, dA, BN_value_one())) { | ||
| 193 | SM2error(ERR_R_BN_LIB); | ||
| 194 | goto err; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (!BN_mod_inverse_ct(s, s, order, ctx)) { | ||
| 198 | SM2error(ERR_R_BN_LIB); | ||
| 199 | goto err; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (!BN_mod_mul(tmp, dA, r, order, ctx)) { | ||
| 203 | SM2error(ERR_R_BN_LIB); | ||
| 204 | goto err; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (!BN_sub(tmp, k, tmp)) { | ||
| 208 | SM2error(ERR_R_BN_LIB); | ||
| 209 | goto err; | ||
| 210 | } | ||
| 211 | |||
| 212 | if (!BN_mod_mul(s, s, tmp, order, ctx)) { | ||
| 213 | SM2error(ERR_R_BN_LIB); | ||
| 214 | goto err; | ||
| 215 | } | ||
| 216 | |||
| 217 | if ((sig = ECDSA_SIG_new()) == NULL) { | ||
| 218 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 219 | goto err; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* sig takes ownership of r and s */ | ||
| 223 | if (!ECDSA_SIG_set0(sig, r, s)) { | ||
| 224 | SM2error(ERR_R_INTERNAL_ERROR); | ||
| 225 | goto err; | ||
| 226 | } | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | |||
| 230 | err: | ||
| 231 | if (sig == NULL) { | ||
| 232 | BN_free(r); | ||
| 233 | BN_free(s); | ||
| 234 | } | ||
| 235 | |||
| 236 | BN_free(order); | ||
| 237 | BN_CTX_end(ctx); | ||
| 238 | BN_CTX_free(ctx); | ||
| 239 | EC_POINT_free(kG); | ||
| 240 | return sig; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int | ||
| 244 | sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, const BIGNUM *e) | ||
| 245 | { | ||
| 246 | const EC_GROUP *group; | ||
| 247 | EC_POINT *pt = NULL; | ||
| 248 | const BIGNUM *r = NULL, *s = NULL; | ||
| 249 | BN_CTX *ctx = NULL; | ||
| 250 | BIGNUM *order, *t, *x1; | ||
| 251 | int ret = 0; | ||
| 252 | |||
| 253 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
| 254 | SM2error(SM2_R_INVALID_FIELD); | ||
| 255 | goto err; | ||
| 256 | } | ||
| 257 | |||
| 258 | if ((ctx = BN_CTX_new()) == NULL) { | ||
| 259 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 260 | goto err; | ||
| 261 | } | ||
| 262 | |||
| 263 | BN_CTX_start(ctx); | ||
| 264 | |||
| 265 | if ((order = BN_CTX_get(ctx)) == NULL) { | ||
| 266 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 267 | goto err; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (!EC_GROUP_get_order(group, order, NULL)) { | ||
| 271 | SM2error(ERR_R_EC_LIB); | ||
| 272 | goto err; | ||
| 273 | } | ||
| 274 | |||
| 275 | if ((pt = EC_POINT_new(group)) == NULL) { | ||
| 276 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 277 | goto err; | ||
| 278 | } | ||
| 279 | |||
| 280 | if ((t = BN_CTX_get(ctx)) == NULL) { | ||
| 281 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 282 | goto err; | ||
| 283 | } | ||
| 284 | if ((x1 = BN_CTX_get(ctx)) == NULL) { | ||
| 285 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 286 | goto err; | ||
| 287 | } | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Section 5.3.1 in https://tools.ietf.org/html/draft-shen-sm2-ecdsa-00 | ||
| 291 | * | ||
| 292 | * B1: verify that r' is in [1, n-1] | ||
| 293 | * B2: verify that s' is in [1, n-1] | ||
| 294 | * B3: set M' ~= ZA || M' | ||
| 295 | * B4: calculate e' = Hv(M'~) | ||
| 296 | * B5: verify that t = r' + s' (mod n) is not zero | ||
| 297 | * B6: calculate the point (x1', y1') = [s']G + [t]PA | ||
| 298 | * B7: verify that r' == e' + x1' (mod n) | ||
| 299 | */ | ||
| 300 | |||
| 301 | ECDSA_SIG_get0(sig, &r, &s); | ||
| 302 | |||
| 303 | /* B1: verify that r' is in [1, n-1] */ | ||
| 304 | if (BN_cmp(r, BN_value_one()) < 0 || BN_cmp(order, r) <= 0) { | ||
| 305 | SM2error(SM2_R_BAD_SIGNATURE); | ||
| 306 | goto err; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* B2: verify that s' is in [1, n-1] */ | ||
| 310 | if (BN_cmp(s, BN_value_one()) < 0 || BN_cmp(order, s) <= 0) { | ||
| 311 | SM2error(SM2_R_BAD_SIGNATURE); | ||
| 312 | goto err; | ||
| 313 | } | ||
| 314 | |||
| 315 | /* B5: verify that t = r + s is not zero */ | ||
| 316 | if (!BN_mod_add(t, r, s, order, ctx)) { | ||
| 317 | SM2error(ERR_R_BN_LIB); | ||
| 318 | goto err; | ||
| 319 | } | ||
| 320 | if (BN_is_zero(t)) { | ||
| 321 | SM2error(SM2_R_BAD_SIGNATURE); | ||
| 322 | goto err; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* B6: calculate pt = (x1', y1') = [s']G + [t]PA */ | ||
| 326 | if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)) { | ||
| 327 | SM2error(ERR_R_EC_LIB); | ||
| 328 | goto err; | ||
| 329 | } | ||
| 330 | |||
| 331 | if (!EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) { | ||
| 332 | SM2error(ERR_R_EC_LIB); | ||
| 333 | goto err; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* B7: verify that r' == e' + x1' (mod n) */ | ||
| 337 | if (!BN_mod_add(t, e, x1, order, ctx)) { | ||
| 338 | SM2error(ERR_R_BN_LIB); | ||
| 339 | goto err; | ||
| 340 | } | ||
| 341 | if (BN_cmp(r, t) == 0) | ||
| 342 | ret = 1; | ||
| 343 | |||
| 344 | err: | ||
| 345 | EC_POINT_free(pt); | ||
| 346 | BN_CTX_end(ctx); | ||
| 347 | BN_CTX_free(ctx); | ||
| 348 | return ret; | ||
| 349 | } | ||
| 350 | |||
| 351 | ECDSA_SIG * | ||
| 352 | sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, const uint8_t *uid, | ||
| 353 | size_t uid_len, const uint8_t *msg, size_t msg_len) | ||
| 354 | { | ||
| 355 | ECDSA_SIG *sig = NULL; | ||
| 356 | BIGNUM *e; | ||
| 357 | |||
| 358 | e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len); | ||
| 359 | if (e == NULL) { | ||
| 360 | SM2error(SM2_R_DIGEST_FAILURE); | ||
| 361 | goto err; | ||
| 362 | } | ||
| 363 | |||
| 364 | sig = sm2_sig_gen(key, e); | ||
| 365 | |||
| 366 | err: | ||
| 367 | BN_free(e); | ||
| 368 | return sig; | ||
| 369 | } | ||
| 370 | |||
| 371 | int | ||
| 372 | sm2_do_verify(const EC_KEY *key, const EVP_MD *digest, const ECDSA_SIG *sig, | ||
| 373 | const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len) | ||
| 374 | { | ||
| 375 | BIGNUM *e; | ||
| 376 | int ret = -1; | ||
| 377 | |||
| 378 | e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len); | ||
| 379 | if (e == NULL) { | ||
| 380 | SM2error(SM2_R_DIGEST_FAILURE); | ||
| 381 | goto err; | ||
| 382 | } | ||
| 383 | |||
| 384 | ret = sm2_sig_verify(key, sig, e); | ||
| 385 | |||
| 386 | err: | ||
| 387 | BN_free(e); | ||
| 388 | return ret; | ||
| 389 | } | ||
| 390 | |||
| 391 | int | ||
| 392 | SM2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, | ||
| 393 | unsigned int *siglen, EC_KEY *eckey) | ||
| 394 | { | ||
| 395 | BIGNUM *e; | ||
| 396 | ECDSA_SIG *s = NULL; | ||
| 397 | int outlen = 0; | ||
| 398 | int ret = -1; | ||
| 399 | |||
| 400 | if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) { | ||
| 401 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 402 | goto err; | ||
| 403 | } | ||
| 404 | |||
| 405 | if ((s = sm2_sig_gen(eckey, e)) == NULL) { | ||
| 406 | goto err; | ||
| 407 | } | ||
| 408 | |||
| 409 | if ((outlen = i2d_ECDSA_SIG(s, &sig)) < 0) { | ||
| 410 | SM2error(SM2_R_ASN1_ERROR); | ||
| 411 | goto err; | ||
| 412 | } | ||
| 413 | |||
| 414 | *siglen = outlen; | ||
| 415 | ret = 1; | ||
| 416 | |||
| 417 | err: | ||
| 418 | ECDSA_SIG_free(s); | ||
| 419 | BN_free(e); | ||
| 420 | return ret; | ||
| 421 | } | ||
| 422 | |||
| 423 | int | ||
| 424 | SM2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, | ||
| 425 | int sig_len, EC_KEY *eckey) | ||
| 426 | { | ||
| 427 | ECDSA_SIG *s; | ||
| 428 | BIGNUM *e = NULL; | ||
| 429 | const unsigned char *p = sig; | ||
| 430 | unsigned char *der = NULL; | ||
| 431 | int derlen = -1; | ||
| 432 | int ret = -1; | ||
| 433 | |||
| 434 | if ((s = ECDSA_SIG_new()) == NULL) { | ||
| 435 | SM2error(ERR_R_MALLOC_FAILURE); | ||
| 436 | goto err; | ||
| 437 | } | ||
| 438 | |||
| 439 | if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { | ||
| 440 | SM2error(SM2_R_INVALID_ENCODING); | ||
| 441 | goto err; | ||
| 442 | } | ||
| 443 | |||
| 444 | /* Ensure signature uses DER and doesn't have trailing garbage */ | ||
| 445 | derlen = i2d_ECDSA_SIG(s, &der); | ||
| 446 | if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { | ||
| 447 | SM2error(SM2_R_INVALID_ENCODING); | ||
| 448 | goto err; | ||
| 449 | } | ||
| 450 | |||
| 451 | if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) { | ||
| 452 | SM2error(ERR_R_BN_LIB); | ||
| 453 | goto err; | ||
| 454 | } | ||
| 455 | |||
| 456 | ret = sm2_sig_verify(eckey, s, e); | ||
| 457 | |||
| 458 | err: | ||
| 459 | free(der); | ||
| 460 | BN_free(e); | ||
| 461 | ECDSA_SIG_free(s); | ||
| 462 | return ret; | ||
| 463 | } | ||
| 464 | |||
| 465 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_za.c b/src/lib/libcrypto/sm2/sm2_za.c new file mode 100644 index 0000000000..2a7f2846ec --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_za.c | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* $OpenBSD: sm2_za.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef OPENSSL_NO_SM2 | ||
| 19 | |||
| 20 | #include <openssl/sm2.h> | ||
| 21 | #include <openssl/evp.h> | ||
| 22 | #include <openssl/bn.h> | ||
| 23 | #include <string.h> | ||
| 24 | |||
| 25 | int | ||
| 26 | sm2_compute_userid_digest(uint8_t *out, const EVP_MD *digest, uint8_t *uid, | ||
| 27 | size_t uid_len, const EC_KEY *key) | ||
| 28 | { | ||
| 29 | const EC_GROUP *group; | ||
| 30 | EVP_MD_CTX *hash = NULL; | ||
| 31 | BN_CTX *ctx = NULL; | ||
| 32 | BIGNUM *p, *a, *b, *xG, *yG, *xA, *yA; | ||
| 33 | uint8_t *buf = NULL; | ||
| 34 | uint16_t entla; | ||
| 35 | uint8_t e_byte; | ||
| 36 | int bytes, p_bytes; | ||
| 37 | int rc = 0; | ||
| 38 | |||
| 39 | if ((group = EC_KEY_get0_group(key)) == NULL) | ||
| 40 | goto err; | ||
| 41 | |||
| 42 | if ((hash = EVP_MD_CTX_new()) == NULL) | ||
| 43 | goto err; | ||
| 44 | |||
| 45 | if ((ctx = BN_CTX_new()) == NULL) | ||
| 46 | goto err; | ||
| 47 | |||
| 48 | if ((p = BN_CTX_get(ctx)) == NULL) | ||
| 49 | goto err; | ||
| 50 | if ((a = BN_CTX_get(ctx)) == NULL) | ||
| 51 | goto err; | ||
| 52 | if ((b = BN_CTX_get(ctx)) == NULL) | ||
| 53 | goto err; | ||
| 54 | if ((xG = BN_CTX_get(ctx)) == NULL) | ||
| 55 | goto err; | ||
| 56 | if ((yG = BN_CTX_get(ctx)) == NULL) | ||
| 57 | goto err; | ||
| 58 | if ((xA = BN_CTX_get(ctx)) == NULL) | ||
| 59 | goto err; | ||
| 60 | if ((yA = BN_CTX_get(ctx)) == NULL) | ||
| 61 | goto err; | ||
| 62 | |||
| 63 | memset(out, 0, EVP_MD_size(digest)); | ||
| 64 | |||
| 65 | if (!EVP_DigestInit(hash, digest)) | ||
| 66 | goto err; | ||
| 67 | |||
| 68 | /* | ||
| 69 | * ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA) | ||
| 70 | */ | ||
| 71 | |||
| 72 | if (uid_len >= 8192) | ||
| 73 | goto err; | ||
| 74 | |||
| 75 | entla = (unsigned short)(8 * uid_len); | ||
| 76 | |||
| 77 | e_byte = entla >> 8; | ||
| 78 | if (!EVP_DigestUpdate(hash, &e_byte, 1)) | ||
| 79 | goto err; | ||
| 80 | |||
| 81 | e_byte = entla & 0xFF; | ||
| 82 | if (!EVP_DigestUpdate(hash, &e_byte, 1)) | ||
| 83 | goto err; | ||
| 84 | |||
| 85 | if (!EVP_DigestUpdate(hash, uid, uid_len)) | ||
| 86 | goto err; | ||
| 87 | |||
| 88 | if (!EC_GROUP_get_curve(group, p, a, b, ctx)) | ||
| 89 | goto err; | ||
| 90 | |||
| 91 | p_bytes = BN_num_bytes(p); | ||
| 92 | |||
| 93 | if ((buf = calloc(1, p_bytes)) == NULL) | ||
| 94 | goto err; | ||
| 95 | |||
| 96 | if ((bytes = BN_num_bytes(a)) > p_bytes) | ||
| 97 | goto err; | ||
| 98 | BN_bn2bin(a, buf + p_bytes - bytes); | ||
| 99 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
| 100 | goto err; | ||
| 101 | |||
| 102 | if ((bytes = BN_num_bytes(b)) > p_bytes) | ||
| 103 | goto err; | ||
| 104 | memset(buf, 0, p_bytes - bytes); | ||
| 105 | BN_bn2bin(b, buf + p_bytes - bytes); | ||
| 106 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
| 107 | goto err; | ||
| 108 | |||
| 109 | if (!EC_POINT_get_affine_coordinates(group, | ||
| 110 | EC_GROUP_get0_generator(group), xG, yG, ctx)) | ||
| 111 | goto err; | ||
| 112 | |||
| 113 | if ((bytes = BN_num_bytes(xG)) > p_bytes) | ||
| 114 | goto err; | ||
| 115 | memset(buf, 0, p_bytes - bytes); | ||
| 116 | BN_bn2bin(xG, buf + p_bytes - bytes); | ||
| 117 | |||
| 118 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
| 119 | goto err; | ||
| 120 | |||
| 121 | if ((bytes = BN_num_bytes(yG)) > p_bytes) | ||
| 122 | goto err; | ||
| 123 | memset(buf, 0, p_bytes - bytes); | ||
| 124 | BN_bn2bin(yG, buf + p_bytes - bytes); | ||
| 125 | |||
| 126 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
| 127 | goto err; | ||
| 128 | |||
| 129 | if (!EC_POINT_get_affine_coordinates(group, | ||
| 130 | EC_KEY_get0_public_key(key), xA, yA, ctx)) | ||
| 131 | goto err; | ||
| 132 | |||
| 133 | if ((bytes = BN_num_bytes(xA)) > p_bytes) | ||
| 134 | goto err; | ||
| 135 | memset(buf, 0, p_bytes - bytes); | ||
| 136 | BN_bn2bin(xA, buf + p_bytes - bytes); | ||
| 137 | |||
| 138 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
| 139 | goto err; | ||
| 140 | |||
| 141 | if ((bytes = BN_num_bytes(yA)) > p_bytes) | ||
| 142 | goto err; | ||
| 143 | memset(buf, 0, p_bytes - bytes); | ||
| 144 | BN_bn2bin(yA, buf + p_bytes - bytes); | ||
| 145 | |||
| 146 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
| 147 | goto err; | ||
| 148 | |||
| 149 | if (!EVP_DigestFinal(hash, out, NULL)) | ||
| 150 | goto err; | ||
| 151 | |||
| 152 | rc = 1; | ||
| 153 | |||
| 154 | err: | ||
| 155 | free(buf); | ||
| 156 | BN_CTX_free(ctx); | ||
| 157 | EVP_MD_CTX_free(hash); | ||
| 158 | return rc; | ||
| 159 | } | ||
| 160 | |||
| 161 | #endif /* OPENSSL_NO_SM2 */ | ||
