int BN_hex2bn(BIGNUM **bn, const char *a)
{
    BIGNUM *ret = NULL;
    BN_ULONG l = 0;
    int neg = 0, h, m, i, j, k, c;
    int num;
    if ((a == NULL) || (*a == '\0'))
        return (0);
    if (*a == '-') {
        neg = 1;
        a++;
    }
    for (i = 0; isxdigit((unsigned char)a[i]); i++) ;
    num = i + neg;
    if (bn == NULL)
        return (num);
    if (*bn == NULL) {
        if ((ret = BN_new()) == NULL)
            return (0);
    } else {
        ret = *bn;
        BN_zero(ret);
    }
    if (bn_expand(ret, i * 4) == NULL)
        goto err;
    j = i;
    m = 0;
    h = 0;
    while (j > 0) {
        m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
        l = 0;
        for (;;) {
            c = a[j - m];
            if ((c >= '0') && (c <= '9'))
                k = c - '0';
            else if ((c >= 'a') && (c <= 'f'))
                k = c - 'a' + 10;
            else if ((c >= 'A') && (c <= 'F'))
                k = c - 'A' + 10;
            else
                k = 0;
            l = (l << 4) | k;
            if (--m <= 0) {
                ret->d[h++] = l;
                break;
            }
        }
        j -= (BN_BYTES * 2);
    }
    ret->top = h;
    bn_correct_top(ret);
    ret->neg = neg;
    *bn = ret;
    bn_check_top(ret);
    return (num);
 err:
    if (*bn == NULL)
        BN_free(ret);
    return (0);
}
['static void char2_field_tests(void)\n{\n    BN_CTX *ctx = NULL;\n    BIGNUM *p, *a, *b;\n    EC_GROUP *group;\n    EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 =\n        NULL, *C2_K571 = NULL;\n    EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 =\n        NULL, *C2_B571 = NULL;\n    EC_POINT *P, *Q, *R;\n    BIGNUM *x, *y, *z, *cof;\n    unsigned char buf[100];\n    size_t i, len;\n    int k;\n#  if 1\n    ctx = BN_CTX_new();\n    if (!ctx)\n        ABORT;\n#  endif\n    p = BN_new();\n    a = BN_new();\n    b = BN_new();\n    if (!p || !a || !b)\n        ABORT;\n    if (!BN_hex2bn(&p, "13"))\n        ABORT;\n    if (!BN_hex2bn(&a, "3"))\n        ABORT;\n    if (!BN_hex2bn(&b, "1"))\n        ABORT;\n    group = EC_GROUP_new(EC_GF2m_simple_method());\n    if (!group)\n        ABORT;\n    if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx))\n        ABORT;\n    {\n        EC_GROUP *tmp;\n        tmp = EC_GROUP_new(EC_GROUP_method_of(group));\n        if (!tmp)\n            ABORT;\n        if (!EC_GROUP_copy(tmp, group))\n            ABORT;\n        EC_GROUP_free(group);\n        group = tmp;\n    }\n    if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx))\n        ABORT;\n    fprintf(stdout,\n            "Curve defined by Weierstrass equation\\n     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");\n    BN_print_fp(stdout, p);\n    fprintf(stdout, ")\\n     a = 0x");\n    BN_print_fp(stdout, a);\n    fprintf(stdout, "\\n     b = 0x");\n    BN_print_fp(stdout, b);\n    fprintf(stdout, "\\n(0x... means binary polynomial)\\n");\n    P = EC_POINT_new(group);\n    Q = EC_POINT_new(group);\n    R = EC_POINT_new(group);\n    if (!P || !Q || !R)\n        ABORT;\n    if (!EC_POINT_set_to_infinity(group, P))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, P))\n        ABORT;\n    buf[0] = 0;\n    if (!EC_POINT_oct2point(group, Q, buf, 1, ctx))\n        ABORT;\n    if (!EC_POINT_add(group, P, P, Q, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, P))\n        ABORT;\n    x = BN_new();\n    y = BN_new();\n    z = BN_new();\n    cof = BN_new();\n    if (!x || !y || !z || !cof)\n        ABORT;\n    if (!BN_hex2bn(&x, "6"))\n        ABORT;\n#  ifdef OPENSSL_EC_BIN_PT_COMP\n    if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx))\n        ABORT;\n#  else\n    if (!BN_hex2bn(&y, "8"))\n        ABORT;\n    if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx))\n        ABORT;\n#  endif\n    if (!EC_POINT_is_on_curve(group, Q, ctx)) {\n#  ifdef OPENSSL_EC_BIN_PT_COMP\n        if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx))\n            ABORT;\n#  endif\n        fprintf(stderr, "Point is not on curve: x = 0x");\n        BN_print_fp(stderr, x);\n        fprintf(stderr, ", y = 0x");\n        BN_print_fp(stderr, y);\n        fprintf(stderr, "\\n");\n        ABORT;\n    }\n    fprintf(stdout, "A cyclic subgroup:\\n");\n    k = 100;\n    do {\n        if (k-- == 0)\n            ABORT;\n        if (EC_POINT_is_at_infinity(group, P))\n            fprintf(stdout, "     point at infinity\\n");\n        else {\n            if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx))\n                ABORT;\n            fprintf(stdout, "     x = 0x");\n            BN_print_fp(stdout, x);\n            fprintf(stdout, ", y = 0x");\n            BN_print_fp(stdout, y);\n            fprintf(stdout, "\\n");\n        }\n        if (!EC_POINT_copy(R, P))\n            ABORT;\n        if (!EC_POINT_add(group, P, P, Q, ctx))\n            ABORT;\n    }\n    while (!EC_POINT_is_at_infinity(group, P));\n    if (!EC_POINT_add(group, P, Q, R, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, P))\n        ABORT;\n#  ifdef OPENSSL_EC_BIN_PT_COMP\n    len =\n        EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf,\n                           sizeof buf, ctx);\n    if (len == 0)\n        ABORT;\n    if (!EC_POINT_oct2point(group, P, buf, len, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, Q, ctx))\n        ABORT;\n    fprintf(stdout, "Generator as octet string, compressed form:\\n     ");\n    for (i = 0; i < len; i++)\n        fprintf(stdout, "%02X", buf[i]);\n#  endif\n    len =\n        EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf,\n                           sizeof buf, ctx);\n    if (len == 0)\n        ABORT;\n    if (!EC_POINT_oct2point(group, P, buf, len, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, Q, ctx))\n        ABORT;\n    fprintf(stdout, "\\nGenerator as octet string, uncompressed form:\\n     ");\n    for (i = 0; i < len; i++)\n        fprintf(stdout, "%02X", buf[i]);\n#  ifdef OPENSSL_EC_BIN_PT_COMP\n    len =\n        EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf,\n                           ctx);\n    if (len == 0)\n        ABORT;\n    if (!EC_POINT_oct2point(group, P, buf, len, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, Q, ctx))\n        ABORT;\n    fprintf(stdout, "\\nGenerator as octet string, hybrid form:\\n     ");\n    for (i = 0; i < len; i++)\n        fprintf(stdout, "%02X", buf[i]);\n#  endif\n    fprintf(stdout, "\\n");\n    if (!EC_POINT_invert(group, P, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, R, ctx))\n        ABORT;\n    CHAR2_CURVE_TEST\n        ("NIST curve K-163",\n         "0800000000000000000000000000000000000000C9",\n         "1",\n         "1",\n         "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",\n         "0289070FB05D38FF58321F2E800536D538CCDAA3D9",\n         1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163, C2_K163);\n    CHAR2_CURVE_TEST\n        ("NIST curve B-163",\n         "0800000000000000000000000000000000000000C9",\n         "1",\n         "020A601907B8C953CA1481EB10512F78744A3205FD",\n         "03F0EBA16286A2D57EA0991168D4994637E8343E36",\n         "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",\n         1, "040000000000000000000292FE77E70C12A4234C33", "2", 163, C2_B163);\n    CHAR2_CURVE_TEST\n        ("NIST curve K-233",\n         "020000000000000000000000000000000000000004000000000000000001",\n         "0",\n         "1",\n         "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",\n         "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",\n         0,\n         "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",\n         "4", 233, C2_K233);\n    CHAR2_CURVE_TEST\n        ("NIST curve B-233",\n         "020000000000000000000000000000000000000004000000000000000001",\n         "000000000000000000000000000000000000000000000000000000000001",\n         "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",\n         "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",\n         "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",\n         1,\n         "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",\n         "2", 233, C2_B233);\n    CHAR2_CURVE_TEST\n        ("NIST curve K-283",\n         "0800000000000000000000000000000000000000000000000000000000000000000010A1",\n         "0",\n         "1",\n         "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",\n         "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",\n         0,\n         "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",\n         "4", 283, C2_K283);\n    CHAR2_CURVE_TEST\n        ("NIST curve B-283",\n         "0800000000000000000000000000000000000000000000000000000000000000000010A1",\n         "000000000000000000000000000000000000000000000000000000000000000000000001",\n         "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",\n         "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",\n         "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",\n         1,\n         "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",\n         "2", 283, C2_B283);\n    CHAR2_CURVE_TEST\n        ("NIST curve K-409",\n         "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",\n         "0",\n         "1",\n         "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",\n         "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",\n         1,\n         "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",\n         "4", 409, C2_K409);\n    CHAR2_CURVE_TEST\n        ("NIST curve B-409",\n         "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",\n         "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",\n         "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",\n         "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",\n         "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",\n         1,\n         "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",\n         "2", 409, C2_B409);\n    CHAR2_CURVE_TEST\n        ("NIST curve K-571",\n         "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",\n         "0",\n         "1",\n         "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",\n         "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",\n         0,\n         "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",\n         "4", 571, C2_K571);\n    CHAR2_CURVE_TEST\n        ("NIST curve B-571",\n         "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",\n         "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",\n         "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",\n         "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",\n         "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",\n         1,\n         "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",\n         "2", 571, C2_B571);\n    if (!EC_POINT_copy(Q, P))\n        ABORT;\n    if (EC_POINT_is_at_infinity(group, Q))\n        ABORT;\n    if (!EC_POINT_dbl(group, P, P, ctx))\n        ABORT;\n    if (!EC_POINT_is_on_curve(group, P, ctx))\n        ABORT;\n    if (!EC_POINT_invert(group, Q, ctx))\n        ABORT;\n    if (!EC_POINT_add(group, R, P, Q, ctx))\n        ABORT;\n    if (!EC_POINT_add(group, R, R, Q, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, R))\n        ABORT;\n    {\n        const EC_POINT *points[3];\n        const BIGNUM *scalars[3];\n        if (EC_POINT_is_at_infinity(group, Q))\n            ABORT;\n        points[0] = Q;\n        points[1] = Q;\n        points[2] = Q;\n        if (!BN_add(y, z, BN_value_one()))\n            ABORT;\n        if (BN_is_odd(y))\n            ABORT;\n        if (!BN_rshift1(y, y))\n            ABORT;\n        scalars[0] = y;\n        scalars[1] = y;\n        fprintf(stdout, "combined multiplication ...");\n        fflush(stdout);\n        if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, P, R, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, R, Q, ctx))\n            ABORT;\n        fprintf(stdout, ".");\n        fflush(stdout);\n        if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0))\n            ABORT;\n        if (!BN_add(z, z, y))\n            ABORT;\n        BN_set_negative(z, 1);\n        scalars[0] = y;\n        scalars[1] = z;\n        if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINT_is_at_infinity(group, P))\n            ABORT;\n        fprintf(stdout, ".");\n        fflush(stdout);\n        if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0))\n            ABORT;\n        if (!BN_add(z, x, y))\n            ABORT;\n        BN_set_negative(z, 1);\n        scalars[0] = x;\n        scalars[1] = y;\n        scalars[2] = z;\n        if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINT_is_at_infinity(group, P))\n            ABORT;\n        fprintf(stdout, " ok\\n\\n");\n    }\n#  if 0\n    timings(C2_K163, TIMING_BASE_PT, ctx);\n    timings(C2_K163, TIMING_RAND_PT, ctx);\n    timings(C2_K163, TIMING_SIMUL, ctx);\n    timings(C2_B163, TIMING_BASE_PT, ctx);\n    timings(C2_B163, TIMING_RAND_PT, ctx);\n    timings(C2_B163, TIMING_SIMUL, ctx);\n    timings(C2_K233, TIMING_BASE_PT, ctx);\n    timings(C2_K233, TIMING_RAND_PT, ctx);\n    timings(C2_K233, TIMING_SIMUL, ctx);\n    timings(C2_B233, TIMING_BASE_PT, ctx);\n    timings(C2_B233, TIMING_RAND_PT, ctx);\n    timings(C2_B233, TIMING_SIMUL, ctx);\n    timings(C2_K283, TIMING_BASE_PT, ctx);\n    timings(C2_K283, TIMING_RAND_PT, ctx);\n    timings(C2_K283, TIMING_SIMUL, ctx);\n    timings(C2_B283, TIMING_BASE_PT, ctx);\n    timings(C2_B283, TIMING_RAND_PT, ctx);\n    timings(C2_B283, TIMING_SIMUL, ctx);\n    timings(C2_K409, TIMING_BASE_PT, ctx);\n    timings(C2_K409, TIMING_RAND_PT, ctx);\n    timings(C2_K409, TIMING_SIMUL, ctx);\n    timings(C2_B409, TIMING_BASE_PT, ctx);\n    timings(C2_B409, TIMING_RAND_PT, ctx);\n    timings(C2_B409, TIMING_SIMUL, ctx);\n    timings(C2_K571, TIMING_BASE_PT, ctx);\n    timings(C2_K571, TIMING_RAND_PT, ctx);\n    timings(C2_K571, TIMING_SIMUL, ctx);\n    timings(C2_B571, TIMING_BASE_PT, ctx);\n    timings(C2_B571, TIMING_RAND_PT, ctx);\n    timings(C2_B571, TIMING_SIMUL, ctx);\n#  endif\n    if (ctx)\n        BN_CTX_free(ctx);\n    BN_free(p);\n    BN_free(a);\n    BN_free(b);\n    EC_GROUP_free(group);\n    EC_POINT_free(P);\n    EC_POINT_free(Q);\n    EC_POINT_free(R);\n    BN_free(x);\n    BN_free(y);\n    BN_free(z);\n    BN_free(cof);\n    if (C2_K163)\n        EC_GROUP_free(C2_K163);\n    if (C2_B163)\n        EC_GROUP_free(C2_B163);\n    if (C2_K233)\n        EC_GROUP_free(C2_K233);\n    if (C2_B233)\n        EC_GROUP_free(C2_B233);\n    if (C2_K283)\n        EC_GROUP_free(C2_K283);\n    if (C2_B283)\n        EC_GROUP_free(C2_B283);\n    if (C2_K409)\n        EC_GROUP_free(C2_K409);\n    if (C2_B409)\n        EC_GROUP_free(C2_B409);\n    if (C2_K571)\n        EC_GROUP_free(C2_K571);\n    if (C2_B571)\n        EC_GROUP_free(C2_B571);\n}', "int BN_hex2bn(BIGNUM **bn, const char *a)\n{\n    BIGNUM *ret = NULL;\n    BN_ULONG l = 0;\n    int neg = 0, h, m, i, j, k, c;\n    int num;\n    if ((a == NULL) || (*a == '\\0'))\n        return (0);\n    if (*a == '-') {\n        neg = 1;\n        a++;\n    }\n    for (i = 0; isxdigit((unsigned char)a[i]); i++) ;\n    num = i + neg;\n    if (bn == NULL)\n        return (num);\n    if (*bn == NULL) {\n        if ((ret = BN_new()) == NULL)\n            return (0);\n    } else {\n        ret = *bn;\n        BN_zero(ret);\n    }\n    if (bn_expand(ret, i * 4) == NULL)\n        goto err;\n    j = i;\n    m = 0;\n    h = 0;\n    while (j > 0) {\n        m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;\n        l = 0;\n        for (;;) {\n            c = a[j - m];\n            if ((c >= '0') && (c <= '9'))\n                k = c - '0';\n            else if ((c >= 'a') && (c <= 'f'))\n                k = c - 'a' + 10;\n            else if ((c >= 'A') && (c <= 'F'))\n                k = c - 'A' + 10;\n            else\n                k = 0;\n            l = (l << 4) | k;\n            if (--m <= 0) {\n                ret->d[h++] = l;\n                break;\n            }\n        }\n        j -= (BN_BYTES * 2);\n    }\n    ret->top = h;\n    bn_correct_top(ret);\n    ret->neg = neg;\n    *bn = ret;\n    bn_check_top(ret);\n    return (num);\n err:\n    if (*bn == NULL)\n        BN_free(ret);\n    return (0);\n}"]