int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
    int max, min, dif;
    BN_ULONG t1, t2, borrow, *rp;
    const BN_ULONG *ap, *bp;
    bn_check_top(a);
    bn_check_top(b);
    max = a->top;
    min = b->top;
    dif = max - min;
    if (dif < 0) {
        BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3);
        return 0;
    }
    if (bn_wexpand(r, max) == NULL)
        return 0;
    ap = a->d;
    bp = b->d;
    rp = r->d;
    borrow = bn_sub_words(rp, ap, bp, min);
    ap += min;
    rp += min;
    while (dif) {
        dif--;
        t1 = *(ap++);
        t2 = (t1 - borrow) & BN_MASK2;
        *(rp++) = t2;
        borrow &= (t1 == 0);
    }
    while (max && *--rp == 0)
        max--;
    r->top = max;
    r->neg = 0;
    bn_pollute(r);
    return 1;
}
['static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)\n{\n    const BIGNUM *dA = EC_KEY_get0_private_key(key);\n    const EC_GROUP *group = EC_KEY_get0_group(key);\n    const BIGNUM *order = EC_GROUP_get0_order(group);\n    ECDSA_SIG *sig = NULL;\n    EC_POINT *kG = NULL;\n    BN_CTX *ctx = NULL;\n    BIGNUM *k = NULL;\n    BIGNUM *rk = NULL;\n    BIGNUM *r = NULL;\n    BIGNUM *s = NULL;\n    BIGNUM *x1 = NULL;\n    BIGNUM *tmp = NULL;\n    kG = EC_POINT_new(group);\n    ctx = BN_CTX_new();\n    if (kG == NULL || ctx == NULL) {\n        SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);\n        goto done;\n    }\n    BN_CTX_start(ctx);\n    k = BN_CTX_get(ctx);\n    rk = BN_CTX_get(ctx);\n    x1 = BN_CTX_get(ctx);\n    tmp = BN_CTX_get(ctx);\n    if (tmp == NULL) {\n        SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);\n        goto done;\n    }\n    r = BN_new();\n    s = BN_new();\n    if (r == NULL || s == NULL) {\n        SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);\n        goto done;\n    }\n    for (;;) {\n        if (!BN_priv_rand_range(k, order)) {\n            SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);\n                goto done;\n        }\n        if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)\n                || !EC_POINT_get_affine_coordinates_GFp(group, kG, x1, NULL,\n                                                        ctx)\n                || !BN_mod_add(r, e, x1, order, ctx)) {\n            SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);\n            goto done;\n        }\n        if (BN_is_zero(r))\n            continue;\n        if (!BN_add(rk, r, k)) {\n            SM2err(SM2_F_SM2_SIG_GEN, ERR_R_INTERNAL_ERROR);\n            goto done;\n        }\n        if (BN_cmp(rk, order) == 0)\n            continue;\n        if (!BN_add(s, dA, BN_value_one())\n                || !BN_mod_inverse(s, s, order, ctx)\n                || !BN_mod_mul(tmp, dA, r, order, ctx)\n                || !BN_sub(tmp, k, tmp)\n                || !BN_mod_mul(s, s, tmp, order, ctx)) {\n            SM2err(SM2_F_SM2_SIG_GEN, ERR_R_BN_LIB);\n            goto done;\n        }\n        sig = ECDSA_SIG_new();\n        if (sig == NULL) {\n            SM2err(SM2_F_SM2_SIG_GEN, ERR_R_MALLOC_FAILURE);\n            goto done;\n        }\n        ECDSA_SIG_set0(sig, r, s);\n        break;\n    }\n done:\n    if (sig == NULL) {\n        BN_free(r);\n        BN_free(s);\n    }\n    BN_CTX_free(ctx);\n    EC_POINT_free(kG);\n    return sig;\n}', 'const BIGNUM *BN_value_one(void)\n{\n    static const BN_ULONG data_one = 1L;\n    static const BIGNUM const_one =\n        { (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA };\n    return &const_one;\n}', 'int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)\n{\n    int ret, r_neg, cmp_res;\n    bn_check_top(a);\n    bn_check_top(b);\n    if (a->neg == b->neg) {\n        r_neg = a->neg;\n        ret = BN_uadd(r, a, b);\n    } else {\n        cmp_res = BN_ucmp(a, b);\n        if (cmp_res > 0) {\n            r_neg = a->neg;\n            ret = BN_usub(r, a, b);\n        } else if (cmp_res < 0) {\n            r_neg = b->neg;\n            ret = BN_usub(r, b, a);\n        } else {\n            r_neg = 0;\n            BN_zero(r);\n            ret = 1;\n        }\n    }\n    r->neg = r_neg;\n    bn_check_top(r);\n    return ret;\n}', 'int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)\n{\n    int max, min, dif;\n    BN_ULONG t1, t2, borrow, *rp;\n    const BN_ULONG *ap, *bp;\n    bn_check_top(a);\n    bn_check_top(b);\n    max = a->top;\n    min = b->top;\n    dif = max - min;\n    if (dif < 0) {\n        BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3);\n        return 0;\n    }\n    if (bn_wexpand(r, max) == NULL)\n        return 0;\n    ap = a->d;\n    bp = b->d;\n    rp = r->d;\n    borrow = bn_sub_words(rp, ap, bp, min);\n    ap += min;\n    rp += min;\n    while (dif) {\n        dif--;\n        t1 = *(ap++);\n        t2 = (t1 - borrow) & BN_MASK2;\n        *(rp++) = t2;\n        borrow &= (t1 == 0);\n    }\n    while (max && *--rp == 0)\n        max--;\n    r->top = max;\n    r->neg = 0;\n    bn_pollute(r);\n    return 1;\n}']