int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
    int max;
    int add = 0, neg = 0;

    bn_check_top(a);
    bn_check_top(b);

    /*-
     *  a -  b      a-b
     *  a - -b      a+b
     * -a -  b      -(a+b)
     * -a - -b      b-a
     */
    if (a->neg) {
        if (b->neg) {
            const BIGNUM *tmp;

            tmp = a;
            a = b;
            b = tmp;
        } else {
            add = 1;
            neg = 1;
        }
    } else {
        if (b->neg) {
            add = 1;
            neg = 0;
        }
    }

    if (add) {
        if (!BN_uadd(r, a, b))
            return 0;
        r->neg = neg;
        return 1;
    }

    /* We are actually doing a - b :-) */

    max = (a->top > b->top) ? a->top : b->top;
    if (bn_wexpand(r, max) == NULL)
        return 0;
    if (BN_ucmp(a, b) < 0) {
        if (!BN_usub(r, b, a))
            return 0;
        r->neg = 1;
    } else {
        if (!BN_usub(r, a, b))
            return 0;
        r->neg = 0;
    }
    bn_check_top(r);
    return 1;
}