/* * 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; }
static void pdf_compute_hardened_hash_r6(unsigned char *password, int pwlen, unsigned char salt[16], unsigned char *ownerkey, unsigned char hash[32]) { unsigned char data[(128 + 64 + 48) * 64]; unsigned char block[64]; int block_size = 32; int data_len = 0; int i, j, sum; SHA256_CTX sha256; SHA384_CTX sha384; SHA512_CTX sha512; aes_context aes; pSHA256_Init(&sha256); pSHA256_Update(&sha256, password, pwlen); pSHA256_Update(&sha256, salt, 8); if (ownerkey) pSHA256_Update(&sha256, ownerkey, 48); pSHA256_Final((uint8_t *)block, &sha256); for (i = 0; i < 64 || i < data[data_len * 64 - 1] + 32; i++) { /* Step 2: repeat password and data block 64 times */ memcpy(data, password, pwlen); memcpy(data + pwlen, block, block_size); if (ownerkey) memcpy(data + pwlen + block_size, ownerkey, 48); data_len = pwlen + block_size + (ownerkey ? 48 : 0); for (j = 1; j < 64; j++) memcpy(data + j * data_len, data, data_len); /* Step 3: encrypt data using data block as key and iv */ aes_setkey_enc(&aes, block, 128); aes_crypt_cbc(&aes, AES_ENCRYPT, data_len * 64, block + 16, data, data); /* Step 4: determine SHA-2 hash size for this round */ for (j = 0, sum = 0; j < 16; j++) sum += data[j]; /* Step 5: calculate data block for next round */ block_size = 32 + (sum % 3) * 16; switch (block_size) { case 32: pSHA256_Init(&sha256); pSHA256_Update(&sha256, data, data_len * 64); pSHA256_Final((uint8_t *)block, &sha256); break; case 48: pSHA384_Init(&sha384); pSHA384_Update(&sha384, data, data_len * 64); pSHA384_Final((uint8_t *)block, &sha384); break; case 64: pSHA512_Init(&sha512); pSHA512_Update(&sha512, data, data_len * 64); pSHA512_Final((uint8_t *)block, &sha512); break; } } memset(data, 0, sizeof(data)); memcpy(hash, block, 32); }