Bool bignum_gcd1(BigNum b1, BigNum b2, BigNum *b0) { //---- 局所宣言 BigNum e; BigNum t; int a; bignum_init(&e, 1); //---- 計算処理 while ( 1 ) { if ( bignum_zero(b1) ) { bignum_mlt(b2, e, b0);return; } if ( bignum_zero(b2) ) { bignum_mlt(b1, e, b0);return; } if ( bignum_cmp(b1, b2) == 0 ) { bignum_mlt(b1, e, b0);return; } if ( b1.num[0]%2 == 0 && b2.num[0]%2 == 0 ) { bignum_div2(b1, 2, &t, &a); b1 = t; bignum_div2(b2, 2, &t, &a); b2 = t; bignum_scl(&e, 2); continue; } if ( b1.num[0]%2 == 0 ) { bignum_div2(b1, 2, &t, &a); b1 = t; continue; } if ( b2.num[0]%2 == 0 ) { bignum_div2(b2, 2, &t, &a); b2 = t; continue; } if ( bignum_cmp(b1, b2) == 1 ) { bignum_sub(b1, b2, &t); b1 = t; } else { bignum_sub(b2, b1, &t); b2 = t; } } //---- 返却処理 return TRUE; // 正常に処理完了 }
Bool bignum_near(BigNum b1, BigNum b2, int a) { //---- 局所宣言 BigNum t; //---- 計算処理 // |b1-b2|≦aの判定 if ( bignum_cmp(b1, b2) > 0 ) { t = b1; b1 = b2; b2 = t; } bignum_inc(&b1, a); //---- 返却処理 return ( bignum_cmp(b2, b1) <= 0 ); }
/* * DH stage 2-epsilon: given a number f, validate it to ensure it's in * range. (RFC 4253 section 8: "Values of 'e' or 'f' that are not in * the range [1, p-1] MUST NOT be sent or accepted by either side." * Also, we rule out 1 and p-1 too, since that's easy to do and since * they lead to obviously weak keys that even a passive eavesdropper * can figure out.) */ const char *dh_validate_f(void *handle, Bignum f) { struct dh_ctx *ctx = (struct dh_ctx *)handle; if (bignum_cmp(f, One) <= 0) { return "f value received is too small"; } else { Bignum pm1 = bigsub(ctx->p, One); int cmp = bignum_cmp(f, pm1); freebn(pm1); if (cmp >= 0) return "f value received is too large"; } return NULL; }
/* * DH stage 1: invent a number x between 1 and q, and compute e = * g^x mod p. Return e. * * If `nbits' is greater than zero, it is used as an upper limit * for the number of bits in x. This is safe provided that (a) you * use twice as many bits in x as the number of bits you expect to * use in your session key, and (b) the DH group is a safe prime * (which SSH demands that it must be). * * P. C. van Oorschot, M. J. Wiener * "On Diffie-Hellman Key Agreement with Short Exponents". * Advances in Cryptology: Proceedings of Eurocrypt '96 * Springer-Verlag, May 1996. */ Bignum dh_create_e(void *handle, int nbits) { struct dh_ctx *ctx = (struct dh_ctx *)handle; int i; int nbytes; unsigned char *buf; nbytes = ssh1_bignum_length(ctx->qmask); buf = snewn(nbytes, unsigned char); do { /* * Create a potential x, by ANDing a string of random bytes * with qmask. */ if (ctx->x) freebn(ctx->x); if (nbits == 0 || nbits > bignum_bitcount(ctx->qmask)) { ssh1_write_bignum(buf, ctx->qmask); for (i = 2; i < nbytes; i++) buf[i] &= random_byte(); ssh1_read_bignum(buf, nbytes, &ctx->x); /* can't fail */ } else { int b, nb; ctx->x = bn_power_2(nbits); b = nb = 0; for (i = 0; i < nbits; i++) { if (nb == 0) { nb = 8; b = random_byte(); } bignum_set_bit(ctx->x, i, b & 1); b >>= 1; nb--; } } } while (bignum_cmp(ctx->x, One) <= 0 || bignum_cmp(ctx->x, ctx->q) >= 0); sfree(buf); /* * Done. Now compute e = g^x mod p. */ ctx->e = modpow(ctx->g, ctx->x, ctx->p); return ctx->e; }
/* returns 1 if the modulus of k1 is < than the one of k2 */ static int modulus_smaller(ssh_public_key k1, ssh_public_key k2){ bignum n1; bignum n2; int res; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; sexp=gcry_sexp_find_token(k1->rsa_pub,"n",0); n1=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(k2->rsa_pub,"n",0); n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG); gcry_sexp_release(sexp); #elif defined HAVE_LIBCRYPTO n1=k1->rsa_pub->n; n2=k2->rsa_pub->n; #endif if(bignum_cmp(n1,n2)<0) res=1; else res=0; #ifdef HAVE_LIBGCRYPT bignum_free(n1); bignum_free(n2); #endif return res; }
int comb_sum_cmp(const void* comb1, const void* comb2) { bignum_t op1, op2; comb_fast_sum(&op1, (const byte*)comb1); comb_fast_sum(&op2, (const byte*)comb2); return bignum_cmp(&op1, &op2); }
Bool bignum_div1(BigNum b1, BigNum b2, int *a3, BigNum *b4) { //---- 局所宣言 BigNum t; // 一時変数 int k; // 反復変数 //---- 初期処理 *a3 = 0; // 整商の初期化 *b4 = b1; // 剰余の初期化 //---- 計算処理 // b1からb2を引けるだけ引く for ( k = 0; bignum_cmp(b1, b2) >= 0; k++ ) { bignum_sub(b1, b2, b4); b1 = *b4; (*a3)++; } // 引いた回数が整商で残った値が剰余 //---- 事後処理 if ( *a3 >= RAD ) { return FALSE; } // 桁溢れ //---- 返却処理 return TRUE; // 正常に処理完了 }
/* * Verify that the public data in an RSA key matches the private * data. We also check the private data itself: we ensure that p > * q and that iqmp really is the inverse of q mod p. */ bool RSAKey::Check() const { Bignum n, ed, pm1, qm1; int cmp; /* n must equal pq. */ n = bigmul(this->p, this->q); cmp = bignum_cmp(n, this->modulus); freebn(n); if (cmp != 0) return 0; /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */ pm1 = copybn(this->p); decbn(pm1); ed = modmul(this->exponent, this->private_exponent, pm1); cmp = bignum_cmp(ed, One); delete [] ed; if (cmp != 0) return 0; qm1 = copybn(this->q); decbn(qm1); ed = modmul(this->exponent, this->private_exponent, qm1); cmp = bignum_cmp(ed, One); delete [] ed; if (cmp != 0) return 0; /* * Ensure p > q. */ if (bignum_cmp(this->p, this->q) <= 0) return 0; /* * Ensure iqmp * q is congruent to 1, modulo p. */ n = modmul(this->iqmp, this->q, this->p); cmp = bignum_cmp(n, One); delete [] n; if (cmp != 0) return 0; return 1; }
/* * Verify that the public data in an RSA key matches the private * data. We also check the private data itself: we ensure that p > * q and that iqmp really is the inverse of q mod p. */ int rsa_verify(struct RSAKey *key) { Bignum n, ed, pm1, qm1; int cmp; /* n must equal pq. */ n = bigmul(key->p, key->q); cmp = bignum_cmp(n, key->modulus); freebn(n); if (cmp != 0) return 0; /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */ pm1 = copybn(key->p); decbn(pm1); ed = modmul(key->exponent, key->private_exponent, pm1); cmp = bignum_cmp(ed, One); sfree(ed); if (cmp != 0) return 0; qm1 = copybn(key->q); decbn(qm1); ed = modmul(key->exponent, key->private_exponent, qm1); cmp = bignum_cmp(ed, One); sfree(ed); if (cmp != 0) return 0; /* * Ensure p > q. */ if (bignum_cmp(key->p, key->q) <= 0) return 0; /* * Ensure iqmp * q is congruent to 1, modulo p. */ n = modmul(key->iqmp, key->q, key->p); cmp = bignum_cmp(n, One); sfree(n); if (cmp != 0) return 0; return 1; }
Bool bignum_div3(BigNum b1, BigNum b2, BigNum *b3, BigNum *b4) { //---- 局所宣言 BigNum low; // 下端 BigNum hig; // 上端 BigNum mid; // 中央 BigNum val; // 計算値(除数と仮整商の積) BigNum t; // 一時変数 int sft; // 上端の節数 int cmp; // 大小比較の結果 //---- 事前処理 // 除数の吟味(0除算の禁止) if ( bignum_zero(b2) == TRUE ) { return FALSE; } //---- 初期処理 bignum_init(&low, 0); // 下端の初期化(0) bignum_init(&hig, 1); // 上端の仮値(1) sft = b1.uni-b2.uni+1; // 上端の節数 bignum_shift(&hig, sft); // 上端の初期化(節移動) //---- 計算処理 //-- 整商の計算 while ( bignum_near(low, hig, 1) == 0 ) { // 上端と下端の中点として中央値をmidに格納 bignum_add(low, hig, &mid); bignum_half(&mid); // 中央値midとb2の乗算をvalに格納l if ( bignum_mlt(mid, b2, &val) == FALSE ) { return FALSE; } // b1とvalが等しければ脱出 cmp = bignum_cmp(val, b1); if ( cmp == 0 ) { low = mid; break; } // 異なれば上端または下端を更新 else if ( cmp > 0 ) { hig = mid; } else { low = mid; } } //-- 整商の格納と剰余の計算 // 下端値lowを整商*b3として格納 *b3 = low; // 整商*b3とb2の乗算をvalに格納l bignum_mlt(*b3, b2, &val); // b1とvalの差を剰余として*b4に格納 bignum_sub(b1, val, b4); //---- 事後処理 bignum_chk(b3); // 節数の更新 bignum_chk(b4); //---- 返却処理 return TRUE; // 正常に処理完了 }
int main (int argc, char ** argv) { if (argc != 2) { fprintf (stderr, "usage: %s <N>\n", argv[0]); return 1; } int N = atoi (argv[1]); if (N < 2) return 1; bignum_t * powers[(N - 1) * (N - 1)]; size_t powers_count = 0; bool * primes = eratosthenes_sieve (N + 1); for (int a = 2; a <= N; a++) { bignum_t * power = NULL; for (int b = 2; b <= N; b++) { bignum_t * new_power = NULL; if (!power) new_power = bignum_get (a * a); else new_power = bignum_mult (power, a); if (b == 2) bignum_delete (power); int duplicate_at = -1; // Powers of a prime base cannot be duplicates if (!primes[a]) for (size_t i = 0; i < powers_count; i++) if (bignum_cmp (powers[i], new_power) == 0) { duplicate_at = i; break; } if (duplicate_at == -1) { powers[powers_count++] = new_power; power = new_power; } else { bignum_delete (new_power); power = powers[duplicate_at]; } } } printf ("%d\n", (int) powers_count); bignum_free_array (powers, powers_count); free (primes); return 0; }
static void *dss_createkey(unsigned char *pub_blob, int pub_len, unsigned char *priv_blob, int priv_len) { dss_key *dss; char *pb = (char *) priv_blob; char *hash; int hashlen; SHA_State s; unsigned char digest[20]; Bignum ytest; dss = dss_newkey((char *) pub_blob, pub_len); if (!dss) return NULL; dss->x = getmp(&pb, &priv_len); if (!dss->x) { dss_freekey(dss); return NULL; } /* * Check the obsolete hash in the old DSS key format. */ hashlen = -1; getstring(&pb, &priv_len, &hash, &hashlen); if (hashlen == 20) { SHA_Init(&s); sha_mpint(&s, dss->p); sha_mpint(&s, dss->q); sha_mpint(&s, dss->g); SHA_Final(&s, digest); if (0 != memcmp(hash, digest, 20)) { dss_freekey(dss); return NULL; } } /* * Now ensure g^x mod p really is y. */ ytest = modpow(dss->g, dss->x, dss->p); if (0 != bignum_cmp(ytest, dss->y)) { dss_freekey(dss); freebn(ytest); return NULL; } freebn(ytest); return dss; }
static void *dss_newkey(char *data, int len) { char *p; int slen; dss_key *dss; dss = snewn(1,dss_key); getstring(&data, &len, &p, &slen); #ifdef DEBUG_DSS { int i; printf("key:"); for (i = 0; i < len; i++) printf(" %02x", (unsigned char) (data[i])); printf("\n"); } #endif if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) { sfree(dss); return NULL; } dss->p = getmp(&data, &len); dss->q = getmp(&data, &len); dss->g = getmp(&data, &len); dss->y = getmp(&data, &len); dss->x = NULL; if (!dss->p || !dss->q || !dss->g || !dss->y || !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) { /* Invalid key. */ dss_freekey(dss); return NULL; } return dss; }
int main (int argc, char ** argv) { if (argc != 2) { fprintf (stderr, "usage: %s <N>\n", argv[0]); return 1; } int N = atoi (argv[1]); if (N <= 0) return 1; /* * C_n,r = n!/r!(n - r)! * We need to check when C_n,r > LIMIT ~ n!/r! > LIMIT * (n - r)! * Precompute the right side of the inequality in factorials[] and the left side in cancelled_factorials[] * Given that C_n,r == C_n,n-r we only need to consider r <= n /2 */ bignum_t * factorials[N + 1]; factorials[0] = bignum_get (LIMIT); for (size_t i = 1; i < array_len (factorials); i++) factorials[i] = bignum_mult (factorials[i - 1], (int) i); int count = 0; for (int n = 1; n <= N; n++) { bignum_t * cancelled_factorials[n + 1]; cancelled_factorials[n] = bignum_get (1); for (int i = n - 1; i >= 0; i--) cancelled_factorials[i] = bignum_mult (cancelled_factorials[i + 1], i + 1); for (int r = 1; r <= n / 2 ; r++) if (bignum_cmp (cancelled_factorials[r], factorials[n - r]) > 0) { if (r + r == n) count++; else count += 2; } bignum_free_array (cancelled_factorials, array_len (cancelled_factorials)); } bignum_free_array (factorials, array_len (factorials)); printf ("%d\n", count); return 0; }
static void *dss_openssh_createkey(unsigned char **blob, int *len) { char **b = (char **) blob; struct dss_key *dss; dss = snew(struct dss_key); dss->p = getmp(b, len); dss->q = getmp(b, len); dss->g = getmp(b, len); dss->y = getmp(b, len); dss->x = getmp(b, len); if (!dss->p || !dss->q || !dss->g || !dss->y || !dss->x || !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) { /* Invalid key. */ dss_freekey(dss); return NULL; } return dss; }
int RSAKey::Generate( int bits ) { Bignum pm1, qm1, phi_n; /* * We don't generate e; we just use a standard one always. */ this->exponent = bignum_from_long(RSA_EXPONENT); /* * Generate p and q: primes with combined length `bits', not * congruent to 1 modulo e. (Strictly speaking, we wanted (p-1) * and e to be coprime, and (q-1) and e to be coprime, but in * general that's slightly more fiddly to arrange. By choosing * a prime e, we can simplify the criterion.) */ this->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL, 1); this->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL, 2); /* * Ensure p > q, by swapping them if not. */ if (bignum_cmp(this->p, this->q) < 0) swap( p, q ); /* * Now we have p, q and e. All we need to do now is work out * the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1), * and (q^-1 mod p). */ this->modulus = bigmul(this->p, this->q); pm1 = copybn(this->p); decbn(pm1); qm1 = copybn(this->q); decbn(qm1); phi_n = bigmul(pm1, qm1); freebn(pm1); freebn(qm1); this->private_exponent = modinv(this->exponent, phi_n); this->iqmp = modinv(this->q, this->p); /* * Clean up temporary numbers. */ freebn(phi_n); return 1; }
Bool bignum_sqrt(BigNum b1, BigNum *b0) { //---- 局所宣言 BigNum low; // 下端 BigNum hig; // 上端 BigNum mid; // 中央 BigNum val; // 二乗値 int sft; // 上端の節数 int cmp; // 大小比較の結果 //---- 初期処理 // lowを最下端0に初期化 bignum_init(&low, 0); // higを最上端に初期化 // 最上端は結果が含まれる範囲でキリの良い値 // 1で初期化し、適当な節だけ左シフト sft = (UNI-1)/2; bignum_init(&hig, 1); bignum_shift(&hig, sft); //---- 計算処理 while ( bignum_near(hig, low, 1) == FALSE ) { // 上端と下端の中点として中央値midの計算 bignum_add(low, hig, &mid); bignum_half(&mid); // 中央値midの二乗値val bignum_mlt(mid, mid, &val); // 二乗値valが入力値b1と等しければ脱出 cmp = bignum_cmp(val, b1); if ( cmp == 0 ) { break; }// 異なれば上端または下端を更新 else if ( cmp > 0 ) { hig = mid; } else { low = mid; } } //---- 事後処理 // 中央値midを結果b0に格納 *b0 = mid; // 節数と桁数の更新 bignum_chk(b0); //---- 返却処理 return TRUE; // 正常に処理完了 }
bool RSAKey::Verify( const CString &data, const CString &sig ) const { Bignum in, out; int bytes, i, j; unsigned char hash[20]; in = bignum_from_bytes( (const unsigned char *) sig.data(), sig.size() ); /* Base (in) must be smaller than the modulus. */ if( bignum_cmp(in, this->modulus) >= 0 ) { freebn(in); return false; } out = modpow(in, this->exponent, this->modulus); freebn(in); bool ret = true; bytes = (bignum_bitcount(this->modulus)+7) / 8; /* Top (partial) byte should be zero. */ if (bignum_byte(out, bytes - 1) != 0) ret = 0; /* First whole byte should be 1. */ if (bignum_byte(out, bytes - 2) != 1) ret = 0; /* Most of the rest should be FF. */ for (i = bytes - 3; i >= 20; i--) { if (bignum_byte(out, i) != 0xFF) ret = 0; } /* Finally, we expect to see the SHA-1 hash of the signed data. */ SHA_Simple( data.data(), data.size(), hash ); for (i = 19, j = 0; i >= 0; i--, j++) { if (bignum_byte(out, i) != hash[j]) ret = false; } freebn(out); return ret; }
Bool bignum_plrt(BigNum b1, int e, BigNum *b0) { //---- 局所宣言 BigNum low; // 下端 BigNum hig; // 上端 BigNum mid; // 中央 BigNum val; // 累乗値 int sft; // 上端の節数 int cmp; // 大小比較の結果 //---- 初期処理 bignum_init(&low, 0); bignum_init(&hig, 1); sft = (UNI-1)/e; bignum_shift(&hig, sft); //---- 計算処理 while ( bignum_near(low, hig, 1) == 0 ) { bignum_add(low, hig, &mid); bignum_half(&mid); bignum_pow(mid, e, &val); cmp = bignum_cmp(val, b1); if ( cmp == 0 ) { break; } else if ( cmp > 0 ) { hig = mid; } else { low = mid; } } //---- 事後処理 *b0 = mid; bignum_chk(b0); //---- 返却処理 return TRUE; // 正常に処理完了 }
static int dss_verifysig(void *key, char *sig, int siglen, char *data, int datalen) { struct dss_key *dss = (struct dss_key *) key; char *p; int slen; char hash[20]; Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v; int ret; if (!dss->p) return 0; #ifdef DEBUG_DSS { int i; printf("sig:"); for (i = 0; i < siglen; i++) printf(" %02x", (unsigned char) (sig[i])); printf("\n"); } #endif /* * Commercial SSH (2.0.13) and OpenSSH disagree over the format * of a DSA signature. OpenSSH is in line with the IETF drafts: * it uses a string "ssh-dss", followed by a 40-byte string * containing two 160-bit integers end-to-end. Commercial SSH * can't be bothered with the header bit, and considers a DSA * signature blob to be _just_ the 40-byte string containing * the two 160-bit integers. We tell them apart by measuring * the length: length 40 means the commercial-SSH bug, anything * else is assumed to be IETF-compliant. */ if (siglen != 40) { /* bug not present; read admin fields */ getstring(&sig, &siglen, &p, &slen); if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) { return 0; } sig += 4, siglen -= 4; /* skip yet another length field */ } r = get160(&sig, &siglen); s = get160(&sig, &siglen); if (!r || !s) return 0; /* * Step 1. w <- s^-1 mod q. */ w = modinv(s, dss->q); /* * Step 2. u1 <- SHA(message) * w mod q. */ SHA_Simple(data, datalen, (unsigned char *)hash); p = hash; slen = 20; sha = get160(&p, &slen); u1 = modmul(sha, w, dss->q); /* * Step 3. u2 <- r * w mod q. */ u2 = modmul(r, w, dss->q); /* * Step 4. v <- (g^u1 * y^u2 mod p) mod q. */ gu1p = modpow(dss->g, u1, dss->p); yu2p = modpow(dss->y, u2, dss->p); gu1yu2p = modmul(gu1p, yu2p, dss->p); v = modmul(gu1yu2p, One, dss->q); /* * Step 5. v should now be equal to r. */ ret = !bignum_cmp(v, r); freebn(w); freebn(sha); freebn(gu1p); freebn(yu2p); freebn(gu1yu2p); freebn(v); freebn(r); freebn(s); return ret; }
int rsa_generate(struct RSAKey *key, struct RSAAux *aux, int bits, progfn_t pfn, void *pfnparam) { Bignum pm1, qm1, phi_n; /* * Set up the phase limits for the progress report. We do this * by passing minus the phase number. * * For prime generation: our initial filter finds things * coprime to everything below 2^16. Computing the product of * (p-1)/p for all prime p below 2^16 gives about 20.33; so * among B-bit integers, one in every 20.33 will get through * the initial filter to be a candidate prime. * * Meanwhile, we are searching for primes in the region of 2^B; * since pi(x) ~ x/log(x), when x is in the region of 2^B, the * prime density will be d/dx pi(x) ~ 1/log(B), i.e. about * 1/0.6931B. So the chance of any given candidate being prime * is 20.33/0.6931B, which is roughly 29.34 divided by B. * * So now we have this probability P, we're looking at an * exponential distribution with parameter P: we will manage in * one attempt with probability P, in two with probability * P(1-P), in three with probability P(1-P)^2, etc. The * probability that we have still not managed to find a prime * after N attempts is (1-P)^N. * * We therefore inform the progress indicator of the number B * (29.34/B), so that it knows how much to increment by each * time. We do this in 16-bit fixed point, so 29.34 becomes * 0x1D.57C4. */ pfn(pfnparam, -1, -0x1D57C4/(bits/2)); pfn(pfnparam, -2, -0x1D57C4/(bits-bits/2)); pfn(pfnparam, -3, 5); /* * We don't generate e; we just use a standard one always. */ key->exponent = bignum_from_short(RSA_EXPONENT); /* * Generate p and q: primes with combined length `bits', not * congruent to 1 modulo e. (Strictly speaking, we wanted (p-1) * and e to be coprime, and (q-1) and e to be coprime, but in * general that's slightly more fiddly to arrange. By choosing * a prime e, we can simplify the criterion.) */ aux->p = primegen(bits/2, RSA_EXPONENT, 1, 1, pfn, pfnparam); aux->q = primegen(bits - bits/2, RSA_EXPONENT, 1, 2, pfn, pfnparam); /* * Ensure p > q, by swapping them if not. */ if (bignum_cmp(aux->p, aux->q) < 0) { Bignum t = aux->p; aux->p = aux->q; aux->q = t; } /* * Now we have p, q and e. All we need to do now is work out * the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1), * and (q^-1 mod p). */ pfn(pfnparam, 3, 1); key->modulus = bigmul(aux->p, aux->q); pfn(pfnparam, 3, 2); pm1 = copybn(aux->p); decbn(pm1); qm1 = copybn(aux->q); decbn(qm1); phi_n = bigmul(pm1, qm1); pfn(pfnparam, 3, 3); freebn(pm1); freebn(qm1); key->private_exponent = modinv(key->exponent, phi_n); pfn(pfnparam, 3, 4); aux->iqmp = modinv(aux->q, aux->p); pfn(pfnparam, 3, 5); /* * Clean up temporary numbers. */ freebn(phi_n); return 1; }
/* * This function is a wrapper on modpow(). It has the same effect * as modpow(), but employs RSA blinding to protect against timing * attacks. */ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key) { Bignum random, random_encrypted, random_inverse; Bignum input_blinded, ret_blinded; Bignum ret; SHA512_State ss; unsigned char digest512[64]; int digestused = lenof(digest512); int hashseq = 0; /* * Start by inventing a random number chosen uniformly from the * range 2..modulus-1. (We do this by preparing a random number * of the right length and retrying if it's greater than the * modulus, to prevent any potential Bleichenbacher-like * attacks making use of the uneven distribution within the * range that would arise from just reducing our number mod n. * There are timing implications to the potential retries, of * course, but all they tell you is the modulus, which you * already knew.) * * To preserve determinism and avoid Pageant needing to share * the random number pool, we actually generate this `random' * number by hashing stuff with the private key. */ while (1) { int bits, byte, bitsleft, v; random = copybn(key->modulus); /* * Find the topmost set bit. (This function will return its * index plus one.) Then we'll set all bits from that one * downwards randomly. */ bits = bignum_bitcount(random); byte = 0; bitsleft = 0; while (bits--) { if (bitsleft <= 0) { bitsleft = 8; /* * Conceptually the following few lines are equivalent to * byte = random_byte(); */ if (digestused >= lenof(digest512)) { unsigned char seqbuf[4]; PUT_32BIT(seqbuf, hashseq); pSHA512_Init(&ss); SHA512_Bytes(&ss, "RSA deterministic blinding", 26); SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf)); sha512_mpint(&ss, key->private_exponent); pSHA512_Final(&ss, digest512); hashseq++; /* * Now hash that digest plus the signature * input. */ pSHA512_Init(&ss); SHA512_Bytes(&ss, digest512, sizeof(digest512)); sha512_mpint(&ss, input); pSHA512_Final(&ss, digest512); digestused = 0; } byte = digest512[digestused++]; } v = byte & 1; byte >>= 1; bitsleft--; bignum_set_bit(random, bits, v); } /* * Now check that this number is strictly greater than * zero, and strictly less than modulus. */ if (bignum_cmp(random, Zero) <= 0 || bignum_cmp(random, key->modulus) >= 0) { freebn(random); continue; } else { break; } } /* * RSA blinding relies on the fact that (xy)^d mod n is equal * to (x^d mod n) * (y^d mod n) mod n. We invent a random pair * y and y^d; then we multiply x by y, raise to the power d mod * n as usual, and divide by y^d to recover x^d. Thus an * attacker can't correlate the timing of the modpow with the * input, because they don't know anything about the number * that was input to the actual modpow. * * The clever bit is that we don't have to do a huge modpow to * get y and y^d; we will use the number we just invented as * _y^d_, and use the _public_ exponent to compute (y^d)^e = y * from it, which is much faster to do. */ random_encrypted = modpow(random, key->exponent, key->modulus); random_inverse = modinv(random, key->modulus); input_blinded = modmul(input, random_encrypted, key->modulus); ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus); ret = modmul(ret_blinded, random_inverse, key->modulus); freebn(ret_blinded); freebn(input_blinded); freebn(random_inverse); freebn(random_encrypted); freebn(random); return ret; }
/** * crypto_rsa_exptmod - RSA modular exponentiation * @in: Input data * @inlen: Input data length * @out: Buffer for output data * @outlen: Maximum size of the output buffer and used size on success * @key: RSA key * @use_private: 1 = Use RSA private key, 0 = Use RSA public key * Returns: 0 on success, -1 on failure */ int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, struct crypto_rsa_key *key, int use_private) { struct bignum *tmp, *a = NULL, *b = NULL; int ret = -1; size_t modlen; if (use_private && !key->private_key) return -1; tmp = bignum_init(); if (tmp == NULL) return -1; if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) goto error; if (bignum_cmp(key->n, tmp) < 0) { /* Too large input value for the RSA key modulus */ goto error; } if (use_private) { /* * Decrypt (or sign) using Chinese remainer theorem to speed * up calculation. This is equivalent to tmp = tmp^d mod n * (which would require more CPU to calculate directly). * * dmp1 = (1/e) mod (p-1) * dmq1 = (1/e) mod (q-1) * iqmp = (1/q) mod p, where p > q * m1 = c^dmp1 mod p * m2 = c^dmq1 mod q * h = q^-1 (m1 - m2) mod p * m = m2 + hq */ a = bignum_init(); b = bignum_init(); if (a == NULL || b == NULL) goto error; /* a = tmp^dmp1 mod p */ if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) goto error; /* b = tmp^dmq1 mod q */ if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) goto error; /* tmp = (a - b) * (1/q mod p) (mod p) */ if (bignum_sub(a, b, tmp) < 0 || bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) goto error; /* tmp = b + q * tmp */ if (bignum_mul(tmp, key->q, tmp) < 0 || bignum_add(tmp, b, tmp) < 0) goto error; } else { /* Encrypt (or verify signature) */ /* tmp = tmp^e mod N */ if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) goto error; } modlen = crypto_rsa_get_modulus_len(key); if (modlen > *outlen) { *outlen = modlen; goto error; } if (bignum_get_unsigned_bin_len(tmp) > modlen) goto error; /* should never happen */ *outlen = modlen; os_memset(out, 0, modlen); if (bignum_get_unsigned_bin( tmp, out + (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) goto error; ret = 0; error: bignum_deinit(tmp); bignum_deinit(a); bignum_deinit(b); return ret; }
int dsa_generate(struct dss_key *key, int bits, progfn_t pfn, void *pfnparam) { Bignum qm1, power, g, h, tmp; unsigned pfirst, qfirst; int progress; /* * Set up the phase limits for the progress report. We do this * by passing minus the phase number. * * For prime generation: our initial filter finds things * coprime to everything below 2^16. Computing the product of * (p-1)/p for all prime p below 2^16 gives about 20.33; so * among B-bit integers, one in every 20.33 will get through * the initial filter to be a candidate prime. * * Meanwhile, we are searching for primes in the region of 2^B; * since pi(x) ~ x/log(x), when x is in the region of 2^B, the * prime density will be d/dx pi(x) ~ 1/log(B), i.e. about * 1/0.6931B. So the chance of any given candidate being prime * is 20.33/0.6931B, which is roughly 29.34 divided by B. * * So now we have this probability P, we're looking at an * exponential distribution with parameter P: we will manage in * one attempt with probability P, in two with probability * P(1-P), in three with probability P(1-P)^2, etc. The * probability that we have still not managed to find a prime * after N attempts is (1-P)^N. * * We therefore inform the progress indicator of the number B * (29.34/B), so that it knows how much to increment by each * time. We do this in 16-bit fixed point, so 29.34 becomes * 0x1D.57C4. */ pfn(pfnparam, PROGFN_PHASE_EXTENT, 1, 0x2800); pfn(pfnparam, PROGFN_EXP_PHASE, 1, -0x1D57C4 / 160); pfn(pfnparam, PROGFN_PHASE_EXTENT, 2, 0x40 * bits); pfn(pfnparam, PROGFN_EXP_PHASE, 2, -0x1D57C4 / bits); /* * In phase three we are finding an order-q element of the * multiplicative group of p, by finding an element whose order * is _divisible_ by q and raising it to the power of (p-1)/q. * _Most_ elements will have order divisible by q, since for a * start phi(p) of them will be primitive roots. So * realistically we don't need to set this much below 1 (64K). * Still, we'll set it to 1/2 (32K) to be on the safe side. */ pfn(pfnparam, PROGFN_PHASE_EXTENT, 3, 0x2000); pfn(pfnparam, PROGFN_EXP_PHASE, 3, -32768); /* * In phase four we are finding an element x between 1 and q-1 * (exclusive), by inventing 160 random bits and hoping they * come out to a plausible number; so assuming q is uniformly * distributed between 2^159 and 2^160, the chance of any given * attempt succeeding is somewhere between 0.5 and 1. Lacking * the energy to arrange to be able to specify this probability * _after_ generating q, we'll just set it to 0.75. */ pfn(pfnparam, PROGFN_PHASE_EXTENT, 4, 0x2000); pfn(pfnparam, PROGFN_EXP_PHASE, 4, -49152); pfn(pfnparam, PROGFN_READY, 0, 0); invent_firstbits(&pfirst, &qfirst); /* * Generate q: a prime of length 160. */ key->q = primegen(160, 2, 2, NULL, 1, pfn, pfnparam, qfirst); /* * Now generate p: a prime of length `bits', such that p-1 is * divisible by q. */ key->p = primegen(bits-160, 2, 2, key->q, 2, pfn, pfnparam, pfirst); /* * Next we need g. Raise 2 to the power (p-1)/q modulo p, and * if that comes out to one then try 3, then 4 and so on. As * soon as we hit a non-unit (and non-zero!) one, that'll do * for g. */ power = bigdiv(key->p, key->q); /* this is floor(p/q) == (p-1)/q */ h = bignum_from_long(1); progress = 0; while (1) { pfn(pfnparam, PROGFN_PROGRESS, 3, ++progress); g = modpow(h, power, key->p); if (bignum_cmp(g, One) > 0) break; /* got one */ tmp = h; h = bignum_add_long(h, 1); freebn(tmp); } key->g = g; freebn(h); /* * Now we're nearly done. All we need now is our private key x, * which should be a number between 1 and q-1 exclusive, and * our public key y = g^x mod p. */ qm1 = copybn(key->q); decbn(qm1); progress = 0; while (1) { int i, v, byte, bitsleft; Bignum x; pfn(pfnparam, PROGFN_PROGRESS, 4, ++progress); x = bn_power_2(159); byte = 0; bitsleft = 0; for (i = 0; i < 160; i++) { if (bitsleft <= 0) bitsleft = 8, byte = random_byte(); v = byte & 1; byte >>= 1; bitsleft--; bignum_set_bit(x, i, v); } if (bignum_cmp(x, One) <= 0 || bignum_cmp(x, qm1) >= 0) { freebn(x); continue; } else { key->x = x; break; } } freebn(qm1); key->y = modpow(key->g, key->x, key->p); return 1; }
/* * Generate a prime. We arrange to select a prime with the property * (prime % modulus) != residue (to speed up use in RSA). */ Bignum primegen(int bits, int modulus, int residue, int phase, progfn_t pfn, void *pfnparam) { int i, k, v, byte, bitsleft, check, checks; unsigned long delta, moduli[NPRIMES+1], residues[NPRIMES+1]; Bignum p, pm1, q, wqp, wqp2; int progress = 0; byte = 0; bitsleft = 0; STARTOVER: pfn(pfnparam, phase, ++progress); /* * Generate a k-bit random number with top and bottom bits set. */ p = newbn((bits+15)/16); for (i = 0; i < bits; i++) { if (i == 0 || i == bits-1) v = 1; else { if (bitsleft <= 0) bitsleft = 8; byte = random_byte(); v = byte & 1; byte >>= 1; bitsleft--; } bignum_set_bit(p, i, v); } /* * Ensure this random number is coprime to the first few * primes, by repeatedly adding 2 to it until it is. */ for (i = 0; i < NPRIMES; i++) { moduli[i] = primes[i]; residues[i] = bignum_mod_short(p, primes[i]); } moduli[NPRIMES] = modulus; residues[NPRIMES] = (bignum_mod_short(p, (unsigned short)modulus) + modulus - residue); delta = 0; while (1) { for (i = 0; i < (sizeof(moduli) / sizeof(*moduli)); i++) if (!((residues[i] + delta) % moduli[i])) break; if (i < (sizeof(moduli) / sizeof(*moduli))) {/* we broke */ delta += 2; if (delta < 2) { freebn(p); goto STARTOVER; } continue; } break; } q = p; p = bignum_add_long(q, delta); freebn(q); /* * Now apply the Miller-Rabin primality test a few times. First * work out how many checks are needed. */ checks = 27; if (bits >= 150) checks = 18; if (bits >= 200) checks = 15; if (bits >= 250) checks = 12; if (bits >= 300) checks = 9; if (bits >= 350) checks = 8; if (bits >= 400) checks = 7; if (bits >= 450) checks = 6; if (bits >= 550) checks = 5; if (bits >= 650) checks = 4; if (bits >= 850) checks = 3; if (bits >= 1300) checks = 2; /* * Next, write p-1 as q*2^k. */ for (k = 0; bignum_bit(p, k) == !k; k++); /* find first 1 bit in p-1 */ q = bignum_rshift(p, k); /* And store p-1 itself, which we'll need. */ pm1 = copybn(p); decbn(pm1); /* * Now, for each check ... */ for (check = 0; check < checks; check++) { Bignum w; /* * Invent a random number between 1 and p-1 inclusive. */ while (1) { w = newbn((bits+15)/16); for (i = 0; i < bits; i++) { if (bitsleft <= 0) bitsleft = 8; byte = random_byte(); v = byte & 1; byte >>= 1; bitsleft--; bignum_set_bit(w, i, v); } if (bignum_cmp(w, p) >= 0 || bignum_cmp(w, Zero) == 0) { freebn(w); continue; } break; } pfn(pfnparam, phase, ++progress); /* * Compute w^q mod p. */ wqp = modpow(w, q, p); freebn(w); /* * See if this is 1, or if it is -1, or if it becomes -1 * when squared at most k-1 times. */ if (bignum_cmp(wqp, One) == 0 || bignum_cmp(wqp, pm1) == 0) { freebn(wqp); continue; } for (i = 0; i < k-1; i++) { wqp2 = modmul(wqp, wqp, p); freebn(wqp); wqp = wqp2; if (bignum_cmp(wqp, pm1) == 0) break; } if (i < k-1) { freebn(wqp); continue; } /* * It didn't. Therefore, w is a witness for the * compositeness of p. */ freebn(p); freebn(pm1); freebn(q); goto STARTOVER; } /* * We have a prime! */ freebn(q); freebn(pm1); return p; }
Bignum *dss_gen_k(const char *id_string, Bignum modulus, Bignum private_key, unsigned char *digest, int digest_len) { /* * The basic DSS signing algorithm is: * * - invent a random k between 1 and q-1 (exclusive). * - Compute r = (g^k mod p) mod q. * - Compute s = k^-1 * (hash + x*r) mod q. * * This has the dangerous properties that: * * - if an attacker in possession of the public key _and_ the * signature (for example, the host you just authenticated * to) can guess your k, he can reverse the computation of s * and work out x = r^-1 * (s*k - hash) mod q. That is, he * can deduce the private half of your key, and masquerade * as you for as long as the key is still valid. * * - since r is a function purely of k and the public key, if * the attacker only has a _range of possibilities_ for k * it's easy for him to work through them all and check each * one against r; he'll never be unsure of whether he's got * the right one. * * - if you ever sign two different hashes with the same k, it * will be immediately obvious because the two signatures * will have the same r, and moreover an attacker in * possession of both signatures (and the public key of * course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q, * and from there deduce x as before. * * - the Bleichenbacher attack on DSA makes use of methods of * generating k which are significantly non-uniformly * distributed; in particular, generating a 160-bit random * number and reducing it mod q is right out. * * For this reason we must be pretty careful about how we * generate our k. Since this code runs on Windows, with no * particularly good system entropy sources, we can't trust our * RNG itself to produce properly unpredictable data. Hence, we * use a totally different scheme instead. * * What we do is to take a SHA-512 (_big_) hash of the private * key x, and then feed this into another SHA-512 hash that * also includes the message hash being signed. That is: * * proto_k = SHA512 ( SHA512(x) || SHA160(message) ) * * This number is 512 bits long, so reducing it mod q won't be * noticeably non-uniform. So * * k = proto_k mod q * * This has the interesting property that it's _deterministic_: * signing the same hash twice with the same key yields the * same signature. * * Despite this determinism, it's still not predictable to an * attacker, because in order to repeat the SHA-512 * construction that created it, the attacker would have to * know the private key value x - and by assumption he doesn't, * because if he knew that he wouldn't be attacking k! * * (This trick doesn't, _per se_, protect against reuse of k. * Reuse of k is left to chance; all it does is prevent * _excessively high_ chances of reuse of k due to entropy * problems.) * * Thanks to Colin Plumb for the general idea of using x to * ensure k is hard to guess, and to the Cambridge University * Computer Security Group for helping to argue out all the * fine details. */ SHA512_State ss; unsigned char digest512[64]; Bignum proto_k, k; /* * Hash some identifying text plus x. */ SHA512_Init(&ss); SHA512_Bytes(&ss, id_string, strlen(id_string) + 1); sha512_mpint(&ss, private_key); SHA512_Final(&ss, digest512); /* * Now hash that digest plus the message hash. */ SHA512_Init(&ss); SHA512_Bytes(&ss, digest512, sizeof(digest512)); SHA512_Bytes(&ss, digest, digest_len); while (1) { SHA512_State ss2 = ss; /* structure copy */ SHA512_Final(&ss2, digest512); smemclr(&ss2, sizeof(ss2)); /* * Now convert the result into a bignum, and reduce it mod q. */ proto_k = bignum_from_bytes(digest512, 64); k = bigmod(proto_k, modulus); freebn(proto_k); if (bignum_cmp(k, One) != 0 && bignum_cmp(k, Zero) != 0) { smemclr(&ss, sizeof(ss)); smemclr(digest512, sizeof(digest512)); return k; } /* Very unlikely we get here, but if so, k was unsuitable. */ freebn(k); /* Perturb the hash to think of a different k. */ SHA512_Bytes(&ss, "x", 1); /* Go round and try again. */ } }