BIGNUM * ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) { BIGNUM *ret; if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) ASN1error(ASN1_R_BN_LIB); else if (ai->type == V_ASN1_NEG_INTEGER) BN_set_negative(ret, 1); return (ret); }
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; BIGNUM *tmp_a; /* p must be a prime > 3 */ if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD); return 0; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); tmp_a = BN_CTX_get(ctx); if (tmp_a == NULL) goto err; /* group->field */ if (!BN_copy(&group->field, p)) goto err; BN_set_negative(&group->field, 0); /* group->a */ if (!BN_nnmod(tmp_a, a, p, ctx)) goto err; if (group->meth->field_encode) { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; } else if (!BN_copy(&group->a, tmp_a)) goto err; /* group->b */ if (!BN_nnmod(&group->b, b, p, ctx)) goto err; if (group->meth->field_encode) if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err; /* group->a_is_minus3 */ if (!BN_add_word(tmp_a, 3)) goto err; group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
BIGNUM * ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn) { BIGNUM *ret; if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) ASN1err(ASN1_F_ASN1_ENUMERATED_TO_BN, ASN1_R_BN_LIB); else if (ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret, 1); return (ret); }
extern "C" void Java_java_math_NativeBN_BN_1bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) { if (!oneValidHandle(env, ret)) return; ScopedByteArrayRO bytes(env, arr); if (bytes.get() == NULL) { return; } BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret)); if (!throwExceptionIfNecessary(env) && neg) { BN_set_negative(toBigNum(ret), true); } }
static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) { if (!oneValidHandle(env, ret)) return JNI_FALSE; ScopedByteArrayRO bytes(env, arr); if (bytes.get() == NULL) { return -1; } jboolean success = (BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, ret) != NULL); if (success && neg) { BN_set_negative(ret, 1); } return success; }
int BN_sub_word(BIGNUM *a, BN_ULONG w) { int i; bn_check_top(a); w &= BN_MASK2; /* degenerate case: w is zero */ if (!w) return 1; /* degenerate case: a is zero */ if(BN_is_zero(a)) { i = BN_set_word(a,w); if (i != 0) BN_set_negative(a, 1); return i; } /* handle 'a' when negative */ if (a->neg) { a->neg=0; i=BN_add_word(a,w); a->neg=1; return(i); } if ((a->top == 1) && (a->d[0] < w)) { a->d[0]=w-a->d[0]; a->neg=1; return(1); } i=0; for (;;) { if (a->d[i] >= w) { a->d[i]-=w; break; } else { a->d[i]=(a->d[i]-w)&BN_MASK2; i++; w=1; } } if ((a->d[i] == 0) && (i == (a->top-1))) a->top--; bn_check_top(a); return(1); }
/* Set the coordinates of an EC_POINT using affine coordinates. * Note that the simple implementation only uses affine coordinates. */ int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { int ret = 0; if (x == NULL || y == NULL) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!BN_copy(&point->X, x)) goto err; BN_set_negative(&point->X, 0); if (!BN_copy(&point->Y, y)) goto err; BN_set_negative(&point->Y, 0); if (!BN_copy(&point->Z, BN_value_one())) goto err; BN_set_negative(&point->Z, 0); point->Z_is_one = 1; ret = 1; err: return ret; }
static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) { if (!oneValidHandle(env, ret)) return JNI_FALSE; ScopedByteArrayRO bytes(env, arr); if (bytes.get() == NULL) { return -1; } jboolean success; const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get()); if ((bytes[0] & 0X80) == 0) { // Positive value! // // We can use the existing BN implementation for unsigned big endian bytes: // success = (BN_bin2bn(s, bytesLen, ret) != NULL); BN_set_negative(ret, JNI_FALSE); } else { // Negative value! // // We need to apply two's complement: // success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret); BN_set_negative(ret, JNI_TRUE); } return success; }
static BIGNUM * integer_to_BN(krb5_context context, const char *field, heim_integer *f) { BIGNUM *bn; bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); if (bn == NULL) { krb5_set_error_message(context, KRB5_BADMSGTYPE, "PKINIT: parsing BN failed %s", field); return NULL; } BN_set_negative(bn, f->negative); return bn; }
int BN_sub_word(BIGNUM *a, BN_ULONG w) { int i; // degenerate case: w is zero if (!w) { return 1; } // degenerate case: a is zero if (BN_is_zero(a)) { i = BN_set_word(a, w); if (i != 0) { BN_set_negative(a, 1); } return i; } // handle 'a' when negative if (a->neg) { a->neg = 0; i = BN_add_word(a, w); a->neg = 1; return i; } if ((bn_minimal_width(a) == 1) && (a->d[0] < w)) { a->d[0] = w - a->d[0]; a->neg = 1; return 1; } i = 0; for (;;) { if (a->d[i] >= w) { a->d[i] -= w; break; } else { a->d[i] -= w; i++; w = 1; } } if ((a->d[i] == 0) && (i == (a->width - 1))) { a->width--; } return 1; }
extern "C" void Java_java_math_NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) { if (!oneValidHandle(env, ret0)) return; BIGNUM* ret = toBigNum(ret0); ScopedByteArrayRO bytes(env, arr); if (bytes.get() == NULL) { return; } const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get()); if ((bytes[0] & 0X80) == 0) { // Positive value! // // We can use the existing BN implementation for unsigned big endian bytes: // BN_bin2bn(s, bytesLen, ret); BN_set_negative(ret, false); } else { // Negative value! // // We need to apply two's complement: // negBigEndianBytes2bn(env, cls, s, bytesLen, ret0); BN_set_negative(ret, true); } throwExceptionIfNecessary(env); }
/** * public static native boolean BN_bin2bn(byte[], int, int, int) */ static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass cls, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) { if (!oneValidHandle(env, ret)) return FALSE; jboolean success; unsigned char * tmpBytes; tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, arr, 0)); if (tmpBytes != NULL) { success = (BN_bin2bn(tmpBytes, len, ret) != NULL); if (neg) { BN_set_negative(ret, 1); } (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpBytes, JNI_ABORT); return success; } else return -1; // Error outside BN. mc FIXME: what to do in this case? Does JNI throw exception itself? }
void print_ascii(FILE *f, const struct number *n) { BIGNUM *v; int numbits, i, ch; v = BN_dup(n->number); bn_checkp(v); if (BN_is_negative(v)) BN_set_negative(v, 0); numbits = BN_num_bytes(v) * 8; while (numbits > 0) { ch = 0; for (i = 0; i < 8; i++) ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i); putc(ch, f); numbits -= 8; } BN_free(v); }
static int stackint(GPtrArray *stack, int index) { struct buffer *buf = stacktop(stack, index); BIGNUM bn; BN_init(&bn); int ret = -1; if (!CastToBigNum(&bn, buf)) goto out; if (!BN_is_negative(&bn)) ret = BN_get_word(&bn); else { BN_set_negative(&bn, 0); ret = BN_get_word(&bn); ret = -ret; } out: BN_clear_free(&bn); return ret; }
/* Computes scalar*point and stores the result in r. * point can not equal r. * Uses a modified algorithm 2P of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * * To protect against side-channel attack the function uses constant time swap, * avoiding conditional branches. */ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) { BIGNUM *x1, *x2, *z1, *z2; int ret = 0, i; BN_ULONG mask,word; if (r == point) { ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); return 0; } /* if result should be point at infinity */ if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || EC_POINT_is_at_infinity(group, point)) { return EC_POINT_set_to_infinity(group, r); } /* only support affine coordinates */ if (!point->Z_is_one) return 0; /* Since point_multiply is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); x1 = BN_CTX_get(ctx); z1 = BN_CTX_get(ctx); if (z1 == NULL) goto err; x2 = &r->X; z2 = &r->Y; bn_wexpand(x1, group->field.top); bn_wexpand(z1, group->field.top); bn_wexpand(x2, group->field.top); bn_wexpand(z2, group->field.top); if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ if (!BN_one(z1)) goto err; /* z1 = 1 */ if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ /* find top most bit and go one past it */ i = scalar->top - 1; mask = BN_TBIT; word = scalar->d[i]; while (!(word & mask)) mask >>= 1; mask >>= 1; /* if top most bit was at word break, go to next word */ if (!mask) { i--; mask = BN_TBIT; } for (; i >= 0; i--) { word = scalar->d[i]; while (mask) { BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); mask >>= 1; } mask = BN_TBIT; } /* convert out of "projective" coordinates */ i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); if (i == 0) goto err; else if (i == 1) { if (!EC_POINT_set_to_infinity(group, r)) goto err; } else { if (!BN_one(&r->Z)) goto err; r->Z_is_one = 1; } /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ BN_set_negative(&r->X, 0); BN_set_negative(&r->Y, 0); ret = 1; err: BN_CTX_end(ctx); return ret; }
extern "C" void Java_java_math_NativeBN_BN_1set_1negative(JNIEnv* env, jclass, jlong b, int n) { if (!oneValidHandle(env, b)) return; BN_set_negative(toBigNum(b), n); }
void prime_field_tests() { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL; EC_POINT *P, *Q, *R; BIGNUM *x, *y, *z; unsigned char buf[100]; size_t i, len; int k; #if 1 /* optional */ ctx = BN_CTX_new(); if (!ctx) ABORT; #endif p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; if (!BN_hex2bn(&p, "17")) ABORT; if (!BN_hex2bn(&a, "1")) ABORT; if (!BN_hex2bn(&b, "1")) ABORT; group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; { EC_GROUP *tmp; tmp = EC_GROUP_new(EC_GROUP_method_of(group)); if (!tmp) ABORT; if (!EC_GROUP_copy(tmp, group)) ABORT; EC_GROUP_free(group); group = tmp; } if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT; fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x"); BN_print_fp(stdout, p); fprintf(stdout, ")\n a = 0x"); BN_print_fp(stdout, a); fprintf(stdout, "\n b = 0x"); BN_print_fp(stdout, b); fprintf(stdout, "\n"); P = EC_POINT_new(group); Q = EC_POINT_new(group); R = EC_POINT_new(group); if (!P || !Q || !R) ABORT; if (!EC_POINT_set_to_infinity(group, P)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; buf[0] = 0; if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); if (!x || !y || !z) ABORT; if (!BN_hex2bn(&x, "D")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, Q, ctx)) { if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT; fprintf(stderr, "Point is not on curve: x = 0x"); BN_print_fp(stderr, x); fprintf(stderr, ", y = 0x"); BN_print_fp(stderr, y); fprintf(stderr, "\n"); ABORT; } fprintf(stdout, "A cyclic subgroup:\n"); k = 100; do { if (k-- == 0) ABORT; if (EC_POINT_is_at_infinity(group, P)) fprintf(stdout, " point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, " x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); } if (!EC_POINT_copy(R, P)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; #if 0 /* optional */ { EC_POINT *points[3]; points[0] = R; points[1] = Q; points[2] = P; if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT; } #endif } while (!EC_POINT_is_at_infinity(group, P)); if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octect string, compressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octect string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT; fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", Y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, ", Z = 0x"); BN_print_fp(stdout, z); fprintf(stdout, "\n"); if (!EC_POINT_invert(group, P, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; /* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000) * -- not a NIST curve, but commonly used */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT; if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT; if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 160) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_160, group)) ABORT; /* Curve P-192 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 192) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_192, group)) ABORT; /* Curve P-224 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT; if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 224) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_224, group)) ABORT; /* Curve P-256 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" "84F3B9CAC2FC632551")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-256 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 256) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_256, group)) ABORT; /* Curve P-384 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-384 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14" "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 384) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_384, group)) ABORT; /* Curve P-521 (FIPS PUB 186-2, App. 6) */ if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B" "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573" "DF883D2C34F1EF451FD46B503F00")) ABORT; if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F" "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" "3C1856A429BF97E7E31C2E5BD66")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" "C9B8899C47AEBB6FB71E91386409")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; fprintf(stdout, "\nNIST curve P-521 -- Generator:\n x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, "\n y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); /* G_y value taken from the standard: */ if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579" "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C" "7086A272C24088BE94769FD16650")) ABORT; if (0 != BN_cmp(y, z)) ABORT; fprintf(stdout, "verify degree ..."); if (EC_GROUP_get_degree(group) != 521) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "verify group order ..."); fflush(stdout); if (!EC_GROUP_get_order(group, z, ctx)) ABORT; if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, "."); fflush(stdout); #if 0 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; #endif if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, Q)) ABORT; fprintf(stdout, " ok\n"); if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; if (!EC_GROUP_copy(P_521, group)) ABORT; /* more tests using the last curve */ if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ { const EC_POINT *points[3]; const BIGNUM *scalars[3]; if (EC_POINT_is_at_infinity(group, Q)) ABORT; points[0] = Q; points[1] = Q; points[2] = Q; if (!BN_add(y, z, BN_value_one())) ABORT; if (BN_is_odd(y)) ABORT; if (!BN_rshift1(y, y)) ABORT; scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; fprintf(stdout, "combined multiplication ..."); fflush(stdout); /* z is still the group order */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; if (!BN_add(z, z, y)) ABORT; BN_set_negative(z, 1); scalars[0] = y; scalars[1] = z; /* z = -(order + y) */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; if (!BN_add(z, x, y)) ABORT; BN_set_negative(z, 1); scalars[0] = x; scalars[1] = y; scalars[2] = z; /* z = -(x+y) */ if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, " ok\n\n"); } #if 0 timings(P_160, TIMING_BASE_PT, ctx); timings(P_160, TIMING_RAND_PT, ctx); timings(P_160, TIMING_SIMUL, ctx); timings(P_192, TIMING_BASE_PT, ctx); timings(P_192, TIMING_RAND_PT, ctx); timings(P_192, TIMING_SIMUL, ctx); timings(P_224, TIMING_BASE_PT, ctx); timings(P_224, TIMING_RAND_PT, ctx); timings(P_224, TIMING_SIMUL, ctx); timings(P_256, TIMING_BASE_PT, ctx); timings(P_256, TIMING_RAND_PT, ctx); timings(P_256, TIMING_SIMUL, ctx); timings(P_384, TIMING_BASE_PT, ctx); timings(P_384, TIMING_RAND_PT, ctx); timings(P_384, TIMING_SIMUL, ctx); timings(P_521, TIMING_BASE_PT, ctx); timings(P_521, TIMING_RAND_PT, ctx); timings(P_521, TIMING_SIMUL, ctx); #endif if (ctx) BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); EC_GROUP_free(group); EC_POINT_free(P); EC_POINT_free(Q); EC_POINT_free(R); BN_free(x); BN_free(y); BN_free(z); if (P_160) EC_GROUP_free(P_160); if (P_192) EC_GROUP_free(P_192); if (P_224) EC_GROUP_free(P_224); if (P_256) EC_GROUP_free(P_256); if (P_384) EC_GROUP_free(P_384); if (P_521) EC_GROUP_free(P_521); }
void negate(struct number *n) { BN_set_negative(n->number, !BN_is_negative(n->number)); }
void char2_field_tests() { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL; EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL; EC_POINT *P, *Q, *R; BIGNUM *x, *y, *z, *cof; unsigned char buf[100]; size_t i, len; int k; #if 1 /* optional */ ctx = BN_CTX_new(); if (!ctx) ABORT; #endif p = BN_new(); a = BN_new(); b = BN_new(); if (!p || !a || !b) ABORT; if (!BN_hex2bn(&p, "13")) ABORT; if (!BN_hex2bn(&a, "3")) ABORT; if (!BN_hex2bn(&b, "1")) ABORT; group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m * so that the library gets to choose the EC_METHOD */ if (!group) ABORT; if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; { EC_GROUP *tmp; tmp = EC_GROUP_new(EC_GROUP_method_of(group)); if (!tmp) ABORT; if (!EC_GROUP_copy(tmp, group)) ABORT; EC_GROUP_free(group); group = tmp; } if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT; fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 + x*y = x^3 + a*x^2 + b (mod 0x"); BN_print_fp(stdout, p); fprintf(stdout, ")\n a = 0x"); BN_print_fp(stdout, a); fprintf(stdout, "\n b = 0x"); BN_print_fp(stdout, b); fprintf(stdout, "\n(0x... means binary polynomial)\n"); P = EC_POINT_new(group); Q = EC_POINT_new(group); R = EC_POINT_new(group); if (!P || !Q || !R) ABORT; if (!EC_POINT_set_to_infinity(group, P)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; buf[0] = 0; if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; x = BN_new(); y = BN_new(); z = BN_new(); cof = BN_new(); if (!x || !y || !z || !cof) ABORT; if (!BN_hex2bn(&x, "6")) ABORT; /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT; #else if (!BN_hex2bn(&y, "8")) ABORT; if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif if (!EC_POINT_is_on_curve(group, Q, ctx)) { /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif fprintf(stderr, "Point is not on curve: x = 0x"); BN_print_fp(stderr, x); fprintf(stderr, ", y = 0x"); BN_print_fp(stderr, y); fprintf(stderr, "\n"); ABORT; } fprintf(stdout, "A cyclic subgroup:\n"); k = 100; do { if (k-- == 0) ABORT; if (EC_POINT_is_at_infinity(group, P)) fprintf(stdout, " point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; fprintf(stdout, " x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); fprintf(stdout, "\n"); } if (!EC_POINT_copy(R, P)) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; } while (!EC_POINT_is_at_infinity(group, P)); if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octet string, compressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); #endif len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); #endif fprintf(stdout, "\n"); if (!EC_POINT_invert(group, P, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; /* Curve K-163 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-163", "0800000000000000000000000000000000000000C9", "1", "1", "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", "0289070FB05D38FF58321F2E800536D538CCDAA3D9", 1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163, C2_K163 ); /* Curve B-163 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-163", "0800000000000000000000000000000000000000C9", "1", "020A601907B8C953CA1481EB10512F78744A3205FD", "03F0EBA16286A2D57EA0991168D4994637E8343E36", "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", 1, "040000000000000000000292FE77E70C12A4234C33", "2", 163, C2_B163 ); /* Curve K-233 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-233", "020000000000000000000000000000000000000004000000000000000001", "0", "1", "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", 0, "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", "4", 233, C2_K233 ); /* Curve B-233 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-233", "020000000000000000000000000000000000000004000000000000000001", "000000000000000000000000000000000000000000000000000000000001", "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", 1, "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", "2", 233, C2_B233 ); /* Curve K-283 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-283", "0800000000000000000000000000000000000000000000000000000000000000000010A1", "0", "1", "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", 0, "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", "4", 283, C2_K283 ); /* Curve B-283 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-283", "0800000000000000000000000000000000000000000000000000000000000000000010A1", "000000000000000000000000000000000000000000000000000000000000000000000001", "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", 1, "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", "2", 283, C2_B283 ); /* Curve K-409 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-409", "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "0", "1", "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", 1, "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", "4", 409, C2_K409 ); /* Curve B-409 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-409", "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", 1, "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", "2", 409, C2_B409 ); /* Curve K-571 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve K-571", "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "0", "1", "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", 0, "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", "4", 571, C2_K571 ); /* Curve B-571 (FIPS PUB 186-2, App. 6) */ CHAR2_CURVE_TEST ( "NIST curve B-571", "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", 1, "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", "2", 571, C2_B571 ); /* more tests using the last curve */ if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ { const EC_POINT *points[3]; const BIGNUM *scalars[3]; if (EC_POINT_is_at_infinity(group, Q)) ABORT; points[0] = Q; points[1] = Q; points[2] = Q; if (!BN_add(y, z, BN_value_one())) ABORT; if (BN_is_odd(y)) ABORT; if (!BN_rshift1(y, y)) ABORT; scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; fprintf(stdout, "combined multiplication ..."); fflush(stdout); /* z is still the group order */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; if (!BN_add(z, z, y)) ABORT; BN_set_negative(z, 1); scalars[0] = y; scalars[1] = z; /* z = -(order + y) */ if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, "."); fflush(stdout); if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; if (!BN_add(z, x, y)) ABORT; BN_set_negative(z, 1); scalars[0] = x; scalars[1] = y; scalars[2] = z; /* z = -(x+y) */ if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) ABORT; fprintf(stdout, " ok\n\n"); } #if 0 timings(C2_K163, TIMING_BASE_PT, ctx); timings(C2_K163, TIMING_RAND_PT, ctx); timings(C2_K163, TIMING_SIMUL, ctx); timings(C2_B163, TIMING_BASE_PT, ctx); timings(C2_B163, TIMING_RAND_PT, ctx); timings(C2_B163, TIMING_SIMUL, ctx); timings(C2_K233, TIMING_BASE_PT, ctx); timings(C2_K233, TIMING_RAND_PT, ctx); timings(C2_K233, TIMING_SIMUL, ctx); timings(C2_B233, TIMING_BASE_PT, ctx); timings(C2_B233, TIMING_RAND_PT, ctx); timings(C2_B233, TIMING_SIMUL, ctx); timings(C2_K283, TIMING_BASE_PT, ctx); timings(C2_K283, TIMING_RAND_PT, ctx); timings(C2_K283, TIMING_SIMUL, ctx); timings(C2_B283, TIMING_BASE_PT, ctx); timings(C2_B283, TIMING_RAND_PT, ctx); timings(C2_B283, TIMING_SIMUL, ctx); timings(C2_K409, TIMING_BASE_PT, ctx); timings(C2_K409, TIMING_RAND_PT, ctx); timings(C2_K409, TIMING_SIMUL, ctx); timings(C2_B409, TIMING_BASE_PT, ctx); timings(C2_B409, TIMING_RAND_PT, ctx); timings(C2_B409, TIMING_SIMUL, ctx); timings(C2_K571, TIMING_BASE_PT, ctx); timings(C2_K571, TIMING_RAND_PT, ctx); timings(C2_K571, TIMING_SIMUL, ctx); timings(C2_B571, TIMING_BASE_PT, ctx); timings(C2_B571, TIMING_RAND_PT, ctx); timings(C2_B571, TIMING_SIMUL, ctx); #endif if (ctx) BN_CTX_free(ctx); BN_free(p); BN_free(a); BN_free(b); EC_GROUP_free(group); EC_POINT_free(P); EC_POINT_free(Q); EC_POINT_free(R); BN_free(x); BN_free(y); BN_free(z); BN_free(cof); if (C2_K163) EC_GROUP_free(C2_K163); if (C2_B163) EC_GROUP_free(C2_B163); if (C2_K233) EC_GROUP_free(C2_K233); if (C2_B233) EC_GROUP_free(C2_B233); if (C2_K283) EC_GROUP_free(C2_K283); if (C2_B283) EC_GROUP_free(C2_B283); if (C2_K409) EC_GROUP_free(C2_K409); if (C2_B409) EC_GROUP_free(C2_B409); if (C2_K571) EC_GROUP_free(C2_K571); if (C2_B571) EC_GROUP_free(C2_B571); }
int FuzzerTestOneInput(const uint8_t *buf, size_t len) { int success = 0; static BN_CTX *ctx; static BN_MONT_CTX *mont; static BIGNUM *b1; static BIGNUM *b2; static BIGNUM *b3; static BIGNUM *b4; static BIGNUM *b5; if (ctx == NULL) { b1 = BN_new(); b2 = BN_new(); b3 = BN_new(); b4 = BN_new(); b5 = BN_new(); ctx = BN_CTX_new(); mont = BN_MONT_CTX_new(); } // Divide the input into three parts, using the values of the first two // bytes to choose lengths, which generate b1, b2 and b3. Use three bits // of the third byte to choose signs for the three numbers. size_t l1 = 0, l2 = 0, l3 = 0; int s1 = 0, s2 = 0, s3 = 0; if (len > 2) { len -= 3; l1 = (buf[0] * len) / 255; ++buf; l2 = (buf[0] * (len - l1)) / 255; ++buf; l3 = len - l1 - l2; s1 = buf[0] & 1; s2 = buf[0] & 2; s3 = buf[0] & 4; ++buf; } OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1); BN_set_negative(b1, s1); OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2); BN_set_negative(b2, s2); OPENSSL_assert(BN_bin2bn(buf + l1 + l2, l3, b3) == b3); BN_set_negative(b3, s3); // mod 0 is undefined if (BN_is_zero(b3)) { success = 1; goto done; } OPENSSL_assert(BN_mod_exp(b4, b1, b2, b3, ctx)); OPENSSL_assert(BN_mod_exp_simple(b5, b1, b2, b3, ctx)); success = BN_cmp(b4, b5) == 0; if (!success) { BN_print_fp(stdout, b1); putchar('\n'); BN_print_fp(stdout, b2); putchar('\n'); BN_print_fp(stdout, b3); putchar('\n'); BN_print_fp(stdout, b4); putchar('\n'); BN_print_fp(stdout, b5); putchar('\n'); } done: OPENSSL_assert(success); return 0; }
/** * public static native void BN_set_negative(int, int) */ static void NativeBN_BN_set_negative(JNIEnv* env, jclass cls, BIGNUM* b, int n) { if (!oneValidHandle(env, b)) return; BN_set_negative(b, n); }
// generate_prime sets |out| to a prime with length |bits| such that |out|-1 is // relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to // |p|. static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e, const BIGNUM *p, const BIGNUM *sqrt2, BN_CTX *ctx, BN_GENCB *cb) { if (bits < 128 || (bits % BN_BITS2) != 0) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } // See FIPS 186-4 appendix B.3.3, steps 4 and 5. Note |bits| here is nlen/2. // Use the limit from steps 4.7 and 5.8 for most values of |e|. When |e| is 3, // the 186-4 limit is too low, so we use a higher one. Note this case is not // reachable from |RSA_generate_key_fips|. if (bits >= INT_MAX/32) { OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE); return 0; } int limit = BN_is_word(e, 3) ? bits * 32 : bits * 5; int ret = 0, tries = 0, rand_tries = 0; BN_CTX_start(ctx); BIGNUM *tmp = BN_CTX_get(ctx); if (tmp == NULL) { goto err; } for (;;) { // Generate a random number of length |bits| where the bottom bit is set // (steps 4.2, 4.3, 5.2 and 5.3) and the top bit is set (implied by the // bound checked below in steps 4.4 and 5.5). if (!BN_rand(out, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD) || !BN_GENCB_call(cb, BN_GENCB_GENERATED, rand_tries++)) { goto err; } if (p != NULL) { // If |p| and |out| are too close, try again (step 5.4). if (!BN_sub(tmp, out, p)) { goto err; } BN_set_negative(tmp, 0); if (!rsa_greater_than_pow2(tmp, bits - 100)) { continue; } } // If out < 2^(bits-1)×√2, try again (steps 4.4 and 5.5). This is equivalent // to out <= ⌊2^(bits-1)×√2⌋, or out <= sqrt2 for FIPS key sizes. // // For larger keys, the comparison is approximate, leaning towards // retrying. That is, we reject a negligible fraction of primes that are // within the FIPS bound, but we will never accept a prime outside the // bound, ensuring the resulting RSA key is the right size. if (BN_cmp(out, sqrt2) <= 0) { continue; } // Check gcd(out-1, e) is one (steps 4.5 and 5.6). if (!BN_sub(tmp, out, BN_value_one()) || !BN_gcd(tmp, tmp, e, ctx)) { goto err; } if (BN_is_one(tmp)) { // Test |out| for primality (steps 4.5.1 and 5.6.1). int is_probable_prime; if (!BN_primality_test(&is_probable_prime, out, BN_prime_checks, ctx, 1, cb)) { goto err; } if (is_probable_prime) { ret = 1; goto err; } } // If we've tried too many times to find a prime, abort (steps 4.7 and // 5.8). tries++; if (tries >= limit) { OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS); goto err; } if (!BN_GENCB_call(cb, 2, tries)) { goto err; } } err: BN_CTX_end(ctx); return ret; }
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; BIGNUM *tmp_a; /* p must be a prime > 3 */ if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD); return 0; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp_a = BN_CTX_get(ctx); if (tmp_a == NULL) { goto err; } /* group->field */ if (!BN_copy(&group->field, p)) { goto err; } BN_set_negative(&group->field, 0); /* group->a */ if (!BN_nnmod(tmp_a, a, p, ctx)) { goto err; } if (group->meth->field_encode) { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) { goto err; } } else if (!BN_copy(&group->a, tmp_a)) { goto err; } /* group->b */ if (!BN_nnmod(&group->b, b, p, ctx)) { goto err; } if (group->meth->field_encode && !group->meth->field_encode(group, &group->b, &group->b, ctx)) { goto err; } #if !defined(NDEBUG) /* ring: assert a == -3. */ if (!BN_add_word(tmp_a, 3)) { goto err; } assert(0 == BN_cmp(tmp_a, &group->field)); #endif ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int ret = 0; BN_CTX *new_ctx = NULL; BIGNUM *tmp_a; // p must be a prime > 3 if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD); return 0; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } BN_CTX_start(ctx); tmp_a = BN_CTX_get(ctx); if (tmp_a == NULL) { goto err; } // group->field if (!BN_copy(&group->field, p)) { goto err; } BN_set_negative(&group->field, 0); // Store the field in minimal form, so it can be used with |BN_ULONG| arrays. bn_set_minimal_width(&group->field); // group->a if (!BN_nnmod(tmp_a, a, &group->field, ctx)) { goto err; } if (group->meth->field_encode) { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) { goto err; } } else if (!BN_copy(&group->a, tmp_a)) { goto err; } // group->b if (!BN_nnmod(&group->b, b, &group->field, ctx)) { goto err; } if (group->meth->field_encode && !group->meth->field_encode(group, &group->b, &group->b, ctx)) { goto err; } // group->a_is_minus3 if (!BN_add_word(tmp_a, 3)) { goto err; } group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); if (group->meth->field_encode != NULL) { if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) { goto err; } } else if (!BN_copy(&group->one, BN_value_one())) { goto err; } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
static bool bp_script_eval(GPtrArray *stack, const GString *script, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { struct const_buffer pc = { script->str, script->len }; struct const_buffer pend = { script->str + script->len, 0 }; struct const_buffer pbegincodehash = { script->str, script->len }; struct bscript_op op; bool rc = false; GByteArray *vfExec = g_byte_array_new(); GPtrArray *altstack = g_ptr_array_new_with_free_func( (GDestroyNotify) buffer_free); BIGNUM bn; BN_init(&bn); if (script->len > 10000) goto out; bool fStrictEncodings = flags & SCRIPT_VERIFY_STRICTENC; unsigned int nOpCount = 0; struct bscript_parser bp; bsp_start(&bp, &pc); while (pc.p < pend.p) { bool fExec = !count_false(vfExec); if (!bsp_getop(&op, &bp)) goto out; enum opcodetype opcode = op.op; if (op.data.len > 520) goto out; if (opcode > OP_16 && ++nOpCount > 201) goto out; if (disabled_op[opcode]) goto out; if (fExec && is_bsp_pushdata(opcode)) stack_push(stack, (struct buffer *) &op.data); else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: bn_set_int(&bn, (int)opcode - (int)(OP_1 - 1)); stack_push_str(stack, bn_getvch(&bn)); break; // // Control // case OP_NOP: case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } guint8 vc = (guint8) fValue; g_byte_array_append(vfExec, &vc, 1); break; } case OP_ELSE: { if (vfExec->len == 0) goto out; guint8 *v = &vfExec->data[vfExec->len - 1]; *v = !(*v); break; } case OP_ENDIF: if (vfExec->len == 0) goto out; g_byte_array_remove_index(vfExec, vfExec->len - 1); break; case OP_VERIFY: { if (stack->len < 1) goto out; bool fValue = CastToBool(stacktop(stack, -1)); if (fValue) popstack(stack); else goto out; break; } case OP_RETURN: goto out; // // Stack ops // case OP_TOALTSTACK: if (stack->len < 1) goto out; stack_push(altstack, stacktop(stack, -1)); popstack(stack); break; case OP_FROMALTSTACK: if (altstack->len < 1) goto out; stack_push(stack, stacktop(altstack, -1)); popstack(altstack); break; case OP_2DROP: // (x1 x2 -- ) if (stack->len < 2) goto out; popstack(stack); popstack(stack); break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack->len < 3) goto out; struct buffer *vch1 = stacktop(stack, -3); struct buffer *vch2 = stacktop(stack, -2); struct buffer *vch3 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); stack_push(stack, vch3); break; } case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack->len < 4) goto out; struct buffer *vch1 = stacktop(stack, -4); struct buffer *vch2 = stacktop(stack, -3); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack->len < 6) goto out; struct buffer *vch1 = stack_take(stack, -6); struct buffer *vch2 = stack_take(stack, -5); g_ptr_array_remove_range(stack, stack->len - 6, 2); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2SWAP: // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack->len < 4) goto out; stack_swap(stack, -4, -2); stack_swap(stack, -3, -1); break; case OP_IFDUP: { // (x - 0 | x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); if (CastToBool(vch)) stack_push(stack, vch); break; } case OP_DEPTH: // -- stacksize BN_set_word(&bn, stack->len); stack_push_str(stack, bn_getvch(&bn)); break; case OP_DROP: // (x -- ) if (stack->len < 1) goto out; popstack(stack); break; case OP_DUP: { // (x -- x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); stack_push(stack, vch); break; } case OP_NIP: // (x1 x2 -- x2) if (stack->len < 2) goto out; g_ptr_array_remove_index(stack, stack->len - 2); break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -2); stack_push(stack, vch); break; } case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack->len < 2) goto out; int n = stackint(stack, -1); popstack(stack); if (n < 0 || n >= (int)stack->len) goto out; struct buffer *vch = stacktop(stack, -n-1); if (opcode == OP_ROLL) { vch = buffer_copy(vch->p, vch->len); g_ptr_array_remove_index(stack, stack->len - n - 1); stack_push_nocopy(stack, vch); } else stack_push(stack, vch); break; } case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack->len < 3) goto out; stack_swap(stack, -3, -2); stack_swap(stack, -2, -1); break; } case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack->len < 2) goto out; stack_swap(stack, -2, -1); break; } case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -1); stack_insert(stack, vch, -2); break; } case OP_SIZE: { // (in -- in size) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); BN_set_word(&bn, vch->len); stack_push_str(stack, bn_getvch(&bn)); break; } case OP_EQUAL: case OP_EQUALVERIFY: { // (x1 x2 - bool) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); bool fEqual = ((vch1->len == vch2->len) && memcmp(vch1->p, vch2->p, vch1->len) == 0); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack_push_char(stack, fEqual ? 1 : 0); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else goto out; } break; } // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack->len < 1) goto out; if (!CastToBigNum(&bn, stacktop(stack, -1))) goto out; switch (opcode) { case OP_1ADD: BN_add_word(&bn, 1); break; case OP_1SUB: BN_sub_word(&bn, 1); break; case OP_NEGATE: BN_set_negative(&bn, !BN_is_negative(&bn)); break; case OP_ABS: if (BN_is_negative(&bn)) BN_set_negative(&bn, 0); break; case OP_NOT: BN_set_word(&bn, BN_is_zero(&bn) ? 1 : 0); break; case OP_0NOTEQUAL: BN_set_word(&bn, BN_is_zero(&bn) ? 0 : 1); break; default: // impossible goto out; } popstack(stack); stack_push_str(stack, bn_getvch(&bn)); break; } case OP_ADD: case OP_SUB: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack->len < 2) goto out; BIGNUM bn1, bn2; BN_init(&bn1); BN_init(&bn2); if (!CastToBigNum(&bn1, stacktop(stack, -2)) || !CastToBigNum(&bn2, stacktop(stack, -1))) { BN_clear_free(&bn1); BN_clear_free(&bn2); goto out; } switch (opcode) { case OP_ADD: BN_add(&bn, &bn1, &bn2); break; case OP_SUB: BN_sub(&bn, &bn1, &bn2); break; case OP_BOOLAND: BN_set_word(&bn, (!BN_is_zero(&bn1) && !BN_is_zero(&bn2)) ? 1 : 0); break; case OP_BOOLOR: BN_set_word(&bn, (!BN_is_zero(&bn1) || !BN_is_zero(&bn2)) ? 1 : 0); break; case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) == 0) ? 1 : 0); break; case OP_NUMNOTEQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) != 0) ? 1 : 0); break; case OP_LESSTHAN: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) < 0) ? 1 : 0); break; case OP_GREATERTHAN: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) > 0) ? 1 : 0); break; case OP_LESSTHANOREQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) <= 0) ? 1 : 0); break; case OP_GREATERTHANOREQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) >= 0) ? 1 : 0); break; case OP_MIN: if (BN_cmp(&bn1, &bn2) < 0) BN_copy(&bn, &bn1); else BN_copy(&bn, &bn2); break; case OP_MAX: if (BN_cmp(&bn1, &bn2) > 0) BN_copy(&bn, &bn1); else BN_copy(&bn, &bn2); break; default: // impossible break; } popstack(stack); popstack(stack); stack_push_str(stack, bn_getvch(&bn)); BN_clear_free(&bn1); BN_clear_free(&bn2); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(stack, -1))) popstack(stack); else goto out; } break; } case OP_WITHIN: { // (x min max -- out) if (stack->len < 3) goto out; BIGNUM bn1, bn2, bn3; BN_init(&bn1); BN_init(&bn2); BN_init(&bn3); bool rc1 = CastToBigNum(&bn1, stacktop(stack, -3)); bool rc2 = CastToBigNum(&bn2, stacktop(stack, -2)); bool rc3 = CastToBigNum(&bn3, stacktop(stack, -1)); bool fValue = (BN_cmp(&bn2, &bn1) <= 0 && BN_cmp(&bn1, &bn3) < 0); popstack(stack); popstack(stack); popstack(stack); stack_push_char(stack, fValue ? 1 : 0); BN_clear_free(&bn1); BN_clear_free(&bn2); BN_clear_free(&bn3); if (!rc1 || !rc2 || !rc3) goto out; break; } // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); unsigned int hashlen; unsigned char md[32]; switch (opcode) { case OP_RIPEMD160: hashlen = 20; RIPEMD160(vch->p, vch->len, md); break; case OP_SHA1: hashlen = 20; SHA1(vch->p, vch->len, md); break; case OP_SHA256: hashlen = 32; SHA256(vch->p, vch->len, md); break; case OP_HASH160: hashlen = 20; bu_Hash160(md, vch->p, vch->len); break; case OP_HASH256: hashlen = 32; bu_Hash(md, vch->p, vch->len); break; default: // impossible goto out; } popstack(stack); struct buffer buf = { md, hashlen }; stack_push(stack, &buf); break; } case OP_CODESEPARATOR: // Hash starts after the code separator memcpy(&pbegincodehash, &pc, sizeof(pc)); break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack->len < 2) goto out; struct buffer *vchSig = stacktop(stack, -2); struct buffer *vchPubKey = stacktop(stack, -1); ////// debug print //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n"); //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n"); // Subset of script starting at the most recent codeseparator GString *scriptCode = g_string_sized_new(pbegincodehash.len); g_string_append_len(scriptCode, pbegincodehash.p, pbegincodehash.len); // Drop the signature, since there's no way for // a signature to sign itself string_find_del(scriptCode, vchSig); bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fSuccess) fSuccess = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); g_string_free(scriptCode, TRUE); popstack(stack); popstack(stack); stack_push_char(stack, fSuccess ? 1 : 0); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if ((int)stack->len < i) goto out; int nKeysCount = stackint(stack, -i); if (nKeysCount < 0 || nKeysCount > 20) goto out; nOpCount += nKeysCount; if (nOpCount > 201) goto out; int ikey = ++i; i += nKeysCount; if ((int)stack->len < i) goto out; int nSigsCount = stackint(stack, -i); if (nSigsCount < 0 || nSigsCount > nKeysCount) goto out; int isig = ++i; i += nSigsCount; if ((int)stack->len < i) goto out; // Subset of script starting at the most recent codeseparator GString *scriptCode = g_string_sized_new(pbegincodehash.len); g_string_append_len(scriptCode, pbegincodehash.p, pbegincodehash.len); // Drop the signatures, since there's no way for // a signature to sign itself int k; for (k = 0; k < nSigsCount; k++) { struct buffer *vchSig =stacktop(stack, -isig-k); string_find_del(scriptCode, vchSig); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { struct buffer *vchSig = stacktop(stack, -isig); struct buffer *vchPubKey = stacktop(stack, -ikey); // Check signature bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fOk) fOk = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed if (nSigsCount > nKeysCount) fSuccess = false; } g_string_free(scriptCode, TRUE); while (i-- > 0) popstack(stack); stack_push_char(stack, fSuccess ? 1 : 0); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } default: goto out; } if (stack->len + altstack->len > 1000) goto out; } rc = (vfExec->len == 0 && bp.error == false); out: BN_clear_free(&bn); g_ptr_array_free(altstack, TRUE); g_byte_array_unref(vfExec); return rc; }