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