71 {
73
75 BN_CTX *ctx = NULL;
76
84 EC_POINT *O = NULL;
85 EC_POINT *Q = NULL;
88 int n = 0;
89 int i = recid / 2;
90
91 const EC_GROUP *group = EC_KEY_get0_group(eckey);
92 if ((ctx = BN_CTX_new()) == NULL) {
ret = -1;
goto err; }
93 BN_CTX_start(ctx);
94 order = BN_CTX_get(ctx);
95 if (!EC_GROUP_get_order(group, order, ctx)) {
ret = -2;
goto err; }
96 x = BN_CTX_get(ctx);
97 if (!BN_copy(x, order)) {
ret=-1;
goto err; }
98 if (!BN_mul_word(x, i)) {
ret=-1;
goto err; }
99 if (!BN_add(x, x, ecsig->r)) {
ret=-1;
goto err; }
100 field = BN_CTX_get(ctx);
101 if (!EC_GROUP_get_curve_GFp(group,
field, NULL, NULL, ctx)) {
ret=-2;
goto err; }
102 if (BN_cmp(x,
field) >= 0) {
ret=0;
goto err; }
103 if ((
R = EC_POINT_new(group)) == NULL) {
ret = -2;
goto err; }
104 if (!EC_POINT_set_compressed_coordinates_GFp(group,
R, x, recid % 2, ctx)) {
ret=0;
goto err; }
105 if (check)
106 {
107 if ((O = EC_POINT_new(group)) == NULL) {
ret = -2;
goto err; }
108 if (!EC_POINT_mul(group, O, NULL,
R, order, ctx)) {
ret=-2;
goto err; }
109 if (!EC_POINT_is_at_infinity(group, O)) {
ret = 0;
goto err; }
110 }
111 if ((Q = EC_POINT_new(group)) == NULL) {
ret = -2;
goto err; }
112 n = EC_GROUP_get_degree(group);
113 e = BN_CTX_get(ctx);
114 if (!BN_bin2bn(msg, msglen, e)) {
ret=-1;
goto err; }
115 if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
116 zero = BN_CTX_get(ctx);
117 if (!BN_zero(zero)) {
ret=-1;
goto err; }
118 if (!BN_mod_sub(e, zero, e, order, ctx)) {
ret=-1;
goto err; }
119 rr = BN_CTX_get(ctx);
120 if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) {
ret=-1;
goto err; }
121 sor = BN_CTX_get(ctx);
122 if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) {
ret=-1;
goto err; }
123 eor = BN_CTX_get(ctx);
124 if (!BN_mod_mul(eor, e, rr, order, ctx)) {
ret=-1;
goto err; }
125 if (!EC_POINT_mul(group, Q, eor,
R, sor, ctx)) {
ret=-2;
goto err; }
126 if (!EC_KEY_set_public_key(eckey, Q)) {
ret=-2;
goto err; }
127
129
130 err:
131 if (ctx) {
132 BN_CTX_end(ctx);
133 BN_CTX_free(ctx);
134 }
135 if (
R != NULL) EC_POINT_free(
R);
136 if (O != NULL) EC_POINT_free(O);
137 if (Q != NULL) EC_POINT_free(Q);
139 }
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)