// oaep.cpp - written and placed in the public domain by Wei Dai #include "pch.h" #include "oaep.h" #include NAMESPACE_BEGIN(CryptoPP) // ******************************************************** ANONYMOUS_NAMESPACE_BEGIN template struct PHashComputation { PHashComputation() {H().CalculateDigest(pHash, P, PLen);} byte pHash[H::DIGESTSIZE]; }; template const byte *PHash() { static PHashComputation pHash; return pHash.pHash; } NAMESPACE_END template unsigned int OAEP::MaxUnpaddedLength(unsigned int paddedLength) const { return paddedLength/8 > 1+2*H::DIGESTSIZE ? paddedLength/8-1-2*H::DIGESTSIZE : 0; } template void OAEP::Pad(RandomNumberGenerator &rng, const byte *input, unsigned int inputLength, byte *oaepBlock, unsigned int oaepBlockLen) const { assert (inputLength <= MaxUnpaddedLength(oaepBlockLen)); // convert from bit length to byte length if (oaepBlockLen % 8 != 0) { oaepBlock[0] = 0; oaepBlock++; } oaepBlockLen /= 8; const unsigned int hLen = H::DIGESTSIZE; const unsigned int seedLen = hLen, dbLen = oaepBlockLen-seedLen; byte *const maskedSeed = oaepBlock; byte *const maskedDB = oaepBlock+seedLen; // DB = pHash || 00 ... || 01 || M memcpy(maskedDB, PHash(), hLen); memset(maskedDB+hLen, 0, dbLen-hLen-inputLength-1); maskedDB[dbLen-inputLength-1] = 0x01; memcpy(maskedDB+dbLen-inputLength, input, inputLength); rng.GenerateBlock(maskedSeed, seedLen); MGF::GenerateAndMask(maskedDB, dbLen, maskedSeed, seedLen); MGF::GenerateAndMask(maskedSeed, seedLen, maskedDB, dbLen); } template DecodingResult OAEP::Unpad(const byte *oaepBlock, unsigned int oaepBlockLen, byte *output) const { bool invalid = false; // convert from bit length to byte length if (oaepBlockLen % 8 != 0) { invalid = (oaepBlock[0] != 0) || invalid; oaepBlock++; } oaepBlockLen /= 8; const unsigned int hLen = H::DIGESTSIZE; const unsigned int seedLen = hLen, dbLen = oaepBlockLen-seedLen; invalid = (oaepBlockLen < 2*hLen+1) || invalid; SecByteBlock t(oaepBlock, oaepBlockLen); byte *const maskedSeed = t; byte *const maskedDB = t+seedLen; MGF::GenerateAndMask(maskedSeed, seedLen, maskedDB, dbLen); MGF::GenerateAndMask(maskedDB, dbLen, maskedSeed, seedLen); // DB = pHash' || 00 ... || 01 || M byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01); invalid = (M == maskedDB+dbLen) || invalid; invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to(), 0)) != M) || invalid; invalid = (memcmp(maskedDB, PHash(), hLen) != 0) || invalid; if (invalid) return DecodingResult(); M++; memcpy(output, M, maskedDB+dbLen-M); return DecodingResult(maskedDB+dbLen-M); } NAMESPACE_END