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 25int 26sm2_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 */ 162