/* * Perform an RSA public key operation */ int rsa_public( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ) { int ret; mpi T; // if( ilen != ctx->len || olen != ctx->len ) // return( ERR_RSA_BAD_INPUT_DATA ); mpi_init( &T, NULL ); CHK( mpi_import( &T, input, ilen ) ); if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { mpi_free( &T, NULL ); return( ERR_RSA_BAD_INPUT_DATA ); } CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); CHK( mpi_export( &T, output, olen ) ); cleanup: mpi_free( &T, NULL ); if( ret != 0 ) return( ERR_RSA_PUBLIC_FAILED | ret ); return( 0 ); }
/* * Perform an RSA private key operation */ int rsa_private( rsa_context *ctx, unsigned char *input, int ilen, unsigned char *output, int *olen ) { int ret; mpi T, T1, T2; //if( ilen != ctx->len || olen != ctx->len ) // return( ERR_RSA_BAD_INPUT_DATA ); mpi_init( &T, &T1, &T2, NULL ); CHK( mpi_import( &T, input, ilen ) ); if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { mpi_free( &T, NULL ); return( ERR_RSA_BAD_INPUT_DATA ); } #if 0 CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else /* * faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); /* * output = T2 + T * Q */ CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); CHK( mpi_add_mpi( &T, &T2, &T1 ) ); #endif CHK( mpi_export( &T, output, olen ) ); cleanup: mpi_free( &T, &T1, &T2, NULL ); if( ret != 0 ) return( ERR_RSA_PRIVATE_FAILED | ret ); return( 0 ); }
void FSPRG_Evolve(void *state) { gcry_mpi_t n, x; uint16_t secpar; uint64_t epoch; initialize_libgcrypt(); secpar = read_secpar(state + 0); n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8); x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8); epoch = uint64_import(state + 2 + 2 * secpar / 8, 8); gcry_mpi_mulm(x, x, x, n); epoch++; mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); gcry_mpi_release(n); gcry_mpi_release(x); }
/* deterministically generate from seed/idx a quadratic residue (mod n) */ static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen, uint32_t idx, unsigned secpar) { size_t buflen = secpar / 8; uint8_t buf[buflen]; gcry_mpi_t x; det_randomize(buf, buflen, seed, seedlen, idx); buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */ x = mpi_import(buf, buflen); assert(gcry_mpi_cmp(x, n) < 0); gcry_mpi_mulm(x, x, x, n); return x; }
void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm; uint16_t secpar; initialize_libgcrypt(); secpar = read_secpar(msk + 0); p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8); q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8); n = gcry_mpi_new(0); gcry_mpi_mul(n, p, q); x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */ kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */ kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */ gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */ store_secpar(state + 0, secpar); mpi_export(state + 2 + 0 * secpar / 8, secpar / 8, n); mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm); uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); gcry_mpi_release(p); gcry_mpi_release(q); gcry_mpi_release(n); gcry_mpi_release(x); gcry_mpi_release(xp); gcry_mpi_release(xq); gcry_mpi_release(kp); gcry_mpi_release(kq); gcry_mpi_release(xm); }
static int asn1_get_mpi( unsigned char **p, unsigned char *end, mpi *X ) { int ret, len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) return( ret ); ret = mpi_import( X, *p, len ); *p += len; return( ret ); }
void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) { gcry_mpi_t n, x; uint16_t secpar; initialize_libgcrypt(); secpar = read_secpar(mpk + 0); n = mpi_import(mpk + 2, secpar / 8); x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); memcpy(state, mpk, 2 + secpar / 8); mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); memset(state + 2 + 2 * secpar / 8, 0, 8); gcry_mpi_release(n); gcry_mpi_release(x); }
/* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */ static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint32_t idx) { size_t buflen = bits / 8; uint8_t buf[buflen]; gcry_mpi_t p; assert(bits % 8 == 0); assert(buflen > 0); det_randomize(buf, buflen, seed, seedlen, idx); buf[0] |= 0xc0; /* set upper two bits, so that n=pq has maximum size */ buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */ p = mpi_import(buf, buflen); while (gcry_prime_check(p, 0)) gcry_mpi_add_ui(p, p, 4); return p; }