/* ** RSA Private key operation using CRT. */ static SECStatus rsa_PrivateKeyOpCRTNoCheck(RSAPrivateKey *key, mp_int *m, mp_int *c) { mp_int p, q, d_p, d_q, qInv; mp_int m1, m2, h, ctmp; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&d_p) = 0; MP_DIGITS(&d_q) = 0; MP_DIGITS(&qInv) = 0; MP_DIGITS(&m1) = 0; MP_DIGITS(&m2) = 0; MP_DIGITS(&h) = 0; MP_DIGITS(&ctmp) = 0; CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&d_p) ); CHECK_MPI_OK( mp_init(&d_q) ); CHECK_MPI_OK( mp_init(&qInv) ); CHECK_MPI_OK( mp_init(&m1) ); CHECK_MPI_OK( mp_init(&m2) ); CHECK_MPI_OK( mp_init(&h) ); CHECK_MPI_OK( mp_init(&ctmp) ); /* copy private key parameters into mp integers */ SECITEM_TO_MPINT(key->prime1, &p); /* p */ SECITEM_TO_MPINT(key->prime2, &q); /* q */ SECITEM_TO_MPINT(key->exponent1, &d_p); /* d_p = d mod (p-1) */ SECITEM_TO_MPINT(key->exponent2, &d_q); /* d_q = d mod (q-1) */ SECITEM_TO_MPINT(key->coefficient, &qInv); /* qInv = q**-1 mod p */ /* 1. m1 = c**d_p mod p */ CHECK_MPI_OK( mp_mod(c, &p, &ctmp) ); CHECK_MPI_OK( mp_exptmod(&ctmp, &d_p, &p, &m1) ); /* 2. m2 = c**d_q mod q */ CHECK_MPI_OK( mp_mod(c, &q, &ctmp) ); CHECK_MPI_OK( mp_exptmod(&ctmp, &d_q, &q, &m2) ); /* 3. h = (m1 - m2) * qInv mod p */ CHECK_MPI_OK( mp_submod(&m1, &m2, &p, &h) ); CHECK_MPI_OK( mp_mulmod(&h, &qInv, &p, &h) ); /* 4. m = m2 + h * q */ CHECK_MPI_OK( mp_mul(&h, &q, m) ); CHECK_MPI_OK( mp_add(m, &m2, m) ); cleanup: mp_clear(&p); mp_clear(&q); mp_clear(&d_p); mp_clear(&d_q); mp_clear(&qInv); mp_clear(&m1); mp_clear(&m2); mp_clear(&h); mp_clear(&ctmp); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
static int submod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return mpi_to_ltc_error(mp_submod(a,b,c,d)); }
int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y) { void *prime, *a, *b, *t1, *t2; int err; if ((err = mp_init_multi(&prime, &a, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } /* load prime, a and b */ if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) goto cleanup; if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) goto cleanup; if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) goto cleanup; /* compute y^2 */ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; /* compute x^3 */ if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; /* compute y^2 - x^3 - a*x */ if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; /* adjust range (0, prime) */ while (mp_cmp_d(t1, 0) == LTC_MP_LT) { if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; } while (mp_cmp(t1, prime) != LTC_MP_LT) { if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; } /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } cleanup: mp_clear_multi(prime, b, t1, t2, NULL); return err; }
int main(int argc, char *argv[]) { int ix; mp_int a, b, c, m; mp_digit r; if(argc < 4) { fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]); return 1; } printf("Test 4: Modular arithmetic\n\n"); mp_init(&a); mp_init(&b); mp_init(&m); mp_read_radix(&a, argv[1], 10); mp_read_radix(&b, argv[2], 10); mp_read_radix(&m, argv[3], 10); printf("a = "); mp_print(&a, stdout); fputc('\n', stdout); printf("b = "); mp_print(&b, stdout); fputc('\n', stdout); printf("m = "); mp_print(&m, stdout); fputc('\n', stdout); mp_init(&c); printf("\nc = a (mod m)\n"); mp_mod(&a, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b (mod m)\n"); mp_mod(&b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b (mod 1853)\n"); mp_mod_d(&b, 1853, &r); printf("c = %04X\n", r); printf("\nc = (a + b) mod m\n"); mp_addmod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = (a - b) mod m\n"); mp_submod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = (a * b) mod m\n"); mp_mulmod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = (a ** b) mod m\n"); mp_exptmod(&a, &b, &m, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nIn-place modular squaring test:\n"); for(ix = 0; ix < 5; ix++) { printf("a = (a * a) mod m a = "); mp_sqrmod(&a, &m, &a); mp_print(&a, stdout); fputc('\n', stdout); } mp_clear(&c); mp_clear(&m); mp_clear(&b); mp_clear(&a); return 0; }
/* Performs basic tests of elliptic curve cryptography over prime fields. * If tests fail, then it prints an error message, aborts, and returns an * error code. Otherwise, returns 0. */ int ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime, int generic) { mp_int one, order_1, gx, gy, rx, ry, n; int size; mp_err res; char s[1000]; /* initialize values */ MP_CHECKOK(mp_init(&one)); MP_CHECKOK(mp_init(&order_1)); MP_CHECKOK(mp_init(&gx)); MP_CHECKOK(mp_init(&gy)); MP_CHECKOK(mp_init(&rx)); MP_CHECKOK(mp_init(&ry)); MP_CHECKOK(mp_init(&n)); MP_CHECKOK(mp_set_int(&one, 1)); MP_CHECKOK(mp_sub(&group->order, &one, &order_1)); /* encode base point */ if (group->meth->field_dec) { MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth)); MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth)); } else { MP_CHECKOK(mp_copy(&group->genx, &gx)); MP_CHECKOK(mp_copy(&group->geny, &gy)); } if (ectestPrint) { /* output base point */ printf(" base point P:\n"); MP_CHECKOK(mp_toradix(&gx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&gy, s, 16)); printf(" %s\n", s); if (group->meth->field_enc) { printf(" base point P (encoded):\n"); MP_CHECKOK(mp_toradix(&group->genx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&group->geny, s, 16)); printf(" %s\n", s); } } #ifdef ECL_ENABLE_GFP_PT_MUL_AFF /* multiply base point by order - 1 and check for negative of base * point */ MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group)); if (ectestPrint) { printf(" (order-1)*P (affine):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth)); if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) { printf(" Error: invalid result (expected (- base point)).\n"); res = MP_NO; goto CLEANUP; } #endif #ifdef ECL_ENABLE_GFP_PT_MUL_AFF /* multiply base point by order - 1 and check for negative of base * point */ MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group)); if (ectestPrint) { printf(" (order-1)*P (jacobian):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth)); if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) { printf(" Error: invalid result (expected (- base point)).\n"); res = MP_NO; goto CLEANUP; } #endif /* multiply base point by order - 1 and check for negative of base * point */ MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry)); if (ectestPrint) { printf(" (order-1)*P (ECPoint_mul):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { printf(" Error: invalid result (expected (- base point)).\n"); res = MP_NO; goto CLEANUP; } /* multiply base point by order - 1 and check for negative of base * point */ MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry)); if (ectestPrint) { printf(" (order-1)*P (ECPoint_mul):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { printf(" Error: invalid result (expected (- base point)).\n"); res = MP_NO; goto CLEANUP; } #ifdef ECL_ENABLE_GFP_PT_MUL_AFF /* multiply base point by order and check for point at infinity */ MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry, group)); if (ectestPrint) { printf(" (order)*P (affine):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { printf(" Error: invalid result (expected point at infinity).\n"); res = MP_NO; goto CLEANUP; } #endif #ifdef ECL_ENABLE_GFP_PT_MUL_JAC /* multiply base point by order and check for point at infinity */ MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry, group)); if (ectestPrint) { printf(" (order)*P (jacobian):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { printf(" Error: invalid result (expected point at infinity).\n"); res = MP_NO; goto CLEANUP; } #endif /* multiply base point by order and check for point at infinity */ MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry)); if (ectestPrint) { printf(" (order)*P (ECPoint_mul):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { printf(" Error: invalid result (expected point at infinity).\n"); res = MP_NO; goto CLEANUP; } /* multiply base point by order and check for point at infinity */ MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry)); if (ectestPrint) { printf(" (order)*P (ECPoint_mul):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { printf(" Error: invalid result (expected point at infinity).\n"); res = MP_NO; goto CLEANUP; } /* check that (order-1)P + (order-1)P + P == (order-1)P */ MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry)); MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry)); if (ectestPrint) { printf(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n"); MP_CHECKOK(mp_toradix(&rx, s, 16)); printf(" %s\n", s); MP_CHECKOK(mp_toradix(&ry, s, 16)); printf(" %s\n", s); } MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { printf(" Error: invalid result (expected (- base point)).\n"); res = MP_NO; goto CLEANUP; } /* test validate_point function */ if (ECPoint_validate(group, &gx, &gy) != MP_YES) { printf(" Error: validate point on base point failed.\n"); res = MP_NO; goto CLEANUP; } MP_CHECKOK(mp_add_d(&gy, 1, &ry)); if (ECPoint_validate(group, &gx, &ry) != MP_NO) { printf(" Error: validate point on invalid point passed.\n"); res = MP_NO; goto CLEANUP; } if (ectestTime) { /* compute random scalar */ size = mpl_significant_bits(&group->meth->irr); if (size < MP_OKAY) { goto CLEANUP; } MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth)); /* timed test */ if (generic) { #ifdef ECL_ENABLE_GFP_PT_MUL_AFF M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry, group)), 100); #endif M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), 100); M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100); } else { M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), 100); M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)), 100); M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100); } } CLEANUP: mp_clear(&one); mp_clear(&order_1); mp_clear(&gx); mp_clear(&gy); mp_clear(&rx); mp_clear(&ry); mp_clear(&n); if (res != MP_OKAY) { printf(" Error: exiting with error value %i\n", res); } return res; }
/** Sign a message digest using a DH private key @param in The data to sign @param inlen The length of the input (octets) @param out [out] The destination of the signature @param outlen [in/out] The max size and resulting size of the output @param prng An active PRNG state @param wprng The index of the PRNG desired @param key A private DH key @return CRYPT_OK if successful */ int dh_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, dh_key *key) { mp_int a, b, k, m, g, p, p1, tmp; unsigned char *buf; unsigned long x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* check parameters */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } /* is the IDX valid ? */ if (is_valid_idx(key->idx) != 1) { return CRYPT_PK_INVALID_TYPE; } /* allocate ram for buf */ buf = XMALLOC(520); /* make up a random value k, * since the order of the group is prime * we need not check if gcd(k, r) is 1 */ if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) != (unsigned long)(sets[key->idx].size)) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } /* init bignums */ if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) { err = mpi_to_ltc_error(err); goto LBL_ERR; } /* load k and m */ if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; } if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY) { goto error; } /* load g, p and p1 */ if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; } if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; } if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY) { goto error; } if ((err = mp_div_2(&p1, &p1)) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */ /* now get a = g^k mod p */ if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY) { goto error; } /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */ if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */ if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = xa */ if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = M - xa */ if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY) { goto error; } /* b = (M - xa)/k */ /* check for overflow */ if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* store header */ y = PACKET_SIZE; /* now store them both (a,b) */ x = (unsigned long)mp_unsigned_bin_size(&a); STORE32L(x, out+y); y += 4; if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY) { goto error; } y += x; x = (unsigned long)mp_unsigned_bin_size(&b); STORE32L(x, out+y); y += 4; if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY) { goto error; } y += x; /* check if size too big */ if (*outlen < y) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* store header */ packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED); *outlen = y; err = CRYPT_OK; goto LBL_ERR; error: err = mpi_to_ltc_error(err); LBL_ERR: mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL); XFREE(buf); return err; }