static int bign_asn1_params2fieldid(BIGN_FIELDID* field, const bign_params* params) { int ok = 0; BIGNUM* p = NULL; octet rev[64]; // ����������� ������� �������� if (!params || !field) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2FIELDID, ERR_R_PASSED_NULL_PARAMETER); return 0; } // ����������� field if (field->fieldType) ASN1_OBJECT_free(field->fieldType); if (field->prime) ASN1_INTEGER_free(field->prime); // ���������� fieldType if (!(field->fieldType = OBJ_nid2obj(id_bign_primefield))) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2FIELDID, ERR_R_OBJ_LIB); goto err; } // ���������� prime memCopy(rev, params->p, params->l / 4); memRev(rev, params->l / 4); if (!(p = BN_new()) || !BN_bin2bn(rev, params->l / 4, p)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2FIELDID, ERR_R_MALLOC_FAILURE); goto err; } field->prime = BN_to_ASN1_INTEGER(p, NULL); if (!field->prime) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2FIELDID, ERR_R_ASN1_LIB); goto err; } ok = 1; // ����� err: p ? OPENSSL_free(p) : 0; memSetZero(rev, sizeof(rev)); return ok; }
err_t g12sVerify(const g12s_params* params, const octet hash[], const octet sig[], const octet pubkey[]) { err_t code; size_t m, mo; // состояние ec_o* ec; word* Q; /* [2n] открытый ключ / точка R */ word* r; /* [m] первая (старшая) часть подписи */ word* s; /* [m] вторая часть подписи */ word* e; /* [m] обработанное хэш-значение, v */ void* stack; // старт code = g12sCreateEc(&ec, params, g12sVerify_deep); ERR_CALL_CHECK(code); // размерности order m = W_OF_B(params->l); mo = O_OF_B(params->l); // проверить входные указатели if (!memIsValid(hash, mo) || !memIsValid(sig, 2 * mo) || !memIsValid(pubkey, 2 * ec->f->no)) { g12sCloseEc(ec); return ERR_BAD_INPUT; } // раскладка состояния Q = objEnd(ec, word); r = Q + 2 * ec->f->n; s = r + m; e = s + m; stack = e + m; // загрузить Q if (!qrFrom(ecX(Q), pubkey, ec->f, stack) || !qrFrom(ecY(Q, ec->f->n), pubkey + ec->f->no, ec->f, stack)) { g12sCloseEc(ec); return ERR_BAD_PUBKEY; } // загрузить r и s memCopy(s, sig + mo, mo); memRev(s, mo); wwFrom(s, s, mo); memCopy(r, sig, mo); memRev(r, mo); wwFrom(r, r, mo); if (wwIsZero(s, m) || wwIsZero(r, m) || wwCmp(s, ec->order, m) >= 0 || wwCmp(r, ec->order, m) >= 0) { g12sCloseEc(ec); return ERR_BAD_SIG; } // e <- hash \mod q memCopy(e, hash, mo); memRev(e, mo); wwFrom(e, e, mo); zzMod(e, e, m, ec->order, m, stack); // e == 0 => e <- 1 if (wwIsZero(e, m)) e[0] = 1; // e <- e^{-1} \mod q [v] zzInvMod(e, e, ec->order, m, stack); // s <- s e \mod q [z1] zzMulMod(s, s, e, ec->order, m, stack); // e <- - e r \mod q [z2] zzMulMod(e, e, r, ec->order, m, stack); zzNegMod(e, e, ec->order, m); // Q <- s P + e Q [z1 P + z2 Q = R] if (!ecAddMulA(Q, ec, stack, 2, ec->base, s, m, Q, e, m)) { g12sCloseEc(ec); return ERR_BAD_PARAMS; } // s <- x_Q \mod q [x_R \mod q] qrTo((octet*)Q, ecX(Q), ec->f, stack); wwFrom(Q, Q, ec->f->no); zzMod(s, Q, ec->f->n, ec->order, m, stack); // s == r? code = wwEq(r, s, m) ? ERR_OK : ERR_BAD_SIG; // завершение g12sCloseEc(ec); return code; }
err_t g12sSign(octet sig[], const g12s_params* params, const octet hash[], const octet privkey[], gen_i rng, void* rng_stack) { err_t code; size_t m, mo; // состояние ec_o* ec; word* d; /* [m] личный ключ */ word* e; /* [m] обработанное хэш-значение */ word* k; /* [m] одноразовый ключ */ word* C; /* [2n] вспомогательная точка */ word* r; /* [m] первая (старшая) часть подписи */ word* s; /* [m] вторая часть подписи */ void* stack; // проверить rng if (rng == 0) return ERR_BAD_RNG; // старт code = g12sCreateEc(&ec, params, g12sSign_deep); ERR_CALL_CHECK(code); // размерности order m = W_OF_B(params->l); mo = O_OF_B(params->l); // проверить входные указатели if (!memIsValid(hash, mo) || !memIsValid(privkey, mo) || !memIsValid(sig, 2 * mo)) { g12sCloseEc(ec); return ERR_BAD_INPUT; } // раскладка состояния d = objEnd(ec, word); e = d + m; k = e + m; C = k + m; r = C + 2 * ec->f->n; s = r + m; stack = s + m; // загрузить d wwFrom(d, privkey, mo); if (wwIsZero(d, m) || wwCmp(d, ec->order, m) >= 0) { g12sCloseEc(ec); return ERR_BAD_PRIVKEY; } // e <- hash \mod q memCopy(e, hash, mo); memRev(e, mo); wwFrom(e, e, mo); zzMod(e, e, m, ec->order, m, stack); // e == 0 => e <- 1 if (wwIsZero(e, m)) e[0] = 1; // k <-R {1,2,..., q - 1} gen_k: if (!zzRandNZMod(k, ec->order, m, rng, rng_stack)) { g12sCloseEc(ec); return ERR_BAD_RNG; } // C <- k P if (!ecMulA(C, ec->base, ec, k, m, stack)) { // если params корректны, то этого быть не должно g12sCloseEc(ec); return ERR_BAD_INPUT; } // r <- x_C \mod q qrTo((octet*)C, ecX(C), ec->f, stack); wwFrom(r, C, ec->f->no); zzMod(r, r, ec->f->n, ec->order, m, stack); // r == 0 => повторить генерацию k if (wwIsZero(r, m)) goto gen_k; // s <- (rd + ke) \mod q zzMulMod(k, k, e, ec->order, m, stack); zzMulMod(s, r, d, ec->order, m, stack); zzAddMod(s, s, k, ec->order, m); // выгрузить ЭЦП wwTo(sig, mo, s); wwTo(sig + mo, mo, r); memRev(sig, 2 * mo); // все нормально g12sCloseEc(ec); return ERR_OK; }
static int bign_asn1_ecp2params(bign_params* params, const BIGN_ECPARAMS* ecp) { int ok = 0; BIGNUM* p = NULL; // ������� �������� if (!params || !ecp) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, ERR_R_PASSED_NULL_PARAMETER); return 0; } memSetZero(params, sizeof(bign_params)); // ��������� �������� ���� GF(p) if (!ecp->fieldID || !ecp->fieldID->fieldType || OBJ_obj2nid(ecp->fieldID->fieldType) != id_bign_primefield || !ecp->fieldID->prime) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2GROUP, BEE2EVP_R_ASN1_ERROR); goto err; } p = ASN1_INTEGER_to_BN(ecp->fieldID->prime, NULL); if (!p) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, ERR_R_ASN1_LIB); goto err; } if (BN_is_negative(p) || BN_is_zero(p) || (params->l = (size_t)BN_num_bits(p)) != 256 && params->l != 384 && params->l != 512) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMETERS2GROUP, BEE2EVP_R_INVALID_FIELD); goto err; } params->l /= 2; // ��������� p if (!BN_bn2bin(p, params->p)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); goto err; } memRev(params->p, params->l / 4); // ��������� a � b if (!ecp->curve || !ecp->curve->a || !ecp->curve->a->data || !ecp->curve->b || !ecp->curve->b->data || ecp->curve->a->length != params->l / 4 || ecp->curve->b->length != params->l / 4) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, BEE2EVP_R_ASN1_ERROR); goto err; } memCopy(params->a, ecp->curve->a->data, params->l / 4); memCopy(params->b, ecp->curve->b->data, params->l / 4); // ��������� seed (optional) if (ecp->curve->seed) { if (ecp->curve->seed->length != 8) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, BEE2EVP_R_ASN1_ERROR); goto err; } memCopy(params->seed, ecp->curve->seed->data, 8); } // ��������� base if (!ecp->base || !ecp->base->data || ecp->base->length != params->l / 4) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, BEE2EVP_R_ASN1_ERROR); goto err; } memCopy(params->yG, ecp->base->data, params->l / 4); // ��������� order if ((p = ASN1_INTEGER_to_BN(ecp->order, p)) == NULL) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, ERR_R_ASN1_LIB); goto err; } if (BN_is_negative(p) || BN_is_zero(p) || BN_num_bits(p) != (int)params->l * 2) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, BEE2EVP_R_INVALID_GROUP_ORDER); goto err; } if (!BN_bn2bin(p, params->q)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); goto err; } memRev(params->q, params->l / 4); // ��������� cofactor (optional) if (ecp->cofactor) { if (!(p = ASN1_INTEGER_to_BN(ecp->cofactor, p)) || !BN_is_one(p)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_ECP2PARAMS, ERR_R_ASN1_LIB); goto err; } } ok = 1; err: p ? BN_free(p) : 0; return ok; }
static BIGN_ECPARAMS* bign_asn1_params2ecp(BIGN_ECPARAMS* ecp, const bign_params* params) { int ok = 0; BIGN_ECPARAMS* ret = ecp; BIGNUM* order = NULL; octet rev[64]; // ������� �������� if (!params) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_PASSED_NULL_PARAMETER); return 0; } // ����������� ������� if (!ret && !(ret = BIGN_ECPARAMS_new())) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_MALLOC_FAILURE); goto err; } // ���������� ������ (������ 1) ret->version = (long)1; // ���������� fieldID if (!bign_asn1_params2fieldid(ret->fieldID, params)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_EC_LIB); goto err; } // ���������� ������ if (!bign_asn1_params2curve(ret->curve, params)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_EC_LIB); goto err; } // ���������� ������� ����� if (!M_ASN1_OCTET_STRING_set(ret->base, params->yG, params->l / 4)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_ASN1_LIB); goto err; } // ���������� ������� memCopy(rev, params->q, params->l / 4); memRev(rev, params->l / 4); if (!(order = BN_new()) || !BN_bin2bn(rev, params->l / 4, order)) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_MALLOC_FAILURE); goto err; } ret->order = BN_to_ASN1_INTEGER(order, NULL); if (!ret->order) { BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_ASN1_LIB); goto err; } // ���������� �������� (optional, ������ 1) //if (!ASN1_INTEGER_set(ret->cofactor, (long)1)) //{ // BEE2EVPerr(BEE2EVP_F_BIGN_ASN1_PARAMS2ECP, ERR_R_ASN1_LIB); // goto err; //} ok = 1; err: if (!ok) { if (ret && !ecp) BIGN_ECPARAMS_free(ret); ret = NULL; } order ? BN_free(order) : 0; memSetZero(rev, sizeof(rev)); return ret; }