ConstBufferPtr BackEndMem::doExportKey(const Name& keyName, const char* pw, size_t pwLen) { OBufferStream os; m_impl->keys[keyName]->savePkcs8(os, pw, pwLen); return os.buf(); }
ConstBufferPtr SecTpmFile::exportPrivateKeyPkcs8FromTpm(const Name& keyName) { OBufferStream privateKeyOs; CryptoPP::FileSource(m_impl->transformName(keyName.toUri(), ".pri").string().c_str(), true, new CryptoPP::Base64Decoder(new CryptoPP::FileSink(privateKeyOs))); return privateKeyOs.buf(); }
void Block::encode() { if (hasWire()) return; OBufferStream os; Tlv::writeVarNumber(os, type()); if (hasValue()) { Tlv::writeVarNumber(os, value_size()); os.write(reinterpret_cast<const char*>(value()), value_size()); } else if (m_subBlocks.size() == 0) { Tlv::writeVarNumber(os, 0); } else { size_t valueSize = 0; for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) { valueSize += i->size(); } Tlv::writeVarNumber(os, valueSize); for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) { if (i->hasWire()) os.write(reinterpret_cast<const char*>(i->wire()), i->size()); else if (i->hasValue()) { Tlv::writeVarNumber(os, i->type()); Tlv::writeVarNumber(os, i->value_size()); os.write(reinterpret_cast<const char*>(i->value()), i->value_size()); } else throw Error("Underlying value buffer is empty"); } } // now assign correct block m_buffer = os.buf(); m_begin = m_buffer->begin(); m_end = m_buffer->end(); m_size = m_end - m_begin; m_value_begin = m_buffer->begin(); m_value_end = m_buffer->end(); Tlv::readType(m_value_begin, m_value_end); Tlv::readVarNumber(m_value_begin, m_value_end); }
ConstBufferPtr BackEndFile::doExportKey(const Name& keyName, const char* pw, size_t pwLen) { shared_ptr<PrivateKey> key; try { key = loadKey(keyName); } catch (const PrivateKey::Error&) { BOOST_THROW_EXCEPTION(Error("Cannot export private key")); } OBufferStream os; key->savePkcs8(os, pw, pwLen); return os.buf(); }
shared_ptr<T> load(std::istream& is, IoEncoding encoding = BASE_64) { typedef typename T::Error TypeError; try { using namespace CryptoPP; shared_ptr<T> object = make_shared<T>(); OBufferStream os; switch (encoding) { case NO_ENCODING: { FileSource ss(is, true, new FileSink(os)); break; } case BASE_64: { FileSource ss(is, true, new Base64Decoder(new FileSink(os))); break; } case HEX: { FileSource ss(is, true, new HexDecoder(new FileSink(os))); break; } default: return shared_ptr<T>(); } object->wireDecode(Block(os.buf())); return object; } catch (CryptoPP::Exception& e) { return shared_ptr<T>(); } catch (Tlv::Error& e) { return shared_ptr<T>(); } catch (TypeError& e) { return shared_ptr<T>(); } }
void SegmentFetcher::finalizeFetch() { // Combine segments into final buffer OBufferStream buf; // We may have received more segments than exist in the object. BOOST_ASSERT(m_receivedSegments.size() >= static_cast<uint64_t>(m_nSegments)); for (int64_t i = 0; i < m_nSegments; i++) { buf.write(m_receivedSegments[i].get<const char>(), m_receivedSegments[i].size()); } onComplete(buf.buf()); stop(); }
shared_ptr<const Buffer> fromHex(const std::string& hexString) { if (hexString.size() % 2 != 0) { BOOST_THROW_EXCEPTION(StringHelperError("Invalid number of characters in the supplied hex " "string")); } using namespace CryptoPP; OBufferStream os; StringSource(hexString, true, new HexDecoder(new FileSink(os))); shared_ptr<const Buffer> buffer = os.buf(); if (buffer->size() * 2 != hexString.size()) { BOOST_THROW_EXCEPTION(StringHelperError("The supplied hex string contains non-hex characters")); } return buffer; }
ConstBufferPtr SecTpm::exportPrivateKeyPkcs5FromTpm(const Name& keyName, const std::string& passwordStr) { using namespace CryptoPP; uint8_t salt[8] = {0}; uint8_t iv[8] = {0}; // derive key if (!generateRandomBlock(salt, 8) || !generateRandomBlock(iv, 8)) BOOST_THROW_EXCEPTION(Error("Cannot generate salt or iv")); uint32_t iterationCount = 2048; PKCS5_PBKDF2_HMAC<SHA1> keyGenerator; size_t derivedLen = 24; // For DES-EDE3-CBC-PAD byte derived[24] = {0}; byte purpose = 0; try { keyGenerator.DeriveKey(derived, derivedLen, purpose, reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(), salt, 8, iterationCount); } catch (const CryptoPP::Exception& e) { BOOST_THROW_EXCEPTION(Error("Cannot derived the encryption key")); } // encrypt CBC_Mode< DES_EDE3 >::Encryption e; e.SetKeyWithIV(derived, derivedLen, iv); ConstBufferPtr pkcs8PrivateKey = exportPrivateKeyPkcs8FromTpm(keyName); if (pkcs8PrivateKey == nullptr) BOOST_THROW_EXCEPTION(Error("Cannot export the private key, #1")); OBufferStream encryptedOs; try { StringSource stringSource(pkcs8PrivateKey->buf(), pkcs8PrivateKey->size(), true, new StreamTransformationFilter(e, new FileSink(encryptedOs))); } catch (const CryptoPP::Exception& e) { BOOST_THROW_EXCEPTION(Error("Cannot export the private key, #2")); } // encode Oid pbes2Id("1.2.840.113549.1.5.13"); Oid pbkdf2Id("1.2.840.113549.1.5.12"); Oid pbes2encsId("1.2.840.113549.3.7"); OBufferStream pkcs8Os; try { FileSink sink(pkcs8Os); // EncryptedPrivateKeyInfo ::= SEQUENCE { // encryptionAlgorithm EncryptionAlgorithmIdentifier, // encryptedData OCTET STRING } DERSequenceEncoder encryptedPrivateKeyInfo(sink); { // EncryptionAlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{PBES2-id}}, // parameters SEQUENCE {{PBES2-params}} } DERSequenceEncoder encryptionAlgorithm(encryptedPrivateKeyInfo); { pbes2Id.encode(encryptionAlgorithm); // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } DERSequenceEncoder pbes2Params(encryptionAlgorithm); { // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{PBKDF2-id}}, // parameters SEQUENCE {{PBKDF2-params}} } DERSequenceEncoder pbes2KDFs(pbes2Params); { pbkdf2Id.encode(pbes2KDFs); // AlgorithmIdentifier ::= SEQUENCE { // salt OCTET STRING, // iterationCount INTEGER (1..MAX), // keyLength INTEGER (1..MAX) OPTIONAL, // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 } DERSequenceEncoder pbkdf2Params(pbes2KDFs); { DEREncodeOctetString(pbkdf2Params, salt, 8); DEREncodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER); } pbkdf2Params.MessageEnd(); } pbes2KDFs.MessageEnd(); // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}}, // parameters OCTET STRING} {{iv}} } DERSequenceEncoder pbes2Encs(pbes2Params); { pbes2encsId.encode(pbes2Encs); DEREncodeOctetString(pbes2Encs, iv, 8); } pbes2Encs.MessageEnd(); } pbes2Params.MessageEnd(); } encryptionAlgorithm.MessageEnd(); DEREncodeOctetString(encryptedPrivateKeyInfo, encryptedOs.buf()->buf(), encryptedOs.buf()->size()); } encryptedPrivateKeyInfo.MessageEnd(); return pkcs8Os.buf(); } catch (const CryptoPP::Exception& e) { BOOST_THROW_EXCEPTION(Error("Cannot export the private key, #3")); } }
bool SecTpm::importPrivateKeyPkcs5IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, const std::string& passwordStr) { using namespace CryptoPP; Oid pbes2Id; Oid pbkdf2Id; SecByteBlock saltBlock; uint32_t iterationCount; Oid pbes2encsId; SecByteBlock ivBlock; SecByteBlock encryptedDataBlock; try { // decode some decoding processes are not necessary for now, // because we assume only one encryption scheme. StringSource source(buf, size, true); // EncryptedPrivateKeyInfo ::= SEQUENCE { // encryptionAlgorithm EncryptionAlgorithmIdentifier, // encryptedData OCTET STRING } BERSequenceDecoder encryptedPrivateKeyInfo(source); { // EncryptionAlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{PBES2-id}}, // parameters SEQUENCE {{PBES2-params}} } BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo); { pbes2Id.decode(encryptionAlgorithm); // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } BERSequenceDecoder pbes2Params(encryptionAlgorithm); { // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{PBKDF2-id}}, // parameters SEQUENCE {{PBKDF2-params}} } BERSequenceDecoder pbes2KDFs(pbes2Params); { pbkdf2Id.decode(pbes2KDFs); // AlgorithmIdentifier ::= SEQUENCE { // salt OCTET STRING, // iterationCount INTEGER (1..MAX), // keyLength INTEGER (1..MAX) OPTIONAL, // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 } BERSequenceDecoder pbkdf2Params(pbes2KDFs); { BERDecodeOctetString(pbkdf2Params, saltBlock); BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER); } pbkdf2Params.MessageEnd(); } pbes2KDFs.MessageEnd(); // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}}, // parameters OCTET STRING} {{iv}} } BERSequenceDecoder pbes2Encs(pbes2Params); { pbes2encsId.decode(pbes2Encs); BERDecodeOctetString(pbes2Encs, ivBlock); } pbes2Encs.MessageEnd(); } pbes2Params.MessageEnd(); } encryptionAlgorithm.MessageEnd(); BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock); } encryptedPrivateKeyInfo.MessageEnd(); } catch (const CryptoPP::Exception& e) { return false; } PKCS5_PBKDF2_HMAC<SHA1> keyGenerator; size_t derivedLen = 24; //For DES-EDE3-CBC-PAD byte derived[24] = {0}; byte purpose = 0; try { keyGenerator.DeriveKey(derived, derivedLen, purpose, reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(), saltBlock.BytePtr(), saltBlock.size(), iterationCount); } catch (const CryptoPP::Exception& e) { return false; } //decrypt CBC_Mode< DES_EDE3 >::Decryption d; d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr()); OBufferStream privateKeyOs; try { StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true, new StreamTransformationFilter(d, new FileSink(privateKeyOs))); } catch (const CryptoPP::Exception& e) { return false; } if (!importPrivateKeyPkcs8IntoTpm(keyName, privateKeyOs.buf()->buf(), privateKeyOs.buf()->size())) return false; // determine key type StringSource privateKeySource(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size(), true); KeyType publicKeyType = KeyType::NONE; SecByteBlock rawKeyBits; // PrivateKeyInfo ::= SEQUENCE { // INTEGER, // SEQUENCE, // OCTECT STRING} BERSequenceDecoder privateKeyInfo(privateKeySource); { uint32_t versionNum; BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER); BERSequenceDecoder sequenceDecoder(privateKeyInfo); { Oid keyTypeOid; keyTypeOid.decode(sequenceDecoder); if (keyTypeOid == oid::RSA) publicKeyType = KeyType::RSA; else if (keyTypeOid == oid::ECDSA) publicKeyType = KeyType::EC; else return false; // Unsupported key type; } } // derive public key OBufferStream publicKeyOs; try { switch (publicKeyType) { case KeyType::RSA: { RSA::PrivateKey privateKey; privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref()); RSAFunction publicKey(privateKey); FileSink publicKeySink(publicKeyOs); publicKey.DEREncode(publicKeySink); publicKeySink.MessageEnd(); break; } case KeyType::EC: { ECDSA<ECP, SHA256>::PrivateKey privateKey; privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref()); ECDSA<ECP, SHA256>::PublicKey publicKey; privateKey.MakePublicKey(publicKey); publicKey.AccessGroupParameters().SetEncodeAsOID(true); FileSink publicKeySink(publicKeyOs); publicKey.DEREncode(publicKeySink); publicKeySink.MessageEnd(); break; } default: return false; } } catch (const CryptoPP::Exception& e) { return false; } if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size())) return false; return true; }
void Certificate::encode() { // Name // <key_name>/ID-CERT/<id#> // Content // DER encoded idCert: // // idCert ::= SEQUENCE { // validity Validity, // subject Name, // subjectPubKeyInfo SubjectPublicKeyInfo, // extension Extensions OPTIONAL } // // Validity ::= SEQUENCE { // notBefore Time, // notAfter Time } // // Name ::= CHOICE { // RDNSequence } // // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName // // RelativeDistinguishedName ::= // SET OF AttributeTypeAndValue // // SubjectPublicKeyInfo ::= SEQUENCE { // algorithm AlgorithmIdentifier // keybits BIT STRING } // // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension // // (see http://www.ietf.org/rfc/rfc3280.txt for more detail) // // KeyLocator // issuer’s certificate name // Signature using namespace CryptoPP; OBufferStream os; CryptoPP::FileSink sink(os); // idCert ::= SEQUENCE { // validity Validity, // subject Name, // subjectPubKeyInfo SubjectPublicKeyInfo, // extension Extensions OPTIONAL } DERSequenceEncoder idCert(sink); { // Validity ::= SEQUENCE { // notBefore Time, // notAfter Time } DERSequenceEncoder validity(idCert); { DEREncodeGeneralTime(validity, m_notBefore); DEREncodeGeneralTime(validity, m_notAfter); } validity.MessageEnd(); // Name ::= CHOICE { // RDNSequence } // // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName DERSequenceEncoder name(idCert); { for (SubjectDescriptionList::iterator it = m_subjectDescriptionList.begin(); it != m_subjectDescriptionList.end(); ++it) { it->encode(name); } } name.MessageEnd(); // SubjectPublicKeyInfo m_key.encode(idCert); // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension // // Extension ::= SEQUENCE { // extnID OBJECT IDENTIFIER, // critical BOOLEAN DEFAULT FALSE, // extnValue OCTET STRING } if (!m_extensionList.empty()) { DERSequenceEncoder extensions(idCert); { for (ExtensionList::iterator it = m_extensionList.begin(); it != m_extensionList.end(); ++it) { it->encode(extensions); } } extensions.MessageEnd(); } } idCert.MessageEnd(); setContent(os.buf()); setContentType(tlv::ContentType_Key); }
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())); } }