]>
Commit | Line | Data |
---|---|---|
3d328a44 | 1 | /* |
b0edda11 | 2 | * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. |
3d328a44 JL |
3 | * Copyright 2017 Ribose Inc. All Rights Reserved. |
4 | * Ported from Ribose contributions from Botan. | |
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 | ||
e425f90f | 12 | #include "internal/sm2.h" |
3d328a44 JL |
13 | #include <openssl/evp.h> |
14 | #include <openssl/bn.h> | |
15 | #include <string.h> | |
16 | ||
17 | int SM2_compute_userid_digest(uint8_t *out, | |
18 | const EVP_MD *digest, | |
19 | const char *user_id, | |
20 | const EC_KEY *key) | |
21 | { | |
22 | int rc = 0; | |
23 | ||
24 | const EC_GROUP *group = EC_KEY_get0_group(key); | |
25 | ||
26 | BN_CTX *ctx = NULL; | |
27 | EVP_MD_CTX *hash = NULL; | |
28 | ||
29 | BIGNUM *p = NULL; | |
30 | BIGNUM *a = NULL; | |
31 | BIGNUM *b = NULL; | |
32 | ||
33 | BIGNUM *xG = NULL; | |
34 | BIGNUM *yG = NULL; | |
35 | BIGNUM *xA = NULL; | |
36 | BIGNUM *yA = NULL; | |
37 | ||
38 | int p_bytes = 0; | |
39 | uint8_t *buf = NULL; | |
40 | size_t uid_len = 0; | |
41 | uint16_t entla = 0; | |
42 | uint8_t e_byte = 0; | |
43 | ||
44 | hash = EVP_MD_CTX_new(); | |
45 | if (hash == NULL) | |
46 | goto done; | |
47 | ||
48 | ctx = BN_CTX_new(); | |
49 | if (ctx == NULL) | |
50 | goto done; | |
51 | ||
52 | p = BN_CTX_get(ctx); | |
53 | a = BN_CTX_get(ctx); | |
54 | b = BN_CTX_get(ctx); | |
55 | xG = BN_CTX_get(ctx); | |
56 | yG = BN_CTX_get(ctx); | |
57 | xA = BN_CTX_get(ctx); | |
58 | yA = BN_CTX_get(ctx); | |
59 | ||
60 | if (p == NULL || a == NULL || b == NULL || | |
61 | xG == NULL || yG == NULL || xA == NULL || yA == NULL) | |
62 | goto done; | |
63 | ||
64 | memset(out, 0, EVP_MD_size(digest)); | |
65 | ||
66 | if (EVP_DigestInit(hash, digest) == 0) | |
67 | goto done; | |
68 | ||
69 | /* | |
70 | ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA) | |
71 | */ | |
72 | ||
73 | uid_len = strlen(user_id); | |
74 | ||
75 | if (uid_len >= 8192) /* too large */ | |
76 | goto done; | |
77 | ||
78 | entla = (unsigned short)(8 * uid_len); | |
79 | ||
80 | e_byte = entla >> 8; | |
81 | if (EVP_DigestUpdate(hash, &e_byte, 1) == 0) | |
82 | goto done; | |
83 | e_byte = entla & 0xFF; | |
84 | if (EVP_DigestUpdate(hash, &e_byte, 1) == 0) | |
85 | goto done; | |
86 | ||
87 | if (EVP_DigestUpdate(hash, user_id, uid_len) == 0) | |
88 | goto done; | |
89 | ||
90 | if (EC_GROUP_get_curve_GFp(group, p, a, b, ctx) == 0) | |
91 | goto done; | |
92 | ||
93 | p_bytes = BN_num_bytes(p); | |
94 | buf = OPENSSL_zalloc(p_bytes); | |
95 | ||
96 | BN_bn2binpad(a, buf, p_bytes); | |
97 | if (EVP_DigestUpdate(hash, buf, p_bytes) == 0) | |
98 | goto done; | |
99 | BN_bn2binpad(b, buf, p_bytes); | |
100 | if (EVP_DigestUpdate(hash, buf, p_bytes) == 0) | |
101 | goto done; | |
102 | EC_POINT_get_affine_coordinates_GFp(group, | |
103 | EC_GROUP_get0_generator(group), | |
104 | xG, yG, ctx); | |
105 | BN_bn2binpad(xG, buf, p_bytes); | |
106 | if (EVP_DigestUpdate(hash, buf, p_bytes) == 0) | |
107 | goto done; | |
108 | BN_bn2binpad(yG, buf, p_bytes); | |
109 | if (EVP_DigestUpdate(hash, buf, p_bytes) == 0) | |
110 | goto done; | |
111 | ||
112 | EC_POINT_get_affine_coordinates_GFp(group, | |
113 | EC_KEY_get0_public_key(key), | |
114 | xA, yA, ctx); | |
115 | BN_bn2binpad(xA, buf, p_bytes); | |
116 | if (EVP_DigestUpdate(hash, buf, p_bytes) == 0) | |
117 | goto done; | |
118 | BN_bn2binpad(yA, buf, p_bytes); | |
119 | if (EVP_DigestUpdate(hash, buf, p_bytes) == 0) | |
120 | goto done; | |
121 | ||
122 | if (EVP_DigestFinal(hash, out, NULL) == 0) | |
123 | goto done; | |
124 | ||
125 | rc = 1; | |
126 | ||
127 | done: | |
128 | OPENSSL_free(buf); | |
129 | BN_CTX_free(ctx); | |
130 | EVP_MD_CTX_free(hash); | |
131 | return rc; | |
132 | } |