void loadRSAPriKey(RSA::PrivateKey& key, const char* filename){ ByteQueue byte; FileSource file(filename, true, new Base64Decoder); file.TransferTo(byte); byte.MessageEnd(); key.Load(byte); }
// EGPublicKey::Dump // Streaming method. Outputs key to specfied stream. Outputs key length followed // by each factor of the key. void EGPublicKey::Dump(std::ostream& os) const { // Output KeyLen followed by P, G, and Y try { ByteQueue aQueue; aQueue.Put(mKey, mKeyLen); aQueue.Close(); Integer p, q, g, y; BERSequenceDecoder aDecoder(aQueue); p.BERDecode(aDecoder); q.BERDecode(aDecoder); g.BERDecode(aDecoder); y.BERDecode(aDecoder); os << "(Len=" << mKeyLen << " P=" << p << " Q=" << q << " G=" << g << " Y=" << y << ')'; } catch (Exception& anEx) { WDBG_AH("EGPublicKey::Dump Caught CryptoLib exception: " << anEx.what()); os << "(EGPublicKey Exception: " << anEx.what() << ')'; } }
void ByteQueue::pop(ByteQueue& data) { uint32_t total = data.size() <= buf.size() ? data.size() : buf.size(); if (!total) return; memcpy(data.ptr(), (const void*)&buf[0], total); buf.erase(buf.begin(), buf.begin() + total); data.resize(total); }
QByteArray CppGetByteArray(const CryptoMaterial &cm) { ByteQueue queue; cm.Save(queue); QByteArray data(queue.CurrentSize(), 0); queue.Get(reinterpret_cast<byte *>(data.data()), data.size()); return data; }
void initRSA() { string pubkey = base64_decode(string(serverPublicKey)); ByteQueue tmp; for (int i = 0; i < pubkey.size(); i++) tmp.Put((byte)pubkey[i]); serverPub = new RSA::PublicKey; serverPub->Load(tmp); encryptor = new RSAES_OAEP_SHA_Encryptor(*serverPub); }
static bool DecodeFromFile(const char* filename, RSA::PrivateKey& key) { try { ByteQueue queue; FileSource file(filename, true); file.TransferTo(queue); queue.MessageEnd(); key.BERDecodePrivateKey(queue, false, queue.MaxRetrievable()); return key.Validate(rng, 3); } catch (...) { return false; } }
void CAuthenticationProfileImpl::sendPublicKey(RSA::PublicKey publicKey) { LOG4CPLUS_TRACE_METHOD(msLogger, __PRETTY_FUNCTION__ ); ByteQueue queue; publicKey.Save(queue); UInt32 queueSize = queue.CurrentSize(); UInt8* outgoingData = new UInt8[queueSize + 1]; outgoingData[0] = static_cast<UInt8>(SEND_PUBLIC_KEY); queue.Get(outgoingData + 1, queueSize); LOG4CPLUS_INFO(msLogger, "***** " + convertIntegerToString(queueSize + 1) + " bytes sent"); iviLink::Channel::sendBuffer(mChannelID, outgoingData, queueSize + 1); delete[] outgoingData; }
// EGPublicKey::AllocateSig // Allocates the mSigP member if needed. Feeds binary rep of key into the // ElGamalVerifier class from Crypto++. void EGPublicKey::AllocateSig() const { WTRACE("EGPublicKey::AllocateSig"); if (! mSigP) { WDBG_LL("EGPublicKey::AllocateSig Allocating crypt object."); ByteQueue aQueue; aQueue.Put(mKey, mKeyLen); aQueue.Close(); mSigP = new ElGamalVerifier(aQueue); } }
void PEM_StripEncapsulatedBoundary(BufferedTransformation& bt, const SecByteBlock& pre, const SecByteBlock& post) { ByteQueue temp; SecByteBlock::const_iterator it; int n = 1, prePos = -1, postPos = -1; while(bt.AnyRetrievable() && n++) { SecByteBlock line, unused; PEM_ReadLine(bt, line, unused); // The write associated with an empty line must to occur. Otherwise, we loose the CR or LF // in an ecrypted private key between the control fields and the encapsulated text. //if(line.empty()) // continue; it = Search(line, pre); if(it != line.end()) { prePos = n; continue; } it = Search(line, post); if(it != line.end()) { postPos = n; continue; } PEM_WriteLine(temp, line); } if(prePos == -1) { string msg = "PEM_StripEncapsulatedBoundary: '"; msg += string((char*)pre.data(), pre.size()) + "' not found"; throw InvalidDataFormat(msg); } if(postPos == -1) { string msg = "PEM_StripEncapsulatedBoundary: '"; msg += string((char*)post.data(), post.size()) + "' not found"; throw InvalidDataFormat(msg); } if(prePos > postPos) throw InvalidDataFormat("PEM_StripEncapsulatedBoundary: header boundary follows footer boundary"); temp.TransferTo(bt); }
void PutDecodedDatumInto(const TestData &data, const char *name, BufferedTransformation &target) { std::string s1 = GetRequiredDatum(data, name), s2; ByteQueue q; while (!s1.empty()) { while (s1[0] == ' ') { s1 = s1.substr(1); if (s1.empty()) goto end; // avoid invalid read if s1 is empty } int repeat = 1; if (s1[0] == 'r') { repeat = atoi(s1.c_str()+1); s1 = s1.substr(s1.find(' ')+1); } s2 = ""; // MSVC 6 doesn't have clear(); if (s1[0] == '\"') { s2 = s1.substr(1, s1.find('\"', 1)-1); s1 = s1.substr(s2.length() + 2); } else if (s1.substr(0, 2) == "0x") { StringSource(s1.substr(2, s1.find(' ')), true, new HexDecoder(new StringSink(s2))); s1 = s1.substr(STDMIN(s1.find(' '), s1.length())); } else { StringSource(s1.substr(0, s1.find(' ')), true, new HexDecoder(new StringSink(s2))); s1 = s1.substr(STDMIN(s1.find(' '), s1.length())); } while (repeat--) { q.Put((const byte *)s2.data(), s2.size()); RandomizedTransfer(q, target, false); } } end: RandomizedTransfer(q, target, true); }
void UDPSocket::send(const Address& address, const ByteQueue& data) { #ifdef _WIN32 SOCKADDR_IN servaddr; memset((void*)&servaddr, 0, sizeof(SOCKADDR_IN)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = address.ip; servaddr.sin_port = address.port; sendto(sd, (const char*)data.ptr(), data.size(), 0, (SOCKADDR*)&servaddr, sizeof(SOCKADDR_IN)); #else sockaddr_in servaddr; memset(&servaddr, 0, sizeof(sockaddr_in)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = address.ip; servaddr.sin_port = address.port; sendto(sd, data.ptr(), data.size(), 0, (const sockaddr*)&servaddr, sizeof(sockaddr_in)); #endif }
// EGPublicKey::Encrypt // Encrypts a block of data of the specified length using ElGamal encryption for this // key. Returns allocated block/len of encrypted data. EGPublicKey::CryptReturn EGPublicKey::Encrypt(const void* theMsgP, unsigned long theLen) const { WTRACE("EGPublicKey::Encrypt"); // Sanity check if ((! theMsgP) || (theLen == 0)) { WDBG_LM("EGPublicKey::Encrypt No data to encrypt"); return CryptReturn(NULL,0); } try { // Allocate crypt object if needed AllocateCrypt(); // Encrypt the data ByteQueue aQueue; EncryptData(aQueue, reinterpret_cast<const unsigned char*>(theMsgP), theLen); // Build return WDBG_LL("EGPublicKey::Encrypt Building return values."); unsigned long anOutLen = aQueue.MaxRetrieveable(); if (anOutLen == 0) { WDBG_LM("EGPublicKey::Encrypt Encrypt failed, no data."); return CryptReturn(NULL, 0); } auto_ptr<unsigned char> anOutP(new unsigned char [anOutLen]); aQueue.Get(anOutP.get(), anOutLen); WDBG_LM("EGPublicKey::Encrypt Encrypted, out block len=" << anOutLen); return CryptReturn(anOutP.release(), anOutLen); } catch (Exception& anEx) { // Little trick here, construct a CryptException to auto log the failure! WDBG_AH("EGPublicKey::Encrypt Caught CryptoLib exception: " << anEx.what()); #ifndef _WONCRYPT_NOEXCEPTIONS WONCrypt::CryptException aLog(WONCommon::ExCryptoLib, __LINE__, __FILE__, anEx.what()); #endif return CryptReturn(NULL,0); } }
ByteQueue UDPSocket::recv(Address& address) { ByteQueue data; #ifdef _WIN32 fd_set fds; timeval timeout; FD_ZERO(&fds); FD_SET(sd, &fds); timeout.tv_sec = 0; timeout.tv_usec = 0; if (select(0, &fds, nullptr, nullptr, &timeout) > 0) { SOCKADDR_IN addr; int addrsize = sizeof(SOCKADDR_IN); data.resize(maxlen); data.resize(uint32_t(recvfrom(SOCKET(sd), (char*)data.ptr(), maxlen, 0, (SOCKADDR*)&addr, &addrsize))); address = Address(addr.sin_addr.S_un.S_addr, addr.sin_port); } #else fd_set fds; timeval timeout; FD_ZERO(&fds); FD_SET(sd, &fds); timeout.tv_sec = 0; timeout.tv_usec = 0; if (select(sd + 1, &fds, nullptr, nullptr, &timeout) > 0) { sockaddr_in addr; socklen_t addrsize = sizeof(sockaddr_in); data.resize(maxlen); data.resize(uint32_t(recvfrom(sd, data.ptr(), maxlen, 0, (sockaddr*)&addr, &addrsize))); address = Address(addr.sin_addr.s_addr, addr.sin_port); } #endif return data; }
// EGPublicKey::CopyFromPrivateKey // Copies public key from a private key. Existing key (if any) is replaced. This // method takes the binary rep of the private key and drops the private portion // to generate the public key. void EGPublicKey::CopyFromPrivateKey(const EGPrivateKey& theKeyR) { ClearLocal(); try { ByteQueue aPrivQueue; aPrivQueue.Put(theKeyR.GetKey(), theKeyR.GetKeyLen()); aPrivQueue.Close(); ElGamalVerifier aKey(aPrivQueue); ByteQueue aPubQueue; aKey.DEREncode(aPubQueue); aPubQueue.Close(); AllocKeyBuf(aPubQueue.MaxRetrieveable()); aPubQueue.Get(mKey, mKeyLen); } catch (Exception& anEx) { WDBG_AH("EGPublicKey::CopyFromPrivateKey Caught CryptoLib exception: " << anEx.what()); #ifndef _WONCRYPT_NOEXCEPTIONS throw WONCrypt::CryptException(WONCommon::ExCryptoLib, __LINE__, __FILE__, anEx.what()); #else Invalidate(); #endif } }
extern "C" int rsa_pss_sign(const char *key_file, const unsigned char *msg, int len, unsigned char *sig_buf, unsigned char *modulus_buf) { try { AutoSeededRandomPool rng; FileSource file(key_file, true); RSA::PrivateKey key; ByteQueue bq; // Load the key file.TransferTo(bq); bq.MessageEnd(); key.BERDecodePrivateKey(bq, false, bq.MaxRetrievable()); // Write the modulus Integer mod = key.GetModulus(); // error check if (mod.ByteCount() != RCM_RSA_MODULUS_SIZE) throw std::length_error("incorrect rsa key modulus length"); for (int i = 0; i < mod.ByteCount(); i++) modulus_buf[i] = mod.GetByte(i); // Sign the message RSASS<PSS, SHA256>::Signer signer(key); size_t length = signer.MaxSignatureLength(); SecByteBlock signature(length); length = signer.SignMessage(rng, msg, len, signature); // Copy in reverse order for (int i = 0; i < length; i++) sig_buf[length - i - 1] = signature[i]; } catch(const CryptoPP::Exception& e) { cerr << e.what() << endl; return 1; } catch(std::length_error& le) { cerr << "Error: " << le.what() << endl; return 1; } return 0; }
void PutDecodedDatumInto(const TestData &data, const char *name, BufferedTransformation &target) { std::string s1 = GetRequiredDatum(data, name), s2; while (!s1.empty()) { while (s1[0] == ' ') s1 = s1.substr(1); int repeat = 1; if (s1[0] == 'r') { repeat = atoi(s1.c_str()+1); s1 = s1.substr(s1.find(' ')+1); } s2 = ""; // MSVC 6 doesn't have clear(); if (s1[0] == '\"') { s2 = s1.substr(1, s1.find('\"', 1)-1); s1 = s1.substr(s2.length() + 2); } else if (s1.substr(0, 2) == "0x") { StringSource(s1.substr(2, s1.find(' ')), true, new HexDecoder(new StringSink(s2))); s1 = s1.substr(STDMIN(s1.find(' '), s1.length())); } else { StringSource(s1.substr(0, s1.find(' ')), true, new HexDecoder(new StringSink(s2))); s1 = s1.substr(STDMIN(s1.find(' '), s1.length())); } ByteQueue q; while (repeat--) { q.Put((const byte *)s2.data(), s2.size()); if (q.MaxRetrievable() > 4*1024 || repeat == 0) q.TransferTo(target); } } }
extern "C" int rsa_pss_sign_file(const char *key_file, const char *msg_file, unsigned char *sig_buf) { try { AutoSeededRandomPool rng; FileSource file(key_file, true); RSA::PrivateKey key; ByteQueue bq; // Load the key file.TransferTo(bq); bq.MessageEnd(); key.BERDecodePrivateKey(bq, false, bq.MaxRetrievable()); // Sign the message RSASS<PSS, SHA256>::Signer signer(key); string signature; FileSource src(msg_file, true, new SignerFilter(rng, signer, new StringSink(signature))); int length = signature.length(); // error check if (length != RCM_RSA_SIG_SIZE) throw std::length_error("incorrect rsa key length"); // Copy in reverse order for (int i = 0; i < length; i++) sig_buf[length - i - 1] = signature[i]; } catch(const CryptoPP::Exception& e) { cerr << e.what() << endl; return 1; } catch(std::length_error& le) { cerr << "Error: " << le.what() << endl; return 1; } return 0; }
bool ByteQueue::operator==(const ByteQueue &rhs) const { const unsigned long currentSize = CurrentSize(); if (currentSize != rhs.CurrentSize()) return false; for (unsigned long i = 0; i<currentSize; i++) if ((*this)[i] != rhs[i]) return false; return true; }
// EGPublicKey::AllocateCrypt // Allocates the mCryptP member if needed. Manually decodes binary rep into factors // and feeds appropriate factor to the ElGamalEncryptor class from Crypto++. void EGPublicKey::AllocateCrypt() const { WTRACE("EGPublicKey::AllocateCrypt"); if (! mCryptP) { WDBG_LL("EGPublicKey::AllocateCrypt Allocating crypt object."); ByteQueue aQueue; aQueue.Put(mKey, mKeyLen); aQueue.Close(); // *HACK* // Manually build the ElGamalEncryptor object. See notes at // top of this file. Integer p, q, g, y; BERSequenceDecoder seq(aQueue); p.BERDecode(seq); q.BERDecode(seq); g.BERDecode(seq); y.BERDecode(seq); mCryptP = new ElGamalEncryptor(p, g, y); } }
CppRsaPublicKeyImpl::CppRsaPublicKeyImpl(const QByteArray &data, bool seed) : m_public_key(new RSA::PublicKey()) { if(seed) { RSA::PrivateKey key; CryptoRandom rand(data); key.GenerateRandomWithKeySize(GetCppRandom(rand), RsaPrivateKey::DefaultKeySize()); m_public_key.reset(new RSA::PublicKey(key)); } else { ByteQueue queue; queue.Put2(reinterpret_cast<const byte *>(data.data()), data.size(), 0, true); try { m_public_key->Load(queue); } catch (std::exception &e) { qWarning() << "In CppRsaPublicKey: " << e.what(); m_valid = false; return; } } m_valid = true; }
bool ByteQueue::operator==(const ByteQueue &rhs) const { const lword currentSize = CurrentSize(); if (currentSize != rhs.CurrentSize()) return false; Walker walker1(*this), walker2(rhs); byte b1, b2; while (walker1.Get(b1) && walker2.Get(b2)) if (b1 != b2) return false; return true; }
bool ValidateRSA() { cout << "\nRSA validation suite running...\n\n"; byte out[100], outPlain[100]; bool pass = true, fail; { static const char plain[] = "Everyone gets Friday off."; byte *signature = (byte *) "\x05\xfa\x6a\x81\x2f\xc7\xdf\x8b\xf4\xf2\x54\x25\x09\xe0\x3e\x84" "\x6e\x11\xb9\xc6\x20\xbe\x20\x09\xef\xb4\x40\xef\xbc\xc6\x69\x21" "\x69\x94\xac\x04\xf3\x41\xb5\x7d\x05\x20\x2d\x42\x8f\xb2\xa2\x7b" "\x5c\x77\xdf\xd9\xb1\x5b\xfc\x3d\x55\x93\x53\x50\x34\x10\xc1\xe1"; FileSource keys("TestData/rsa512a.dat", true, new HexDecoder); Weak::RSASSA_PKCS1v15_MD2_Signer rsaPriv(keys); Weak::RSASSA_PKCS1v15_MD2_Verifier rsaPub(rsaPriv); size_t signatureLength = rsaPriv.SignMessage(GlobalRNG(), (byte *)plain, strlen(plain), out); fail = !VerifyBufsEqual(signature, out, 64); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "signature check against test vector\n"; fail = !rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "verification check against test vector\n"; out[10]++; fail = rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "invalid signature verification\n"; } { FileSource keys("TestData/rsa1024.dat", true, new HexDecoder); RSAES_PKCS1v15_Decryptor rsaPriv(keys); RSAES_PKCS1v15_Encryptor rsaPub(rsaPriv); pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass; } { RSAES<OAEP<SHA> >::Decryptor rsaPriv(GlobalRNG(), 512); RSAES<OAEP<SHA> >::Encryptor rsaPub(rsaPriv); pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass; } { byte *plain = (byte *) "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; byte *encrypted = (byte *) "\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a" "\x8b\x40\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4" "\x17\x53\x03\x29\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52" "\x62\x51"; byte *oaepSeed = (byte *) "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2" "\xf0\x6c\xb5\x8f"; ByteQueue bq; bq.Put(oaepSeed, 20); FixedRNG rng(bq); FileSource privFile("TestData/rsa400pv.dat", true, new HexDecoder); FileSource pubFile("TestData/rsa400pb.dat", true, new HexDecoder); RSAES_OAEP_SHA_Decryptor rsaPriv; rsaPriv.AccessKey().BERDecodePrivateKey(privFile, false, 0); RSAES_OAEP_SHA_Encryptor rsaPub(pubFile); memset(out, 0, 50); memset(outPlain, 0, 8); rsaPub.Encrypt(rng, plain, 8, out); DecodingResult result = rsaPriv.FixedLengthDecrypt(GlobalRNG(), encrypted, outPlain); fail = !result.isValidCoding || (result.messageLength!=8) || !VerifyBufsEqual(out, encrypted, 50) || !VerifyBufsEqual(plain, outPlain, 8); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "PKCS 2.0 encryption and decryption\n"; } return pass; }
size_t PEM_ReadLine(BufferedTransformation& source, SecByteBlock& line, SecByteBlock& ending) { if(!source.AnyRetrievable()) { line.New(0); ending.New(0); return 0; } ByteQueue temp; while(source.AnyRetrievable()) { byte b; if(!source.Get(b)) throw Exception(Exception::OTHER_ERROR, "PEM_ReadLine: failed to read byte"); // LF ? if(b == '\n') { ending = LF; break; } // CR ? if(b == '\r') { // CRLF ? if(source.AnyRetrievable() && source.Peek(b)) { if(b == '\n') { source.Skip(1); ending = CRLF; break; } } ending = CR; break; } // Not End-of-Line, accumulate it. temp.Put(b); } if(temp.AnyRetrievable()) { line.Grow(temp.MaxRetrievable()); temp.Get(line.data(), line.size()); } else { line.New(0); ending.New(0); } // We return a line stripped of CRs and LFs. However, we return the actual number of // of bytes processed, including the CR and LF. A return of 0 means nothing was read. // A return of 1 means an empty line was read (CR or LF). A return of 2 could // mean an empty line was read (CRLF), or could mean 1 character was read. In // any case, line will hold whatever was parsed. return line.size() + ending.size(); }
void PEM_NextObject(BufferedTransformation& src, BufferedTransformation& dest, bool trimTrailing) { if(!src.AnyRetrievable()) return; // We have four things to find: // 1. -----BEGIN (the leading begin) // 2. ----- (the trailing dashes) // 3. -----END (the leading end) // 4. ----- (the trailing dashes) // Once we parse something that purports to be PEM encoded, another routine // will have to look for something particular, like a RSA key. We *will* // inadvertently parse garbage, like -----BEGIN FOO BAR-----. It will // be caught later when a PEM_Load routine is called. static const size_t BAD_IDX = PEM_INVALID; // We use iterators for the search. However, an interator is invalidated // after each insert that grows the container. So we save indexes // from begin() to speed up searching. On each iteration, we simply // reinitialize them. SecByteBlock::const_iterator it; size_t idx1 = BAD_IDX, idx2 = BAD_IDX, idx3 = BAD_IDX, idx4 = BAD_IDX; // The idea is to read chunks in case there are multiple keys or // paramters in a BufferedTransformation. So we use CopyTo to // extract what we are interested in. We don't take anything // out of the BufferedTransformation (yet). // We also use indexes because the iterator will be invalidated // when we append to the ByteQueue. Even though the iterator // is invalid, `accum.begin() + index` will be valid. // Reading 8 or 10 lines at a time is an optimization from testing // against cacerts.pem. The file has 153 certs, so its a good test. // +2 to allow for CR + LF line endings. There's no guarantee a line // will be present, or it will be RFC1421_LINE_BREAK in size. static const size_t READ_SIZE = (RFC1421_LINE_BREAK + 1) * 10; static const size_t REWIND = max(SBB_PEM_BEGIN.size(), SBB_PEM_END.size()) + 2; SecByteBlock accum; size_t idx = 0, next = 0; size_t available = src.MaxRetrievable(); while(available) { // How much can we read? const size_t size = std::min(available, READ_SIZE); // Ideally, we would only scan the line we are reading. However, // we need to rewind a bit in case a token spans the previous // block and the block we are reading. But we can't rewind // into a previous index. Once we find an index, the variable // next is set to it. Hence the reason for the max() if(idx > REWIND) { const size_t x = idx - REWIND; next = max(next, x); } #if 0 // Next should be less than index by 10 or so std::cout << " Index: " << idx << std::endl; std::cout << " Next: " << next << std::endl; #endif // We need a temp queue to use CopyRangeTo. We have to use it // because there's no Peek that allows us to peek a range. ByteQueue tq; src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(size)); const size_t offset = accum.size(); accum.Grow(offset + size); tq.Get(accum.data() + offset, size); // Adjust sizes idx += size; available -= size; // Locate '-----BEGIN' if(idx1 == BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_BEGIN.begin(), SBB_PEM_BEGIN.end()); if(it == accum.end()) continue; idx1 = it - accum.begin(); next = idx1 + SBB_PEM_BEGIN.size(); } // Locate '-----' if(idx2 == BAD_IDX && idx1 != BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_TAIL.begin(), SBB_PEM_TAIL.end()); if(it == accum.end()) continue; idx2 = it - accum.begin(); next = idx2 + SBB_PEM_TAIL.size(); } // Locate '-----END' if(idx3 == BAD_IDX && idx2 != BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_END.begin(), SBB_PEM_END.end()); if(it == accum.end()) continue; idx3 = it - accum.begin(); next = idx3 + SBB_PEM_END.size(); } // Locate '-----' if(idx4 == BAD_IDX && idx3 != BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_TAIL.begin(), SBB_PEM_TAIL.end()); if(it == accum.end()) continue; idx4 = it - accum.begin(); next = idx4 + SBB_PEM_TAIL.size(); } } // Did we find `-----BEGIN XXX-----` (RFC 1421 calls this pre-encapsulated boundary)? if(idx1 == BAD_IDX || idx2 == BAD_IDX) throw InvalidDataFormat("PEM_NextObject: could not locate boundary header"); // Did we find `-----END XXX-----` (RFC 1421 calls this post-encapsulated boundary)? if(idx3 == BAD_IDX || idx4 == BAD_IDX) throw InvalidDataFormat("PEM_NextObject: could not locate boundary footer"); // *IF* the trailing '-----' occurred in the last 5 bytes in accum, then we might miss the // End of Line. We need to peek 2 more bytes if available and append them to accum. if(available >= 2) { ByteQueue tq; src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(2)); const size_t offset = accum.size(); accum.Grow(offset + 2); tq.Get(accum.data() + offset, 2); } else if(available == 1) { ByteQueue tq; src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(1)); const size_t offset = accum.size(); accum.Grow(offset + 1); tq.Get(accum.data() + offset, 1); } // Final book keeping const byte* ptr = accum.begin() + idx1; const size_t used = idx4 + SBB_PEM_TAIL.size(); const size_t len = used - idx1; // Include one CR/LF if its available in the accumulator next = idx1 + len; size_t adjust = 0; if(next < accum.size()) { byte c1 = accum[next]; byte c2 = 0; if(next + 1 < accum.size()) c2 = accum[next + 1]; // Longest match first if(c1 == '\r' && c2 == '\n') adjust = 2; else if(c1 == '\r' || c1 == '\n') adjust = 1; } dest.Put(ptr, len + adjust); dest.MessageEnd(); src.Skip(used + adjust); if(trimTrailing) { while (src.AnyRetrievable()) { byte b; src.Peek(b); if(!isspace(b)) break; src.Skip(1); } } }
void CAuthenticationProfileImpl::onBufferReceived(const iviLink::Channel::tChannelId channel, Buffer const& buffer) { LOG4CPLUS_TRACE_METHOD(msLogger, __PRETTY_FUNCTION__); LOG4CPLUS_TRACE(msLogger, "CBuffer write position = "+convertIntegerToString(buffer.getWritePosition()) + "; CBuffer size = " + convertIntegerToString(buffer.getSize()) + "; Channel = "+ convertIntegerToString(channel)); assert(this); UInt8 *incomingData = buffer.getBuffer(); int read_size = buffer.getSize(); LOG4CPLUS_INFO(msLogger, "Procedure ID = " + convertIntegerToString(incomingData[0])); if(incomingData[0] == SEND_ENCRYPTED_PIN) { LOG4CPLUS_INFO(msLogger, "Encrypted PIN received"); string encryptedPIN((char*)(incomingData + 1), read_size - 1); LOG4CPLUS_INFO(msLogger, "Engrypted PIN length = " + convertIntegerToString(encryptedPIN.length())); LOG4CPLUS_INFO(msLogger, "Encrypted PIN = " + encryptedPIN); string decryptedRemotePIN = CRSAEncryptDecrypt::decrypt(encryptedPIN, CRSAEncryptDecrypt::getPrivateKey(mpAppCallbacks->getInternalPath())); LOG4CPLUS_INFO(msLogger, "Decrypted remote PIN = " + decryptedRemotePIN); mpAppCallbacks->gotPIN(decryptedRemotePIN[0] - '0', decryptedRemotePIN[1] - '0', decryptedRemotePIN[2] - '0', decryptedRemotePIN[3] - '0'); } else if(incomingData[0] == SEND_PUBLIC_KEY) { LOG4CPLUS_INFO(msLogger, "PublicKey received"); UInt8* keyBytes = new UInt8[read_size - 1]; memcpy(keyBytes, incomingData + 1, read_size - 1); ByteQueue queue; queue.Put(keyBytes, read_size - 1); remoteHostPublicKey.Load(queue); } else if(incomingData[0] == SEND_UID) { LOG4CPLUS_INFO(msLogger, "Remote UID received"); string uid((char*)(incomingData + 1), read_size - 1); LOG4CPLUS_INFO(msLogger, "UID = " + uid); mRemoteUID = iviLink::BaseUid(uid); if(mpTrustList->isKnownUid(mRemoteUID)) { LOG4CPLUS_INFO(msLogger, "Remote UID is known"); remoteUIDIsChecked = true; remoteUIDIsOK = true; sendYourUIDIsKnow(); validateUIDs(); } else { LOG4CPLUS_INFO(msLogger, "Remote UID is unknown"); remoteUIDIsChecked = true; remoteUIDIsOK = false; sendYourUIDIsUnknown(); validateUIDs(); } } else if(incomingData[0] == YOUR_UID_IS_OK) { localUIDIsChecked = true; localUIDIsOK = true; validateUIDs(); } else if(incomingData[0] == YOUR_UID_IS_NOK) { localUIDIsChecked = true; localUIDIsOK = false; validateUIDs(); } else if(incomingData[0] == READY_TO_EXIT) { mpAppCallbacks->onReadyToExit(); } }
Block SecTpmFile::signInTpm(const uint8_t* data, size_t dataLength, const Name& keyName, DigestAlgorithm digestAlgorithm) { string keyURI = keyName.toUri(); if (!doesKeyExistInTpm(keyName, KeyClass::PRIVATE)) BOOST_THROW_EXCEPTION(Error("private key doesn't exist")); try { using namespace CryptoPP; AutoSeededRandomPool rng; // Read public key shared_ptr<v1::PublicKey> pubkeyPtr; pubkeyPtr = getPublicKeyFromTpm(keyName); switch (pubkeyPtr->getKeyType()) { case KeyType::RSA: { // Read private key ByteQueue bytes; FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(), true, new Base64Decoder); file.TransferTo(bytes); bytes.MessageEnd(); RSA::PrivateKey privateKey; privateKey.Load(bytes); // Sign message switch (digestAlgorithm) { case DigestAlgorithm::SHA256: { RSASS<PKCS1v15, SHA256>::Signer signer(privateKey); OBufferStream os; StringSource(data, dataLength, true, new SignerFilter(rng, signer, new FileSink(os))); return Block(tlv::SignatureValue, os.buf()); } default: BOOST_THROW_EXCEPTION(Error("Unsupported digest algorithm")); } } case KeyType::EC: { // Read private key ByteQueue bytes; FileSource file(m_impl->transformName(keyURI, ".pri").string().c_str(), true, new Base64Decoder); file.TransferTo(bytes); bytes.MessageEnd(); // Sign message switch (digestAlgorithm) { case DigestAlgorithm::SHA256: { ECDSA<ECP, SHA256>::PrivateKey privateKey; privateKey.Load(bytes); ECDSA<ECP, SHA256>::Signer signer(privateKey); OBufferStream os; StringSource(data, dataLength, true, new SignerFilter(rng, signer, new FileSink(os))); uint8_t buf[200]; size_t bufSize = DSAConvertSignatureFormat(buf, sizeof(buf), DSA_DER, os.buf()->buf(), os.buf()->size(), DSA_P1363); shared_ptr<Buffer> sigBuffer = make_shared<Buffer>(buf, bufSize); return Block(tlv::SignatureValue, sigBuffer); } default: BOOST_THROW_EXCEPTION(Error("Unsupported digest algorithm")); } } default: BOOST_THROW_EXCEPTION(Error("Unsupported key type")); } } catch (const CryptoPP::Exception& e) { BOOST_THROW_EXCEPTION(Error(e.what())); } }
bool RSAValidate() { cout << "\nRSA validation suite running...\n\n"; byte out[100], outPlain[100]; unsigned int outLen; bool pass = true, fail; try { { char *plain = "Everyone gets Friday off."; byte *signature = (byte *) "\x05\xfa\x6a\x81\x2f\xc7\xdf\x8b\xf4\xf2\x54\x25\x09\xe0\x3e\x84" "\x6e\x11\xb9\xc6\x20\xbe\x20\x09\xef\xb4\x40\xef\xbc\xc6\x69\x21" "\x69\x94\xac\x04\xf3\x41\xb5\x7d\x05\x20\x2d\x42\x8f\xb2\xa2\x7b" "\x5c\x77\xdf\xd9\xb1\x5b\xfc\x3d\x55\x93\x53\x50\x34\x10\xc1\xe1"; LC_RNG rng(765); FileSource keys("rsa512a.dat", true, new HexDecoder); RSASSA_PKCS1v15_MD2_Signer rsaPriv(keys); RSASSA_PKCS1v15_MD2_Verifier rsaPub(rsaPriv); rsaPriv.SignMessage(rng, (byte *)plain, strlen(plain), out); fail = memcmp(signature, out, 64) != 0; pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "signature check against test vector\n"; fail = !rsaPub.VerifyMessage((byte *)plain, strlen(plain), out); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "verification check against test vector\n"; out[10]++; fail = rsaPub.VerifyMessage((byte *)plain, strlen(plain), out); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "invalid signature verification\n"; } { FileSource keys("rsa512.dat", true, new HexDecoder); RSAES_PKCS1v15_Decryptor rsaPriv(keys); RSAES_PKCS1v15_Encryptor rsaPub(rsaPriv); pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass; } { byte *plain = (byte *) "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; byte *encrypted = (byte *) "\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a" "\x8b\x40\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4" "\x17\x53\x03\x29\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52" "\x62\x51"; byte *oaepSeed = (byte *) "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2" "\xf0\x6c\xb5\x8f"; ByteQueue bq; bq.Put(oaepSeed, 20); FixedRNG rng(bq); FileSource privFile("rsa400pv.dat", true, new HexDecoder); FileSource pubFile("rsa400pb.dat", true, new HexDecoder); RSAES_OAEP_SHA_Decryptor rsaPriv(privFile); RSAES_OAEP_SHA_Encryptor rsaPub(pubFile); memset(out, 0, 50); memset(outPlain, 0, 8); rsaPub.Encrypt(rng, plain, 8, out); outLen = rsaPriv.Decrypt(encrypted, outPlain); fail = (outLen!=8) || memcmp(out, encrypted, 50) || memcmp(plain, outPlain, 8); pass = pass && !fail; cout << (fail ? "FAILED " : "passed "); cout << "PKCS 2.0 encryption and decryption\n"; } } catch (BERDecodeErr) { cout << "FAILED Error decoding RSA key\n"; pass = false; } return pass; }
bool Validator::verifySignature(const uint8_t* buf, const size_t size, const Signature& sig, const v1::PublicKey& key) { try { using namespace CryptoPP; switch (sig.getType()) { case tlv::SignatureSha256WithRsa: { if (key.getKeyType() != KeyType::RSA) return false; RSA::PublicKey publicKey; ByteQueue queue; queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size()); publicKey.Load(queue); RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey); return verifier.VerifyMessage(buf, size, sig.getValue().value(), sig.getValue().value_size()); } case tlv::SignatureSha256WithEcdsa: { if (key.getKeyType() != KeyType::EC) return false; ECDSA<ECP, SHA256>::PublicKey publicKey; ByteQueue queue; queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size()); publicKey.Load(queue); ECDSA<ECP, SHA256>::Verifier verifier(publicKey); uint32_t length = 0; StringSource src(key.get().buf(), key.get().size(), true); BERSequenceDecoder subjectPublicKeyInfo(src); { BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo); { Oid algorithm; algorithm.decode(algorithmInfo); Oid curveId; curveId.decode(algorithmInfo); if (curveId == SECP256R1) length = 256; else if (curveId == SECP384R1) length = 384; else return false; } } switch (length) { case 256: { uint8_t buffer[64]; size_t usedSize = DSAConvertSignatureFormat(buffer, sizeof(buffer), DSA_P1363, sig.getValue().value(), sig.getValue().value_size(), DSA_DER); return verifier.VerifyMessage(buf, size, buffer, usedSize); } case 384: { uint8_t buffer[96]; size_t usedSize = DSAConvertSignatureFormat(buffer, sizeof(buffer), DSA_P1363, sig.getValue().value(), sig.getValue().value_size(), DSA_DER); return verifier.VerifyMessage(buf, size, buffer, usedSize); } default: return false; } } default: // Unsupported sig type return false; } } catch (const CryptoPP::Exception& e) { return false; } }