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; }
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; } }