xref: /openbsd-src/lib/libcrypto/sm2/sm2_za.c (revision 51892d90bfcefb54f7395f2f97f2099daa1c609c)
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
sm2_compute_userid_digest(uint8_t * out,const EVP_MD * digest,uint8_t * uid,size_t uid_len,const EC_KEY * key)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 */
162